Senha única baseada no tempo - TOTP explicado
Os usuários da Internet têm que inserir senhas regularmente – por exemplo, ao entrar em plataformas de mídia social, fazer compras online ou usar internet banking. Senhas impedem que terceiros acessem dados confidenciais. No entanto, muitos usuários não são suficientemente diligentes em matéria de segurança online: os profissionais podem quebrar senhas simples em questão de segundos. Outras pessoas criam boas senhas, mas não conseguem armazená-las com segurança, *deixando assim uma porta aberta para criminosos. Além disso, as fraquezas nos serviços que os usuários assinam também não são pequenas. Se esses serviços não protegerem corretamente senhas, os dados de milhares de usuários podem estar em risco.
Uma maneira de minimizar o risco é usar autenticação de dois fatores ou autenticação multifatorial. Em vez de usar apenas uma senha, pelo menos um outro meio de autenticação é necessário. Os usuários desta tecnologia obtêm este fator de autenticação adicional através de seu smartphone ou um dispositivo de hardware especial (chamado de “token”). O ponto comum entre a maioria desses fatores adicionais é que eles são únicos e válidos apenas por um curto período de tempo – em outras palavras, uma senha única baseada no tempo é gerada. Vamos dar uma olhada em como isso funciona.
Conteúdo
- Por que precisamos de um TOTP?
- Como funciona o algoritmo de senha único baseado no tempo?
- Exemplo de um cálculo TOTP
Por que precisamos de um TOTP?
Senhas convencionais – por mais fortes que o usuário as faça – têm uma desvantagem: se alguém conhece a cadeia de caracteres, a segurança não é mais garantida. Uma solução seria alterar senhas regularmente, mas mesmo os usuários mais exemplares não fazem isso a cada hora. A solução é um TOTP: uma senha que só é válida por um breve período, após o qual expira. A Força-Tarefa de Engenharia da Internet (IETF) publicou o algoritmo de senha única em 2011 na RFC 6238 para facilitar uma maior segurança on-line.
Senhas únicas são usadas principalmente como parte da autenticação de vários fatores, um sistema de segurança que exige que os usuários que entram em um serviço web primeiro digitem sua senha pessoal e estática e, em seguida, uma senha limitada de tempo gerada especialmente para esse login. O usuário recebe a segunda senha através de um aplicativo ou um token de hardware especial.
Uma vez que a senha única tenha sido usada ou se não tiver sido usada após um tempo especificado, ela expira. Portanto, é muito difícil para os criminosos obter o segundo fator, pois mesmo que eles saibam a senha estática, é muito difícil para eles obter o TOTP também, especialmente porque eles têm quase nenhum tempo para quebrá-lo.
Como funciona o algoritmo de senha único baseado no tempo?
O TOTP é baseado em uma função hash, que é um procedimento criptográfico pelo qual uma chave secreta e um carimbo de tempo são combinados para formar uma sequência de caracteres criptografadas. Tanto o usuário quanto o servidor conhecem a chave secreta. O carimbo de hora é dado no tempo do Unix.
Fato
O tempo unix é um valor correspondente ao número de segundos que se passaram desde 1º de janeiro de 1970.
TOTP é, na verdade, um desenvolvimento adicional do HOTP, que significa senha única baseada em HMAC. Como o HOTP, o TOTP é baseado no procedimento HMAC – a operação hash em segundo plano. Tanto o dispositivo do usuário quanto o servidor geram um valor de hash combinando a chave secreta com um contador. Os dois valores são idênticos, que é como a autenticação funciona.
A função hash em si não está definida; na prática, o SHA-1 é frequentemente usado (inclusive pelo Google Authenticator, por exemplo). O SHA-1 gera um valor de hash de 160 bits. Por conveniência, este valor é truncado usando uma função de compressão. O resultado final é um número curto (seis dígitos, por exemplo) que o usuário pode usar facilmente para fazer login no serviço web.
Nota
A chave secreta está incorporada em um token no dispositivo, o que significa que muitas vezes nem o usuário o conhece. Se este não for o caso, a chave secreta deve ser armazenada com segurança, idealmente offline, ou mesmo impressa e mantida em um lugar seguro, por exemplo. Se o usuário perder a chave secreta, ele não poderá mais fazer login no serviço.
Para a segunda parte da função, o HOTP usa um contador, e isso é compartilhado pelo servidor e pelo usuário. O problema com isso é que o código gerado permanece válido até que seja usado. TOTP restringe isso: o código gerado só pode ser usado dentro de um período de tempo definido. Como isso funciona?
Para o algoritmo de senha única baseado no tempo, existem três fórmulas importantes:
TOTP = HOTP (SecretKey,CurrentTime)
Esta fórmula básica simplesmente define que o TOTP é um procedimento HOTP com dois parâmetros – SecretKey e CurrentTime:
- SecretKey: Senha gerada aleatoriamente, conhecida tanto pelo servidor quanto pelo cliente
- CurrentTime: Tempo atual no tempo do Unix
No entanto, esse valor de tempo muda a cada segundo, o que não deixa o usuário tempo suficiente para digitar o código gerado. Ou seja, um segundo depois, o TOTP não é mais válido, pois o servidor já gerou um novo valor de hash. Portanto, é necessária uma outra fórmula:
CurrentTime = piso ((unixtime(agora) – unixtime(T0)/T1)
O parâmetro CurrentTime é definido da seguinte forma:
- unixtime(agora): Tempo atual no tempo unix
- unixtime(T0): Tempo de Unix em T0, o ponto a partir do qual os passos do tempo são contados – na maioria dos casos meia-noite em 1º de janeiro de 1970 (=0)
- T1: O período para o qual o TOTP será válido (geralmente 30 segundos)
- floor: Função de arredondamento para arredondar o valor calculado até um número inteiro
Nota
Em teoria, T0 pode ter qualquer valor, não necessariamente 0. O importante é que o cliente e o servidor selecionem o mesmo valor.
O efeito da divisão e arredondamento é que o resultado muda em intervalos definidos.
Em seguida, o valor de hash gerado é truncado para torná-lo mais fácil de usar.
Resultado = TOTPmod10d
A operação modulo gera um cheque:
- mod 10: Modulo com divisor = 10
- d: Número desejado de dígitos do TOTP
Em outras palavras, a base (10) é elevada ao número desejado de dígitos, então o TOTP é dividido por este valor e o restante é extraído.
Exemplo de um cálculo TOTP
Vamos supor que queremos gerar um TOTP que é válido por 30 segundos. Podemos começar calculando o CurrentTime e determinando por quanto tempo a validade será garantida. Para o unxtime(agora), vamos levá 1548322860, ou seja, 10:41 da manhã em 24 de janeiro de 2019. Se dividirmos esse valor em 30, teremos exatamente 51610762. Porque este já é um número inteiro, arredondamento daria o mesmo resultado. No entanto, se definirmos o CurrentTime 15 segundos depois (ou seja, 1548322875), após a divisão, o resultado é 51610762.5. Após arredondamento, o valor é 51610762, como antes. Portanto, o CurrentTime permanece o mesmo. A tabela a seguir mostra que um novo valor só é gerado a cada 30 segundos.
unixtime(now) | unixtime(now)/30 | floor(unixtime(now)/30) |
---|---|---|
1548322857 | 51610761.9000 | 51610761 |
1548322858 | 51610761.9333 | 51610761 |
1548322859 | 51610761.9667 | 51610761 |
1548322860 | 51610762.0000 | 51610762 |
1548322861 | 51610762.0333 | 51610762 |
1548322862 | 51610762.0667 | 51610762 |
1548322863 | 51610762.1000 | 51610762 |
1548322864 | 51610762.1333 | 51610762 |
1548322865 | 51610762.1667 | 51610762 |
1548322866 | 51610762.2000 | 51610762 |
1548322867 | 51610762.2333 | 51610762 |
1548322868 | 51610762.2667 | 51610762 |
1548322869 | 51610762.3000 | 51610762 |
1548322870 | 51610762.3333 | 51610762 |
1548322871 | 51610762.3667 | 51610762 |
1548322872 | 51610762.4000 | 51610762 |
1548322873 | 51610762.4333 | 51610762 |
1548322874 | 51610762.4667 | 51610762 |
1548322875 | 51610762.5000 | 51610762 |
1548322876 | 51610762.5333 | 51610762 |
1548322877 | 51610762.5667 | 51610762 |
1548322878 | 51610762.6000 | 51610762 |
1548322879 | 51610762.6333 | 51610762 |
1548322880 | 51610762.6667 | 51610762 |
1548322881 | 51610762.7000 | 51610762 |
1548322882 | 51610762.7333 | 51610762 |
1548322883 | 51610762.7667 | 51610762 |
1548322884 | 51610762.8000 | 51610762 |
1548322885 | 51610762.8333 | 51610762 |
1548322886 | 51610762.8667 | 51610762 |
1548322887 | 51610762.9000 | 51610762 |
1548322888 | 51610762.9333 | 51610762 |
1548322889 | 51610762.9667 | 51610762 |
1548322890 | 51610763.0000 | 51610763 |
1548322891 | 51610763.0333 | 51610763 |
Nosso CurrentTime é, portanto, estabelecido (51610762). Agora usamos um gerador de senhas para obter o SecretKey: >cHSB_UQ#O5m;~b
HMAC (com SHA-1) combina a chave secreta e o tempo atual para produzir um valor de hash (em formato hexadecimal): c0 62 37 94 dd 37 7a 3a f0 91 22 08 1f 21 6f 9b 17 4b 17 45. Este valor de 160 bits (20 byte) é truncado a 31 bits usando o que é conhecido como truncação dinâmica. Isso envolve a realização das seguintes etapas: Primeiro, os últimos 4 bits são considerados. Em nosso exemplo, este é o número 0x5, que também pode ser escrito como 5 em notação decimal. Isso dá o valor de deslocamento a ser usado para truncação dinâmica, e significa que a partir do byte com o índice 5, devemos extrair quatro bytes (leia-se da esquerda, a partir de 0): 0x377a3af0. Neste exemplo nosso valor já começa com um pouco igual a 0. Se este não for o caso, deve ser alterado em conformidade. O valor de 31 bits aqui é assim: 0x377a3af0, ou 930757360.
Para reduzir esta sequência de 9 dígitos para 6 dígitos, usamos uma operação de modulo, enchimento do resultado com zeros principais, se necessário: 930757360 mod (106) = 757360. Este é agora o TOTP, que é válido por 30 segundos. Em combinação com outro fator, isso torna o procedimento de login bastante seguro.