bitwiseshiftleft / sjcl

Stanford Javascript Crypto Library
http://bitwiseshiftleft.github.com/sjcl/
Other
7.18k stars 986 forks source link

PBKDF2 + RIPEMD160 incorrect result #412

Open guidovranken opened 4 years ago

guidovranken commented 4 years ago
{
    var iterations = 2;
    var keySize = 147;
    var password = sjcl.codec.hex.toBits("00");
    var salt = sjcl.codec.hex.toBits("006ab795cd7d");

    var digestFn = sjcl.hash.ripemd160;

    var hmac = function (key) {
        var hasher = new sjcl.misc.hmac(key, digestFn);
        this.encrypt = function () {
            return hasher.encrypt.apply(hasher, arguments);
        };
    };

    var derivedKey = sjcl.misc.pbkdf2(password, salt, iterations, keySize * 8, hmac);

    console.log(sjcl.codec.hex.fromBits(derivedKey));
}

Expected result:

bed0d4b1e9909ff4239fc6e010ebae803d1503f1e5deac97891e18c6ae7207377f1756741d5f54964251e48927861f01e633226ab89cd54768b9a89c737ae3c42791ebe6936b146b96fdb4448e6fa6b093d6aef78d86dbcd960fd3cfd111fcaeb1559461aa336d92925735e5bdad560542245ff6910c9b002c6bd3ae9f9a80a5bd44f8a5f80645ebe1fbd51d75675d6a27d67e

Actual result

7815e14e4b1e0a60301a2fd1fad378de3fa99acdc2ed9c2e2b6870a5c1940e1607b87cd5441b11314e7301d098231420ec08bb45c1a94f8347befad2ff163b726e2e0c1a85917d2e309b0037125efb430ead1bd48f2499c77adc32a734aea303b86bee18963a035a2dea7508cc5ec91fdc500d9349b4f53b6ea21bfa798f8465c7cb2eed618b6cf0238e6bbdf332ab4edce92c

Reproducer for Botan

#include <botan/pbkdf.h>
#include <botan/pwdhash.h>
#include <string>
#include <stdlib.h>

#define CF_CHECK_NE(expr, res) if ( (expr) == (res) ) { goto end; }

int main(int argc, char** argv)
{
    const size_t size = 147;
    unsigned char* out = (uint8_t*)malloc(size);
    const uint8_t _password[] = {0x00};
    const uint8_t _salt[] = {0x00, 0x6a, 0xb7, 0x95, 0xcd, 0x7d};
    const std::string password(_password, _password + sizeof(_password));
    const std::string salt(_salt, _salt + sizeof(_salt));

    try {
        std::unique_ptr<::Botan::PasswordHashFamily> pwdhash_fam = nullptr;
        std::unique_ptr<::Botan::PasswordHash> pwdhash = nullptr;

        CF_CHECK_NE(pwdhash_fam = ::Botan::PasswordHashFamily::create("PBKDF2(RIPEMD-160)"), nullptr);

        CF_CHECK_NE(pwdhash = pwdhash_fam->from_params(2), nullptr);

        pwdhash->derive_key(
                out,
                size,
                password.data(),
                password.size(),
                (const uint8_t*)salt.data(),
                salt.size());

        for (size_t i = 0; i < size; i++) {
            printf("%02x", out[i]);
        }
        printf("\n");

    } catch ( ... ) { }

    free(out);
end:
    return 0;
}

Reproducer for OpenSSL

#include <openssl/evp.h>
int main(void)
{ 
    unsigned char out[147];
    const unsigned char password[] = {0x00};
    const unsigned char salt[] = {0x00, 0x6a, 0xb7, 0x95, 0xcd, 0x7d};
    if ( PKCS5_PBKDF2_HMAC((const char*)password, sizeof(password),
            salt, sizeof(salt), 2,
            EVP_ripemd160(),
            147, out) == 1 ) {
        for (size_t i = 0; i < sizeof(out); i++) {
            printf("%02x", out[i]);
        }
        printf("\n");
    }

    return 0;
}

May be related to https://github.com/bitwiseshiftleft/sjcl/issues/410