I'm creating a little game-like feature for fun (so no need to be super secure).
On the server, I encrypt using a secret password:
const key = crypto.createCipher('aes-256-cbc', 'secret')
let encryption = key.update('cheerio', 'utf8', 'hex')
encryption += key.final('hex')
On the client, I want the user to guess the password (which is secret
in this example), like this:
try {
const key = crypto.createDecipher('aes-256-cbc', guess)
let decryption = key.update(encryption, 'hex', 'utf8')
decryption += key.final('utf8')
}
catch(err) {
console.log("err", err)
}
The question is, will this always throw an error if the guess
fails, or do I need to compare it to my phrase ( 'cheerio'
)? (I am yet to guess something that doesn't throw an error.)
I feel the former would give an extra layer of security, because then there's both a secret password AND secret word, while if I do a compare on the client the secret word is exposed in the code.
No, an error is not always generated when guess
fails.
The reason for the error ( error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt ), is a wrong padding during decryption, here . The crypto
module uses PKCS7 padding by default. In this padding variant each padding byte has the value that corresponds to the number of padding bytes, eg 01 , 0202 , 030303 , 04040404 etc., see here for details. Decryption with an incorrect password will result in random/corrupted plaintext. Its end will generally not correspond to a valid PKCS7 padding, which causes the error. However, by chance a plaintext may result, whose end matches a valid PKCS7 padding. In this case, no error is raised. Eg a 01 byte terminating the plaintext would be compatible with PKCS7 padding, which occurs for a random password with a probability of 1/256. The same applies to 0202 with a probability of 1/65536, and so on.
This can be easily verified if padding is disabled during decryption ( key.setAutoPadding(false)
). Then no error is raised. The same applies when using a stream cipher mode (eg, CTR) where padding is implicitly disabled.
This means that even in cases where no error is produced, a comparison with the plain text is necessary.
Note that createCipher
(deprecated, by the way) derives a key and an IV from the password. The same password (and thus the same key and IV) will generate the same ciphertext for the same plaintext. Therefore, a comparison of the ciphertexts serves the same purpose as a comparison of the plaintexts.
One more thing, the results of update
and final
must be concatenated, otherwise the result is generally not complete, ie in encryption = key.final('hex')
the =
must be replaced by +=
, although this is probably just a typo. The same applies to decryption.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.