Yes, this is a workable approach, when you use authenticated encryption, as you've indicated. The authentication tag on the encrypted data is analogous to a stored password hash, and GCM is specifically designed to prevent message forgery (i.e., a valid tag constructed without access to the private key).
In fact, GMAC is a variant of GCM mode that is designed not to encrypt data, but just to provide a signature with a shared key over some data.
It's important to note that this should not be done with non-authenticated ciphers, as even with padding being used to detect "correct" decryption, this would lead to a (slightly better than) 1/256 chance of any password working correctly by having correct padding despite being the incorrect key.
All this being said, I don't think this is a good idea, because it's much easier to have implementation errors in this than it is in a standard password storage scheme. Attacking this scheme is equally easy/difficult to attacking a separate PBKDF2 hash for the user password, which is a well studied authentication mechanism. If you're worried about CPU time with computing two PBKDF2 hashes, you can do the following:
- Compute
key = PBKDF2(Password, Salt, N)
to derive the symmetric key.
- Compute
pwhash = PBKDF2(Password, Salt, N+1)
to derive the stored password hash. (This can be done with only a single extra round on the original hash above.)
Inverting PBKDF2(Password, Salt, N+1)
into PBKDF2(Password, Salt, N)
is equivalent to inverting HMAC
on whatever hash function you use.
The scheme above is the scheme used by Lastpass for authentication vs decrypting your password vault. (Only pwhash
is sent to their server so they cannot recover the key for the password vault from that.)