Passwords: hashing, not encryption.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // ====================================================================== // Q: How do you store passwords and protect sensitive data? // // - Passwords: hashing, not encryption. A slow algorithm with a salt (PBKDF2, // bcrypt, Argon2). ASP.NET Core Identity already does this. Never MD5 or plain // SHA-256 on its own. // - Even better: no passwords in our database at all. Login through an external // IdP (Entra ID, Entra External ID, Keycloak) with MFA. // - In transit: TLS everywhere, HSTS. At rest: database encryption (TDE), and // for very sensitive columns Always Encrypted or application-level encryption. // - Data Protection API for cookies and tokens in links (password reset, // unsubscribe). With multiple instances the keys must be shared. // - PII in logs: never tokens, passwords or full card details. Redaction with // Microsoft.Extensions.Compliance.Redaction. GDPR: right to erasure and // retention policies. // ====================================================================== // If you need your own hashing (without the whole of Identity) var hasher = new PasswordHasher<User>(); // PBKDF2 + salt, with a version in the hash user.PasswordHash = hasher.HashPassword(user, password); var result = hasher.VerifyHashedPassword(user, user.PasswordHash, attempt); if (result == PasswordVerificationResult.SuccessRehashNeeded) // old algorithm: rehash user.PasswordHash = hasher.HashPassword(user, attempt); // Data Protection keys shared across all instances (otherwise cookies break after scale-out) builder.Services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri(cfg["DataProtection:BlobUri"]!), new DefaultAzureCredential()) .ProtectKeysWithAzureKeyVault(new Uri(cfg["DataProtection:KeyUri"]!), new DefaultAzureCredential()); |