From 1e401d14331c4816c2653884cae01cfc75d4888e Mon Sep 17 00:00:00 2001 From: mfont <121682800+mfont-bz17@users.noreply.github.com> Date: Sat, 31 Dec 2022 16:18:43 +0100 Subject: [PATCH] bcrypt: fix issue #16769 security problem in compare_hash_and_password (#16815) --- vlib/crypto/bcrypt/bcrypt.v | 8 ++++++-- vlib/crypto/bcrypt/bcrypt_test.v | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/vlib/crypto/bcrypt/bcrypt.v b/vlib/crypto/bcrypt/bcrypt.v index 519dc0229f..9398959d42 100644 --- a/vlib/crypto/bcrypt/bcrypt.v +++ b/vlib/crypto/bcrypt/bcrypt.v @@ -125,14 +125,18 @@ fn bcrypt(password []u8, cost int, salt []u8) ?[]u8 { // expensive_blowfish_setup generate a Blowfish cipher, given key, cost and salt. fn expensive_blowfish_setup(key []u8, cost u32, salt []u8) ?&blowfish.Blowfish { csalt := base64.decode(salt.bytestr()) + // Bug compatibility with C bcrypt implementations, which use the trailing NULL in the key string during expansion. + // See https://cs.opensource.google/go/x/crypto/+/master:bcrypt/bcrypt.go;l=226 + mut ckey := key.clone() + ckey << 0 - mut bf := blowfish.new_salted_cipher(key, csalt) or { return err } + mut bf := blowfish.new_salted_cipher(ckey, csalt) or { return err } mut i := u64(0) mut rounds := u64(0) rounds = 1 << cost for i = 0; i < rounds; i++ { - blowfish.expand_key(key, mut bf) + blowfish.expand_key(ckey, mut bf) blowfish.expand_key(csalt, mut bf) } diff --git a/vlib/crypto/bcrypt/bcrypt_test.v b/vlib/crypto/bcrypt/bcrypt_test.v index 772fe0862e..65894159a1 100644 --- a/vlib/crypto/bcrypt/bcrypt_test.v +++ b/vlib/crypto/bcrypt/bcrypt_test.v @@ -8,4 +8,14 @@ fn test_crypto_bcrypt() { bcrypt.compare_hash_and_password('password2'.bytes(), hash.bytes()) or { assert err.msg() == 'mismatched hash and password' } + + hash2 := bcrypt.generate_from_password('bb'.bytes(), 10) or { panic(err) } + mut hash2_must_mismatch := false + + bcrypt.compare_hash_and_password('bbb'.bytes(), hash2.bytes()) or { + hash2_must_mismatch = true + assert err.msg() == 'mismatched hash and password' + } + + assert hash2_must_mismatch }