Depurador de códigos TOTP / 2FA

Gere e depure códigos TOTP / 2FA: a derivação RFC 6238 completa, verificação com janela de deriva e análise de otpauth:// — tudo no seu navegador.

Tempo

Insira um segredo para ver um código.

otpauth:// URI para esta configuração
otpauth://totp/user%40example.com?secret=JBSWY3DPEHPK3PXP&algorithm=SHA1&digits=6&period=30

O que são realmente os seis dígitos

Um código TOTP — o número que um app de autenticação renova a cada trinta segundos — não é aleatório nem é guardado em lugar nenhum. Ele é calculado, tanto no seu telefone quanto no servidor, a partir de duas coisas que já compartilham: um segredo configurado uma vez ao ativar a autenticação de dois fatores, e a hora atual. Como ambos os lados podem calculá-lo de forma independente, nada precisa viajar entre eles ao entrar; o servidor apenas executa o mesmo cálculo e confere se a resposta dele corresponde à sua.

TOTP (RFC 6238) é uma camada fina sobre um esquema mais antigo, HOTP (RFC 4226). HOTP transforma um segredo e um contador em um código; TOTP é simplesmente HOTP com o contador definido como o número de passos de tempo desde a época Unix. É toda a ideia: divida a hora Unix atual pelo tamanho do passo (30 segundos por padrão) e passe o resultado ao HOTP. Esta ferramenta mostra cada passo desse cálculo, porque quando um código não verifica, a resposta quase sempre está visível em algum ponto da derivação.

A derivação, passo a passo

Cinco passos levam do segredo e da hora aos dígitos que você digita. A ferramenta imprime cada um para você comparar com a sua implementação:

  • O contador. Pegue a hora Unix em segundos, subtraia T0 (0 em toda implantação real), divida pelo período e arredonde para baixo. Com passos de 30 segundos, qualquer momento no mesmo meio minuto dá o mesmo contador, por isso um código dura o que dura.
  • O HMAC. Escreva o contador como 8 bytes big-endian e calcule HMAC(segredo, contador) com o hash escolhido — SHA-1 para quase todos os apps. Isso produz um resumo de 20 bytes para SHA-1 (32 para SHA-256, 64 para SHA-512).
  • O deslocamento. Pegue os quatro bits baixos do último byte do resumo. É um número de 0 a 15 e diz onde ler no resumo — truncamento dinâmico, para que o mesmo segredo não use sempre os mesmos bytes.
  • O valor de 31 bits. Leia quatro bytes a partir do deslocamento e mascare o bit alto (para evitar confusão de sinal). Sobra um inteiro de 31 bits.
  • O código. Pegue esse inteiro módulo 10^dígitos e preencha com zeros à esquerda. Seis dígitos é a escolha quase universal; sete e oito existem e são permitidos.

O mascaramento do bit alto e o módulo são os únicos passos com perda: muitos resumos diferentes mapeiam para os mesmos seis dígitos, e tudo bem, porque o código só precisa ser difícil de adivinhar nos trinta segundos em que vive, não único para sempre.

Por que um código não corresponde — as três causas habituais

Uma divergência de TOTP nunca vem com uma mensagem de erro; o código simplesmente está errado. Na prática é quase sempre uma de três coisas, e os painéis aqui estão dispostos para distingui-las:

  • O segredo foi lido no formato errado. Um segredo de autenticador é Base32, mas os mesmos caracteres lidos como hex — ou um segredo que era de fato hex lido como Base32 — produzem bytes completamente diferentes e um código completamente diferente. Troque o seletor de formato e veja qual dá o código esperado.
  • Um parâmetro difere. O padrão esmagador é HMAC-SHA-1, 6 dígitos, um período de 30 segundos. Um servidor que use SHA-256, ou 8 dígitos, ou um passo de 60 segundos, discordará de um app deixado nos padrões. O otpauth:// URI carrega os três, por isso escanear um QR os acerta e digitar um segredo à mão muitas vezes não.
  • Os relógios derivaram. TOTP supõe que ambos os lados concordam sobre a hora. Se o relógio de um telefone adianta um minuto, o código dele fica um minuto à frente do servidor. É para isso que serve a janela de deriva: verificar um código contra os passos dos dois lados do agora diz não só se corresponde, mas quanto o relógio está desviado.

RFC 6238 recomenda uma janela de validação de no máximo um passo de cada lado — suficiente para absorver o desvio de relógio comum e a corrida do momento de renovação, sem alargar o espaço de busca mais do que o necessário. Esta ferramenta usa ±1 por padrão e deixa você alargá-la ao depurar.

Segredos, Base32 e o otpauth:// URI

O segredo é compartilhado uma vez, na configuração, e tudo o mais deriva dele. Apps de autenticação o codificam em Base32 (RFC 4648) — o alfabeto A–Z e 2–7, que evita os caracteres fáceis de confundir e sobrevive a ser impresso sob um QR. Esta ferramenta lê Base32 por padrão, ignorando os espaços que apps adicionam por legibilidade e as maiúsculas, e também aceita hex para você reproduzir os vetores de teste de RFC 6238, cujos segredos são dados como bytes brutos.

