0

I'd like to authenticate my users without storing their password, even in a derived form with scrypt/pbkdf or other derivation methods.

I'm exploring the idea of encrypting a random payload with AES GCM, and storing it alongside its IV and tag. Then, authentication would simply be a matter of decrypting that payload with the provided password. I'm counting on the fact that the GCM algorithm will fail to decrypt/authenticate the data if the password is wrong.

When creating a new user, I would generate a key based on the provided password, a random IV and a random payload.

# Password is provided by the user
password := get_password_from_user()

iv := generate_random_iv()
payload := generate_random_payload()

encrypted_payload, tag = encrypt('aes-256-gcm', password, iv, payload)
store_authentication_info(iv, tag, encrypted_payload)

The authentication process would simply decrypt the payload, checking the tag.

# Password is provided by the user
password := get_password_from_user()

# IV, 
iv := get_iv_from_storage()
tag := get_tag_from_storage()
encrypted_payload = get_payload_from_storage()

decrypt('aes-256-gcm', password, iv, tag, encrypted_payload)

I'm using PHP in this case, and the openssl_decrypt function returns false if the decryption didn't work.

Is that a sound authentication method? Can I assume that being able to decrypt the payload successfully validates that the user knows the right password?

Well it sounds obvious now that I'm writing it, but anyway, it's written so I might as well publish the question.

Can I use aes-gcm to authenticate my user? Am I missing anything important? Is there any obvious security issues to this approach?

aspyct
  • 183
  • 4
  • 1
    This doesn't add much security over brute-forcing the password. For every password, they will go for decryption, assuming that the attackers have access to iv, tag, encrypted_payload. Instead, incrementing the iteration of scryt/argon2id is easier than this. Why do you want to get rid of the usual salt-paper and a good PBKDF like Scrypt/Argon2id? – kelalaka Mar 15 '20 at 21:59
  • I'm deriving the password with pbkdf2 already. I don't want to store the password in any form because the main goal of the application is to keep data encrypted with said password. I feel like it would be wrong to keep a derived form of the password along with the encrypted data. – aspyct Mar 15 '20 at 22:02
  • You can derive more with different salt/context information etc. An example with HKDF is here – kelalaka Mar 15 '20 at 22:05
  • Ahah, I'm afraid you'll have to lay this out for me. I store the salt and iterations for the pbkdf2 derivation. I'm always using the same salt, hence getting the same key for encryption. However I'm using a different IV every time. Am I doing it right? You can find the code here, if interested: https://github.com/aspyct/captainslog/blob/master/app/log.php – aspyct Mar 15 '20 at 22:15
  • You can append information to salt, like "login", "encrypt", etc. – kelalaka Mar 15 '20 at 22:19
  • I'm not following you. Are you suggesting I should be using one pbkdf salt (and thus one derived key) to encrypt all my payloads. Or the opposite, I should use a different pbkdf salt for each payload to be encrypted? – aspyct Mar 15 '20 at 22:20
  • 1
    I'm missing the difference between (say) scrypt and gcm. In both cases, they take the password, send it through a series of computations, and then compare the result to an expected value (in the GCM case, this is the "tag"). If they're essentially the same, what value does GCM bring you? – poncho Mar 15 '20 at 22:35
  • Well that's actually a good point. I was afraid to use different hashing/derivation methods, thinking I could give more information to a potential attacker. But if that's not justified, then I should probably used scrypt indeed. – aspyct Mar 15 '20 at 22:52

0 Answers0