Repository navigation
senhas
Home > Autenticação > Senhas, revogação e TOTP 🚧
Important
Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.
Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: intermediário
Em uma frase: o RAL guarda senhas com Argon2id, bcrypt, scrypt ou PBKDF2 (em Pascal, sem DLL), revoga tokens JWT em todos os servidores, troca a chave do JWT sem derrubar ninguém e confere os códigos de 6 dígitos dos aplicativos autenticadores.
Você vai precisar: o pacote RALCryptoPasswordPackage para as senhas; o resto está
no PascalRAL (TOTP) e no RALPluginAuthPackage (JWT).
Nunca guarde a senha, nem um MD5/SHA dela: guarde o hash de senha.
uses RALPassword;
Hash := RALPasswordHash(Senha); // Argon2id, parâmetros da OWASP
if RALPasswordVerify(SenhaDigitada, Hash) then // reconhece qualquer formato abaixo
...
if RALPasswordNeedsRehash(Hash) then // fraco ou de outro algoritmo
Hash := RALPasswordHash(SenhaDigitada); // troque no login, com a senha certa em mãos| algoritmo | formato guardado | padrão |
|---|---|---|
| Argon2id (padrão) | $argon2id$v=19$m=19456,t=2,p=1$sal$hash |
19 MiB, 2 passadas |
| bcrypt |
$2b$10$... (o mesmo do htpasswd -B e do PHP) |
custo 10 |
| scrypt | $scrypt$ln=17,r=8,p=1$sal$hash |
N = 2^17 |
| PBKDF2-SHA256 / SHA512 | $pbkdf2-sha256$i=600000,l=32$sal$hash |
600 000 / 210 000 iterações |
Para outro algoritmo ou custo, use TRALPasswordOptions (ou o componente
TRALPasswordHasher, com Options no Object Inspector). Verify lê hashes de outras
ferramentas no mesmo formato (Argon2 de argon2-cffi, bcrypt do PHP/Python/htpasswd).
Lista := TRALPasswordList.Create(Self);
Lista.FileName := 'usuarios.txt'; // linhas usuario:hash (o formato do htpasswd)
Lista.OnRehash := SalvarNovoHash; // um login com hash fraco ganha um novo
BasicAuth.Passwords := Lista; // sem OnValidate, o Basic confere aquiLista.SetPassword('ana', 'nova senha') cria ou troca; Lista.Save grava o arquivo.
Usuário inexistente leva o mesmo tempo que senha errada: o tempo não entrega quem existe.
JWT.RevocationStore := Armazenamento; // TRALFileStore ou outro compartilhado entre servidores
JWT.Revoke(Token); // este token, até ele expirar
JWT.RevokeAllFor('ana'); // todos os tokens da ana emitidos até agora (logout geral)Com RevocationStore, todo token ganha jti e iat. Um token revogado é 401 em todos
os servidores que usam o mesmo armazenamento; o TRALServerOAuth2 também lê e grava
ali.
Troca de chave sem derrubar ninguém, por Keys:
-
JWT.Keys.AddSecret('2026-11', 'nova-chave')(ouAddPrivateKeycom um PEM RSA/EC): os novos tokens saem comkid = 2026-11; os antigos continuam valendo. - Depois que os tokens da chave antiga expiraram,
Retired := Truenela.
NotBefore publica uma chave antes de ela assinar. Com chaves RS/ES, PublishJWKS
responde GET /.well-known/jwks.json com as públicas, para outros servidores
conferirem os tokens (o TRALServerOAuth2 em modo ovJWKS, por exemplo).
uses RALOTP;
Totp := TRALTOTP.Create;
Totp.Issuer := 'Minha Empresa';
Segredo := Totp.NewSecret; // guarde junto do usuário
QR := Totp.URI('ana@empresa.com', Segredo); // mostre como QR code
...
Totp.Store := Armazenamento; // o mesmo código não vale duas vezes
if Totp.Verify(Segredo, CodigoDigitado, 'ana') then
...Funciona com Google Authenticator, Microsoft Authenticator, Authy e afins (SHA-1, 6
dígitos, 30 s). Window (padrão 1) aceita o código anterior e o próximo, para relógios
um pouco fora. Num login JWT, peça o código no OnGetToken depois da senha.
| sintoma | causa |
|---|---|
| login lento | é o custo do hash, de propósito (~50 ms no padrão); não baixe abaixo da OWASP |
Verify sempre False com hash do PHP |
confira se o texto chegou inteiro ($2y$ é aceito) |
| token revogado ainda entra em outro servidor | os servidores não usam o mesmo RevocationStore
|
| depois de aposentar a chave, todos deslogaram |
Retired antes de os tokens antigos expirarem |
| código TOTP sempre inválido | relógio do servidor errado (use NTP) ou segredo digitado com letras trocadas |
Começar
Servidor
- Rotas e parâmetros
- Rotas avançadas: tipos, grupos, versões 🚧
- Ler o pedido e responder
- Objetos no corpo 🚧
- Resposta em fluxo 🚧
- Plugins 🚧
- Autenticação
- Banco de dados (DBWare)
- Servir site e arquivos
- Swagger e Postman
- Servidor SOAP 🚧
- HTTPS
- Criptografia ponto a ponto
- Segurança para produção
- Colocar no ar
- Desempenho
- Testes em memória 🚧
MQTT 🚧
- O que é e quando usar 🚧
- Cliente MQTT 🚧
- Broker MQTT 🚧
- MQTT-SN 🚧
- Ponte REST 🚧
- Segurança 🚧
- Rede ruim 🚧
Cliente
Motores
Avançado
Ajuda
- Problemas comuns
- Atualizar o Indy
- Várias versões do Delphi
- Vídeos e guias
- Módulos de terceiros
- Licenças
- Contribuir
- Roadmap e changelog
🚧 = em desenvolvimento, pode mudar