字节数组的HEX表示

时间:2012-04-03 08:57:30

标签: hex bytearray hmac pbkdf2

我觉得这很愚蠢,但是由于我不知道答案,我还是要继续前进。

我正在尝试一些身份验证代码,并想知道为什么我从Rfc2898DeriveBytes获得的字节数组需要转换为HEX并再次返回到字节数组,以便正确初始化我的HMACSHA1对象。我觉得我是做一些愚蠢的事情,或者只是遗漏一些明显的东西。

我的客户端代码是基于crypto-js;

的javascript函数
var key256bit = Crypto.PBKDF2(passwordEntered, saltBytes, 32, { iterations: 1000 }); 
var hmacBytes = Crypto.HMAC(Crypto.SHA1, url, key256bit, { asBytes: true });
var base64Hash = Crypto.util.bytesToBase64(hmacBytes);

我的服务器端代码如下;

    Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password,
                                              encoding.GetBytes(salt), 1000);
    byte[] key = rfc2898.GetBytes(32);

    // Don't think I should need to do this. 
    // However, it wont work if I initialise HMACSHA1 
    // with the rfc2898.GetBytes(32)
    string test = ByteArrayToString(key); 

    HMACSHA1 hmacSha1 = new HMACSHA1(encoding.GetBytes(test));

    byte[] computedHash = hmacSha1.ComputeHash(encoding.GetBytes(requestUri));
    string computedHashString = Convert.ToBase64String(computedHash);

我从网上获取的ByteArrayToString方法是;

private static string ByteArrayToString(byte[] ba)
{
    StringBuilder hex = new StringBuilder(ba.Length * 2);
    foreach (byte b in ba)
        hex.AppendFormat("{0:x2}", b);
    return hex.ToString();
}

所以我可以看到我从rfc2898.GetBytes(32)的调用中得到32个字节。我使用ByteArrayToString方法将其转换为HEX,以确认它与我在Javascript变量key256bit中看到的匹配。现在我的测试变量是一个长度为64的字符串,当我使用encoding.GetBytes(test)将它传递给HMACSHA1的constuctor时,它是一个长度为64的字节数组。

crypto-js上的doco有点缺乏,但我认为调用Crypto.PBKDF2的参数为32,它创建了一个32字节长(或256位)的密钥。

非常感谢任何澄清。

1 个答案:

答案 0 :(得分:3)

我怀疑这是问题的根源,在PBKDF2.js

return options && options.asBytes ? derivedKeyBytes :
       options && options.asString ? Binary.bytesToString(derivedKeyBytes) :
       util.bytesToHex(derivedKeyBytes);

因为您没有为asBytesasString提供选项,所以它会将密钥转换为十六进制表示形式 - 就像您的C#代码一样。所以目前你 使用512位密钥,正是因为你从“原始密钥”的每个字节生成2个字节的“使用密钥”。

我怀疑如果你在Javascript中指定asBytes选项,它只会在C#代码中没有额外的十六进制部分。

然后,我以前从未见过PBKDF2,所以我可能会离开基地......