HEX представление байтового массива - PullRequest
6 голосов
/ 03 апреля 2012

Я чувствую себя довольно глупо, спрашивая это, но так как я не знаю ответа, я все равно иду вперед.

Я испытываю некоторый код аутентификации и хочу знать, почему байтовый массив, который я получаю из Rfc2898DeriveBytes, необходимо преобразовать в HEX и обратно в байтовый массив, чтобы он правильно инициализировал мой объект HMACSHA1. Мне кажется, что я делать что-то глупое или просто упустить что-то очевидное.

Мой код клиента - это функция JavaScript, основанная на crypto-js ;

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();
}

Итак, я вижу, что я получаю 32 байта от моего вызова на rfc2898.GetBytes(32). Я преобразовал это в HEX, используя метод ByteArrayToString, чтобы подтвердить, что он соответствует тому, что я вижу в моей переменной Javascript key256bit. Теперь моя тестовая переменная - это строка длиной 64, и когда я передаю ее конструктору HMACSHA1 с помощью encoding.GetBytes (test), это байтовый массив длиной 64.

Доку по crypto-js немного не хватает, но я подумал, что вызов Crypto.PBKDF2 с параметром 32 и он создает ключ длиной 32 байта (или 256 бит).

Любые разъяснения приветствуются.

1 Ответ

3 голосов
/ 19 апреля 2012

Я подозреваю, что это корень проблемы, в PBKDF2.js :

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

Поскольку вы не предоставили опции для asBytes или asString,это преобразование ключа в шестнадцатеричное представление - так же, как это делает ваш код C #.Таким образом, в данный момент вы используете 512-битный ключ, именно потому, что вы генерируете 2 байта «используемого ключа» из каждого байта «исходного ключа».

Я подозреваю, что есливы указываете опцию asBytes в Javascript, она будет работать без лишней шестнадцатеричной части в коде C #.

Опять же, я никогда раньше не видел PBKDF2, так что я мог бы быть далеко от базы...

...