Gerador de tokens
Gera segredos a partir do gerador criptográfico do navegador — hex, base64url ou um alfabeto seu, e frases secretas da EFF — com entropia em bits.
192,0 bitsTempo médio até o encontrar, a três velocidades de adivinha. A distância entre elas é maior do que qualquer diferença que o próprio segredo faça.
- Contra um início de sessão com limite de tentativas — 10/s
10^49 anos - Contra uma hash lenta divulgada (bcrypt, argon2) — 10⁴/s
10^46 anos - Contra uma hash rápida divulgada (SHA-256, MD5) — 10¹²/s
10^38 anos
Retirado de 64 caracteres, portanto cada um leva 6,00 bits.
O que esta ferramenta faz
Produz segredos: valores cuja única defesa é ninguém os conseguir adivinhar. Escolha um alfabeto e um comprimento para uma chave de API ou uma senha de banco de dados, ou passe a uma frase secreta retirada de uma lista publicada para algo que uma pessoa tenha de escrever. Cada resultado é gerado no seu navegador e mostrado com o único número que descreve a sua força com honestidade.
É um trabalho diferente do gerador de UUID deste site. Um UUID tem de ser único, para que dois registros nunca colidam; um segredo tem de ser inadivinhável, o que é uma exigência mais forte e uma falha diferente. Um identificador previsível é inofensivo. Um segredo previsível é uma porta aberta.
De onde vem a aleatoriedade
Tudo aqui é retirado de crypto.getRandomValues, o gerador de aleatoriedade criptograficamente seguro do navegador, alimentado a partir da reserva de entropia do sistema operacional — a mesma fonte que o openssl rand e o /dev/urandom usam.
A alternativa, Math.random, não é uma função de segurança e nunca o pretendeu ser. É um gerador pseudoaleatório rápido com um estado interno pequeno, e em todos os motores atuais esse estado pode ser recuperado a partir de uma série curta de saídas, após o que todos os valores passados e futuros são conhecidos. Um token construído com ele parece exatamente tão aleatório como um verdadeiro; a diferença só aparece quando alguém se dá ao trabalho de olhar.
É legítimo perguntar se uma página web é sequer o lugar certo para gerar um segredo de produção. A geração em si é sólida: é o CSPRNG da plataforma, a página é estática e nada é transmitido. O que merece reflexão é o que a rodeia — um segredo que passa pela área de transferência pode ser legível por outras aplicações, e um colado num terminal costuma acabar no histórico da shell. São as mesmas considerações de qualquer outro método.
O enviesamento escondido na implementação óbvia
Transformar bytes aleatórios em caracteres parece uma linha só: pegar um byte, tirar-lhe o resto da divisão pelo tamanho do alfabeto e indexar. É sutilmente errado para todo o alfabeto cujo tamanho não divida 256 de forma exata, e a saída não dá disso sinal nenhum.
Com 62 caracteres alfanuméricos, a divisão não é exata: 62 cabe em 256 quatro vezes e sobram 8. Esses 8 valores de byte que sobram — de 248 a 255 — dobram-se sobre os primeiros 8 caracteres do alfabeto, portanto cada um deles recebe cinco hipóteses em 256 enquanto os restantes recebem quatro. Os primeiros oito caracteres ficam cerca de 25% mais prováveis do que os outros.
A correção é a amostragem com rejeição: descartar uma extração que caia na cauda que sobra e extrair de novo, em vez de a dobrar para dentro. Custa cerca de uma extração extra em cada trinta e duas para um alfabeto de 62 caracteres e nada de nada para hex ou base64url, cujos tamanhos são potências de dois e que por isso não têm cauda. Esta ferramenta rejeita; o efeito não se vê em nenhum token isolado, que é precisamente por isso que vale a pena dizê-lo.
A entropia, que é a única medida honesta
A entropia em bits diz quão grande é o espaço de segredos igualmente prováveis: n bits significam 2^n possibilidades. É aditiva e fácil de comparar, e não diz nada sobre a rapidez com que alguém consegue percorrer esse espaço — o que é uma virtude, porque essa parte depende de coisas que um gerador não pode saber.
A aritmética é deliberadamente simples. Cada caractere contribui com log2(tamanho do alfabeto) bits, e cada palavra com log2(tamanho da lista), portanto:
- Um caractere hex são 4 bits, portanto um token hex de 32 caracteres são exatamente 128 bits: uma chave AES-128 escrita por extenso.
- Um caractere base64url são 6 bits, portanto 22 caracteres passam dos 128 bits e 43 passam dos 256.
- Um caractere alfanumérico são cerca de 5,95 bits; excluir os parecidos baixa o alfabeto para 58 e o caractere para 5,86, o que custa aproximadamente um caractere de comprimento em cada sessenta.
- Uma palavra da lista longa da EFF são 12,925 bits, porque a lista tem 7776 entradas, que são 6^5: cinco lançamentos de dado.
- Uma palavra da lista curta da EFF são 10,34 bits, de 1296 entradas, que são 6^4.
Um alvo habitual são 128 bits, que é onde a força bruta deixa de ser uma estratégia em vez de ser apenas cara. São 32 caracteres hex, 22 caracteres base64url, ou 10 palavras da lista longa da EFF.
Por que não há um único «tempo até ser quebrado»
Um segredo não tem tempo de quebra. Tem-no o par formado pelo segredo e por aquilo que o guarda, e o guarda pesa muito mais do que o segredo. O mesmo valor que demoraria mais do que a idade do universo a ser encontrado através de um formulário de acesso cai numa tarde se tiver sido armazenado como um SHA-256 sem sal e o banco de dados tiver sido divulgado.
Por isso mostram-se três velocidades em vez de um número, e cada uma vem com o seu nome:
- Dez tentativas por segundo, contra um início de sessão que limita a taxa. É o tecto realista para quem tenha de passar pelo seu serviço.
- Dez mil tentativas por segundo, contra uma hash de senhas divulgada e construída para ser lenta — bcrypt com um custo moderno, ou argon2. Essa lentidão é toda a razão de ser dessas funções.
- Um trilhão de tentativas por segundo, contra uma hash divulgada que nunca foi pensada para senhas. O SHA-256 e o MD5 são desenhados para serem rápidos, e um conjunto de GPU é rapidíssimo.
As velocidades estão arredondadas a potências de dez de propósito. Algo mais preciso sugeriria a medição de um atacante em concreto, quando a informação útil são as onze ordens de grandeza entre a primeira linha e a última. Se um segredo estiver à vontade nas três, a questão fica resolvida sem precisar dos números exatos.
Cada número é a média, que é metade do espaço e não a totalidade — uma procura encontra a resposta a meio caminho, em média. E passado o milhão de anos a resposta é dada como ordem de grandeza, porque «quatrocentos trilhões de anos» não é uma duração que alguém consiga comparar. O universo tem cerca de 10^10 anos, o que dá uma referência útil para as linhas que chegam tão longe.
As frases secretas, e de onde vem realmente a sua força
Uma frase secreta é forte por uma única razão: várias palavras foram escolhidas ao acaso de uma lista grande. Não é forte por ser comprida, nem por parecer linguagem. Seis palavras ao acaso de uma lista de 7776 são cerca de 77 bits; seis palavras em que uma pessoa pensou valem muito menos, porque as pessoas não escolhem de forma uniforme e um atacante sabe sobre as expressões comuns exatamente o mesmo que você.
As duas listas aqui vêm da EFF e são as listas diceware publicadas, baixadas sem alterações. Não são listas montadas aqui, e isso importa: uma lista de palavras que alguém inventou tem tamanho desconhecido, sobreposição desconhecida com outras listas e nenhuma maneira de verificar a entropia que lhe é atribuída.
- A lista longa tem 7776 palavras, uma por cada lançamento de cinco dados, e dá 12,925 bits por palavra.
- A lista curta tem 1296 palavras, uma por cada lançamento de quatro dados, e dá 10,34 bits por palavra. As suas palavras são mais curtas — nenhuma passa das cinco letras — o que facilita escrevê-las à custa de precisar de mais palavras para a mesma força.
Uma palavra repetida numa frase secreta não é um defeito e aqui não é retirada de novo. Cada extração é independente, portanto qualquer par concreto de palavras é exatamente tão provável como outro; recusar repetições encolheria o espaço de frases possíveis e as tornaria um pouco mais fracas, não mais fortes.
Ambas as listas da EFF contêm um punhado de entradas com hífen: t-shirt, yo-yo, drop-down, felt-tip. Se o separador também for um hífen, uma frase que contenha uma delas não pode voltar a ser dividida nas suas palavras sem ambiguidade. É um problema de apresentação e não de segurança, e escolher um espaço ou um ponto como separador evita-o por completo.
As opções que custam entropia, e a que não custa
Excluir os caracteres parecidos troca força por legibilidade, e a troca está à vista. Retirar 0, O, I e l leva o alfabeto alfanumérico de 62 para 58 caracteres — que é, exatamente, o alfabeto base58 que o Bitcoin usa, e pela mesma razão. Cada caractere desce de 5,95 para 5,86 bits, portanto um token precisa de cerca de um caractere a mais em cada sessenta para continuar igualmente forte. Costuma valer a pena para tudo o que uma pessoa vá ler na tela e escrever em outro lugar.
A opção só é oferecida onde significa alguma coisa. O hex e o base64url são codificações, não conjuntos de caracteres: os seus alfabetos são fixados por uma especificação, e um hex sem 0 já não é hex — nada seria capaz de o decodificar.
Pôr maiúscula em cada palavra de uma frase secreta não acrescenta absolutamente nada, e o número da força aqui deliberadamente não se mexe quando a liga. É a mesma transformação aplicada sempre, portanto não cria uma única possibilidade nova: um atacante que saiba que a frase leva maiúsculas está exatamente onde começou. A opção existe porque há campos de senha que continuam exigindo uma maiúscula, não porque ajude.
Escolher o comprimento
Para tudo o que uma máquina trate — chaves de API, tokens de sessão, segredos de webhook, senhas de banco de dados — não há razão para poupar. 32 caracteres hex ou 22 base64url dão 128 bits, e ir mais além só custa bytes num arquivo de configuração.
Para tudo o que uma pessoa escreva, a restrição é outra e uma frase secreta costuma ser a melhor forma. Seis palavras da lista longa são mais fortes do que uma senha aleatória de doze caracteres e muitíssimo mais fáceis de acertar à primeira, o que importa mais do que parece: um segredo que as pessoas escrevem mal é um segredo que as pessoas apontam.
Para um código numérico, a leitura honesta é que quatro algarismos são 13 bits e podem ser esgotados em segundos por qualquer coisa que não limite a taxa. Um PIN só é seguro por causa da política de bloqueio à sua volta, nunca pela sua própria força.
Perguntas frequentes
- Que comprimento deve ter uma chave de API?
- Aponte a 128 bits de entropia ou mais, que é onde a força bruta deixa de ser uma estratégia. São 32 caracteres hex, 22 caracteres base64url, ou 43 caracteres base64url se quiser 256 bits. Para um valor que só o software trata, a opção mais comprida não custa nada.
- Isto é mais seguro do que gerar um segredo com Math.random?
- É, e a diferença não é de grau. O Math.random é um gerador pseudoaleatório com um estado pequeno que os motores atuais permitem recuperar a partir de uma série curta de saídas, após o que todos os valores que produzirá são conhecidos. Esta ferramenta usa crypto.getRandomValues, o CSPRNG da plataforma, que é a mesma fonte de onde o openssl rand bebe.
- Por que não mostram um único «tempo até ser quebrado»?
- Porque esse número não existe. O mesmo segredo é inalcançável atrás de um início de sessão que limita a taxa e cai depressa atrás de uma hash rápida divulgada — onze ordens de grandeza de distância. Um número único tem de escolher um pressuposto e depois escondê-lo, e quem lê recorda o número, não o pressuposto. Três velocidades com nome põem o pressuposto onde se vê.
- As frases secretas são mais fracas do que uma cadeia aleatória?
- Não: a força depende apenas de quantas palavras se retiram de uma lista de que tamanho, e ambas são mostradas. Seis palavras da lista longa da EFF são cerca de 77 bits, mais do que uma senha aleatória de dez caracteres. O que enfraquece uma frase secreta é escolher as palavras por si, coisa que aqui não sucede.
- Devo excluir os caracteres parecidos?
- Se uma pessoa for ler o segredo na tela e escrevê-lo em outro lugar, sim: o custo é pequeno e um token mal lido é um pedido de apoio. Se só o software lhe tocar, não há razão. Retirar 0, O, I e l leva o alfabeto de 62 para 58 caracteres, que é exatamente o alfabeto base58, e custa cerca de um caractere de comprimento em cada sessenta.
- Pôr maiúsculas torna uma frase secreta mais forte?
- Não. É a mesma alteração aplicada sempre, portanto não acrescenta uma única possibilidade ao espaço das frases. O número de entropia fica parado quando a liga, e é esse o comportamento correto. A opção existe porque alguns campos de senha insistem numa maiúscula.
- Alguma coisa do que gero é enviada para um servidor?
- Não. A geração roda inteiramente no seu navegador com o gerador de aleatoriedade da plataforma, nada é carregado nem registrado, e funciona sem conexão à rede. Os tokens não ficam armazenados em lugar nenhum: recarregar a página produz novos e os antigos desaparecem.
Ferramentas relacionadas
- Gerador de dados fictícios
Dados de teste com semente, cujos dígitos de controle e IBAN são mesmo válidos.
- Gerador de códigos QR
Cada decisão da codificação à vista: modo, versão, nível e máscara.
- Gerador de UUID
Versão 4 (aleatória) e versão 7 (ordenada por tempo).