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?

  • 1
    $\begingroup$ 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? $\endgroup$ – kelalaka Mar 15 at 21:59
  • $\begingroup$ 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. $\endgroup$ – aspyct Mar 15 at 22:02
  • $\begingroup$ You can derive more with different salt/context information etc. An example with HKDF is here $\endgroup$ – kelalaka Mar 15 at 22:05
  • $\begingroup$ 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: github.com/aspyct/captainslog/blob/master/app/log.php $\endgroup$ – aspyct Mar 15 at 22:15
  • 1
    $\begingroup$ 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? $\endgroup$ – poncho Mar 15 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.