为什么PBKDF2 SHA256生成的哈希值在C和java之间不相等

时间:2016-02-18 03:41:52

标签: java c sha256 encryption-symmetric pbkdf2

我有一个Android客户端和服务器,客户端需要在与服务器通信或处理数据之前验证会话密钥。客户端是Android应用程序,其加密方法是用Java编写的,服务器是用C语言编写的。

我将会话密钥称为"魔术令牌",并且魔术令牌由PBKDF2算法生成,在服务器上具有1000次SHA256哈希迭代。客户端从服务器获取魔术令牌,客户端本身需要再次重新生成魔术令牌,以便比较获取的令牌和生成的令牌。如果它们相等,则表示会话密钥有效,客户端可以进一步操作。

但我的问题是当我尝试使用相同的算法生成魔术令牌,盐,服务器端的迭代计数时,生成的哈希值不一样。也许它由PBKDF2算法或sha256引起的不同平台不完全相同。我觉得很困惑,任何人都可以帮我找出错误的来源?

注意,C和Java源代码都是在github上托管的开源项目,如下所示。提前谢谢。

C语言风格如下

static unsigned char salt[8] = { 0xda, 0x90, 0x45, 0xc3, 0x06, 0xc7, 0xcc, 0x26 };

    int
seafile_derive_key (const char *data_in, int in_len, int version,
                    unsigned char *key, unsigned char *iv)
{
    if (version == 2) {
        PKCS5_PBKDF2_HMAC (data_in, in_len,
                           salt, sizeof(salt),
                           KEYGEN_ITERATION2,
                           EVP_sha256(),
                           32, key);
        PKCS5_PBKDF2_HMAC ((char *)key, 32,
                           salt, sizeof(salt),
                           10,
                           EVP_sha256(),
                           16, iv);
        return 0;
    } else if (version == 1)
        return EVP_BytesToKey (EVP_aes_128_cbc(), /* cipher mode */
                               EVP_sha1(),        /* message digest */
                               salt,              /* salt */
                               (unsigned char*)data_in,
                               in_len,
                               KEYGEN_ITERATION,   /* iteration times */
                               key, /* the derived key */
                               iv); /* IV, initial vector */
    else
        return EVP_BytesToKey (EVP_aes_128_ecb(), /* cipher mode */
                               EVP_sha1(),        /* message digest */
                               NULL,              /* salt */
                               (unsigned char*)data_in,
                               in_len,
                               3,   /* iteration times */
                               key, /* the derived key */
                               iv); /* IV, initial vector */
}

        void
    seafile_generate_magic (int version, const char *repo_id,
                            const char *passwd, char *magic)
    {
        GString *buf = g_string_new (NULL);
        unsigned char key[32], iv[16];

        /* Compute a "magic" string from repo_id and passwd.
         * This is used to verify the password given by user before decrypting
         * data.
         */
        g_string_append_printf (buf, "%s%s", repo_id, passwd);

        seafile_derive_key (buf->str, buf->len, version, key, iv);

        g_string_free (buf, TRUE);
        rawdata_to_hex (key, magic, 32);
    }

可以在github

上找到C的完整文件

和我的java(Android)语言风格如下

private static String generateMagic(String repoID, String password, int version) throws NoSuchAlgorithmException, InvalidKeySpecException, UnsupportedEncodingException, SeafException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
    if (version != 1 && version != 2) {
        throw SeafException.unsupportedEncVersion;
    }

    String src = repoID + password;
    char[] salt = {0xda, 0x90, 0x45, 0xc3, 0x06, 0xc7, 0xcc, 0x26};
    final byte[] slt = new String(salt).getBytes("UTF-8");
    // If you use version 1.47 or higher of SpongyCastle, you can invoke PBKDF2WithHmacSHA256 directly.
    // In versions of BC < 1.47, you could not specify SHA256 digest and it defaulted to SHA1.
    // see http://stackoverflow.com/questions/6898801/how-to-include-the-spongy-castle-jar-in-android
    PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest());
    gen.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(src.toCharArray()), slt, ITERATION_COUNT);
    byte[] keyBytes;

    if (version == 2) {
        keyBytes = ((KeyParameter) gen.generateDerivedMacParameters(KEY_LENGTH * 8)).getKey();
    } else
        keyBytes = ((KeyParameter) gen.generateDerivedMacParameters(16 * 8)).getKey();

    // final SecretKey key = deriveKeyPbkdf2(slt, src, version);
    // final byte[] bytes = key.getEncoded();
    return toHex(keyBytes);
}

可以在github

上找到Java的完整文件

修改

最后,我发现了错误,它是由char [] salt引起的,

是正确的
byte[] salt = {(byte) 0xda, (byte) 0x90, (byte) 0x45, (byte) 0xc3, (byte) 0x06, (byte) 0xc7, (byte) 0xcc, (byte) 0x26};

0 个答案:

没有答案