Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass key_len to bcrypt(). Fix for issues kelektiv#774, kelektiv#776 #807

Merged
merged 3 commits into from Jun 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/bcrypt.cc
Expand Up @@ -146,12 +146,11 @@ bcrypt_gensalt(char minor, u_int8_t log_rounds, u_int8_t *seed, char *gsalt)
i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */

void
bcrypt(const char *key, const char *salt, char *encrypted)
bcrypt(const char *key, size_t key_len, const char *salt, char *encrypted)
{
blf_ctx state;
u_int32_t rounds, i, k;
u_int16_t j;
size_t key_len;
u_int8_t salt_len, logr, minor;
u_int8_t ciphertext[4 * BCRYPT_BLOCKS+1] = "OrpheanBeholderScryDoubt";
u_int8_t csalt[BCRYPT_MAXSALT];
Expand Down Expand Up @@ -215,14 +214,11 @@ bcrypt(const char *key, const char *salt, char *encrypted)
decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
salt_len = BCRYPT_MAXSALT;
if (minor <= 'a')
key_len = (u_int8_t)(strlen(key) + (minor >= 'a' ? 1 : 0));
key_len = (u_int8_t)(key_len + (minor >= 'a' ? 1 : 0));
else
{
/* strlen() returns a size_t, but the function calls
* below result in implicit casts to a narrower integer
* type, so cap key_len at the actual maximum supported
/* cap key_len at the actual maximum supported
* length here to avoid integer wraparound */
key_len = strlen(key);
if (key_len > 72)
key_len = 72;
key_len++; /* include the NUL */
Expand Down
8 changes: 4 additions & 4 deletions src/bcrypt_node.cc
Expand Up @@ -148,7 +148,7 @@ namespace {
SetError("Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue");
}
char bcrypted[_PASSWORD_LEN];
bcrypt(input.c_str(), salt.c_str(), bcrypted);
bcrypt(input.c_str(), input.length(), salt.c_str(), bcrypted);
output = std::string(bcrypted);
}

Expand Down Expand Up @@ -185,7 +185,7 @@ namespace {
throw Napi::Error::New(env, "Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue");
}
char bcrypted[_PASSWORD_LEN];
bcrypt(data.c_str(), salt.c_str(), bcrypted);
bcrypt(data.c_str(), data.length(), salt.c_str(), bcrypted);
return Napi::String::New(env, bcrypted, strlen(bcrypted));
}

Expand All @@ -206,7 +206,7 @@ namespace {
void Execute() {
char bcrypted[_PASSWORD_LEN];
if (ValidateSalt(encrypted.c_str())) {
bcrypt(input.c_str(), encrypted.c_str(), bcrypted);
bcrypt(input.c_str(), input.length(), encrypted.c_str(), bcrypted);
result = CompareStrings(bcrypted, encrypted.c_str());
}
}
Expand Down Expand Up @@ -243,7 +243,7 @@ namespace {
std::string hash = info[1].As<Napi::String>();
char bcrypted[_PASSWORD_LEN];
if (ValidateSalt(hash.c_str())) {
bcrypt(pw.c_str(), hash.c_str(), bcrypted);
bcrypt(pw.c_str(), pw.length(), hash.c_str(), bcrypted);
return Napi::Boolean::New(env, CompareStrings(bcrypted, hash.c_str()));
} else {
return Napi::Boolean::New(env, false);
Expand Down
2 changes: 1 addition & 1 deletion src/node_blf.h
Expand Up @@ -125,7 +125,7 @@ u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t , u_int16_t *);

/* bcrypt functions*/
void bcrypt_gensalt(char, u_int8_t, u_int8_t*, char *);
void bcrypt(const char *, const char *, char *);
void bcrypt(const char *, size_t key_len, const char *, char *);
void encode_salt(char *, u_int8_t *, char, u_int16_t, u_int8_t);
u_int32_t bcrypt_get_rounds(const char *);

Expand Down
5 changes: 5 additions & 0 deletions test/implementation.js
Expand Up @@ -26,6 +26,11 @@ module.exports = {
assert.strictEqual(bcrypt.hashSync("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345", "$2b$05$CCCCCCCCCCCCCCCCCCCCC."), "$2b$05$CCCCCCCCCCCCCCCCCCCCC.XxrQqgBi/5Sxuq9soXzDtjIZ7w5pMfK");
assert.done();
},
test_embedded_nulls: function(assert) {
assert.strictEqual(bcrypt.hashSync("Passw\0rd123", "$2b$05$CCCCCCCCCCCCCCCCCCCCC."), "$2b$05$CCCCCCCCCCCCCCCCCCCCC.VHy/kzL4sCcX3Ib3wN5rNGiRt.TpfxS");
assert.strictEqual(bcrypt.hashSync("Passw\0 you can literally write anything after the NUL character", "$2b$05$CCCCCCCCCCCCCCCCCCCCC."), "$2b$05$CCCCCCCCCCCCCCCCCCCCC.4vJLJQ6nZ/70INTjjSZWQ0iyUek92tu");
assert.done();
},
test_shorten_salt_to_128_bits: function(assert) {
assert.strictEqual(bcrypt.hashSync("test", "$2a$10$1234567899123456789012"), "$2a$10$123456789912345678901u.OtL1A1eGK5wmvBKUDYKvuVKI7h2XBu");
assert.strictEqual(bcrypt.hashSync("U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCCh"), "$2a$05$CCCCCCCCCCCCCCCCCCCCCeUQ7VjYZ2hd4bLYZdhuPpZMUpEUJDw1S");
Expand Down