Gerador de tokens

Gera segredos a partir do gerador criptográfico do navegador — hex, base64url ou um alfabeto seu, e frases-passe da EFF — com entropia em bits.

A gerar…
Entropia192.0 bits

Tempo 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/s10^49 anos
  • Contra uma hash lenta divulgada (bcrypt, argon2) — 10⁴/s10^46 anos
  • Contra uma hash rápida divulgada (SHA-256, MD5) — 10¹²/s10^38 anos

Retirado de 64 caracteres, pelo que 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 base de dados, ou passe a uma frase-passe 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 sítio. Um UUID tem de ser único, para que dois registos 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 operativo — 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 sítio 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 num byte, tirar-lhe o resto da divisão pelo tamanho do alfabeto e indexar. É subtilmente 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, pelo que 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 carácter contribui com log2(tamanho do alfabeto) bits, e cada palavra com log2(tamanho da lista), portanto:

  • Um carácter hex são 4 bits, pelo que um token hex de 32 caracteres são exatamente 128 bits: uma chave AES-128 escrita por extenso.
  • Um carácter base64url são 6 bits, pelo que 22 caracteres passam dos 128 bits e 43 passam dos 256.
  • Um carácter alfanumérico são cerca de 5,95 bits; excluir os parecidos baixa o alfabeto para 58 e o carácter para 5,86, o que custa aproximadamente um carácter de comprimento em cada doze.
  • 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 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.

Porque 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 guardado como um SHA-256 sem sal e a base de dados tiver sido divulgada.

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 biliã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 biliõ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-passe, e de onde vem realmente a sua força

Uma frase-passe é 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, descarregadas 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-passe não é um defeito e aqui não é retirada de novo. Cada extração é independente, pelo que qualquer par concreto de palavras é exatamente tão provável como outro; recusar repetições encolheria o espaço de frases possíveis e torná-las-ia 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 carácter desce de 5,95 para 5,86 bits, pelo que um token precisa de cerca de um carácter a mais em cada doze para continuar igualmente forte. Costuma valer a pena para tudo o que uma pessoa vá ler no ecrã e escrever noutro sítio.

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 descodificar.

Pôr maiúscula em cada palavra de uma frase-passe 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, pelo que 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 a exigir 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 base 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 ficheiro de configuração.

Para tudo o que uma pessoa escreva, a restrição é outra e uma frase-passe 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.
Porque é 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-passe 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-passe é escolher as palavras por si, coisa que aqui não sucede.
Devo excluir os caracteres parecidos?
Se uma pessoa for ler o segredo no ecrã e escrevê-lo noutro sítio, 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 carácter de comprimento em cada doze.
Pôr maiúsculas torna uma frase-passe mais forte?
Não. É a mesma alteração aplicada sempre, pelo que 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 corre inteiramente no seu navegador com o gerador de aleatoriedade da plataforma, nada é carregado nem registado, e funciona sem ligação à rede. Os tokens não ficam guardados em lado nenhum: recarregar a página produz novos e os antigos desaparecem.