O QR code que você escaneia na configuração também não é mágica: ele codifica um otpauth:// URI em texto simples que carrega o segredo e todos os parâmetros. Cole um aqui para preencher os campos, ou construa um a partir dos campos para mover uma configuração entre apps:

otpauth://totp/GitHub:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=GitHub&algorithm=SHA1&digits=6&period=30

Apenas o tipo totp é aceito. Um otpauth://hotp URI carrega um contador em vez de um período, e tratá-lo como TOTP produziria códigos errados em silêncio — então ele é recusado em vez de adivinhado.

Algoritmo, dígitos e período

RFC 6238 permite HMAC-SHA-1, SHA-256 ou SHA-512, de seis a oito dígitos, e qualquer tamanho de passo. Na prática o mundo se firmou em SHA-1, seis dígitos e trinta segundos, e a maioria dos apps só implementa essa combinação — um servidor que escolhe outra coisa tem que torcer para o app do usuário acompanhar, e muitos não acompanham. A escolha segura para interoperabilidade é a chata.

Vale abordar a questão do SHA-1 diretamente, porque a ferramenta de hash deste site marca SHA-1 como quebrado. As duas afirmações são verdadeiras. SHA-1 é inútil para assinaturas digitais porque atacantes podem fabricar colisões — dois documentos com o mesmo hash. TOTP não depende dessa propriedade: sua segurança vem da chave secreta dentro do HMAC, não da resistência a colisões do hash, e HMAC-SHA-1 continua sólido. Usar SHA-256 aqui é defensável mas rende pouco, e custa interoperabilidade com apps que só fazem SHA-1.

O que esta ferramenta protege e o que não protege

Tudo aqui roda no seu navegador. O HMAC é calculado com a Web Crypto API no seu próprio dispositivo, o mesmo primitivo que as ferramentas de hash e HMAC usam, e nada do que você digita — segredo, código ou otpauth URI — é enviado, guardado ou registrado. É uma propriedade de o código ser do lado do cliente, não uma promessa a acreditar de boa fé.

Dito isso, um segredo TOTP é um segundo fator: quem o tiver pode gerar seus códigos. Colar um segredo de produção em qualquer página web — incluindo esta — o coloca na área de transferência e possivelmente no histórico do navegador, então trate-o com o mesmo cuidado que uma senha, e prefira um segredo descartável ou de teste quando só precisar entender o mecanismo. A ferramenta existe para depurar e aprender, não para ser onde vive o seu segundo fator real.

Perguntas frequentes

O meu segredo é enviado a um servidor?
Não. O código é calculado no seu navegador com a Web Crypto API, e nada do que você digita é enviado ou registrado. Como um segredo TOTP é um segundo fator, tenha cuidado mesmo assim ao colar um de produção — ele pode passar pela área de transferência e pelo histórico do navegador como qualquer texto.
Por que o meu código não corresponde ao meu autenticador?
Quase sempre uma de três coisas: o segredo foi lido no formato errado (Base32 vs hex), um parâmetro difere dos padrões (a maioria dos apps é SHA-1, 6 dígitos, período de 30 segundos), ou o relógio do dispositivo derivou. O painel de derivação isola os dois primeiros, e verificar com uma janela de deriva ± revela o terceiro.
Qual é a diferença entre TOTP e HOTP?
HOTP (RFC 4226) calcula um código a partir de um segredo e um contador que incrementa a cada uso. TOTP (RFC 6238) é a mesma construção com o contador definido como o número de passos de tempo desde a época Unix, então o código muda com o relógio em vez de com um toque. TOTP é o que os apps de autenticação usam.
Por que SHA-1 é o padrão se é quebrado em outros lugares?
SHA-1 é quebrado para assinaturas porque se pode construir colisões, mas HMAC — sobre o qual TOTP é construído — não depende de resistência a colisões; sua segurança reside na chave secreta. HMAC-SHA-1 é sólido, e é o único algoritmo que muitos apps de autenticação implementam, então é o padrão tanto seguro quanto compatível.
Posso fixar o código a uma hora específica?
Sim. Troque a hora de ao vivo para fixada e insira um carimbo de tempo Unix. O código então fica estático, é assim que se reproduz um vetor de teste publicado — RFC 6238 dá valores em horas como 59 e 1111111109 — ou se confere qual código era válido em um momento passado.
Qual deve ser o tamanho da janela de deriva?
RFC 6238 recomenda no máximo um passo de cada lado, que é o que esta ferramenta usa por padrão. Uma janela mais ampla tolera um relógio mais desviado mas também alarga o conjunto de códigos que um servidor aceitaria, então é um compromisso; ±1 é o equilíbrio padrão.
Para que servem os dígitos e o período?
Os dígitos são quantos algarismos o código tem — seis quase em todo lugar, sete ou oito onde um serviço quer um pouco mais de força. O período é quantos segundos um código permanece válido, trinta por padrão. Ambos vão no otpauth:// URI, e ambos têm que corresponder nos dois lados ou os códigos não concordarão.