| ... | ... | @@ -95,11 +95,10 @@ pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: |
| 95 | 95 | // |
| 96 | 96 | // DK = T_1 || T_2 || ... || T_l<0..r-1> |
| 97 | 97 | |
| 98 | | var prevBlock: [hLen]u8 = undefined; |
| 99 | | var newBlock: [hLen]u8 = undefined; |
| 100 | | |
| 101 | 98 | var block: u32 = 0; // Spec limits to u32 |
| 102 | 99 | while (block < l) : (block += 1) { |
| 100 | var prevBlock: [hLen]u8 = undefined; |
| 101 | var newBlock: [hLen]u8 = undefined; |
| 103 | 102 | |
| 104 | 103 | // U_1 = PRF (P, S || INT (i)) |
| 105 | 104 | const blockIndex = mem.toBytes(mem.nativeToBig(u32, block + 1)); // Block index starts at 0001 |
| ... | ... | @@ -109,15 +108,15 @@ pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: |
| 109 | 108 | ctx.final(prevBlock[0..]); |
| 110 | 109 | |
| 111 | 110 | // Choose portion of DK to write into (T_n) and initialize |
| 112 | | const offset = block * hLen; |
| 111 | const offset: usize = block * hLen; |
| 113 | 112 | const blockLen = if (block != l - 1) hLen else r; |
| 114 | 113 | var dkBlock = derivedKey[offset..(offset + blockLen)]; |
| 115 | | mem.copy(u8, dkBlock[0..], prevBlock[0..dkBlock.len]); |
| 114 | mem.copy(u8, dkBlock, prevBlock[0..dkBlock.len]); |
| 116 | 115 | |
| 117 | 116 | var i: u32 = 1; |
| 118 | 117 | while (i < rounds) : (i += 1) { |
| 119 | 118 | // U_c = PRF (P, U_{c-1}) |
| 120 | | Prf.create(newBlock[0..], prevBlock[0..], password); |
| 119 | Prf.create(&newBlock, prevBlock[0..], password); |
| 121 | 120 | mem.copy(u8, prevBlock[0..], newBlock[0..]); |
| 122 | 121 | |
| 123 | 122 | // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c |
| ... | ... | @@ -225,3 +224,26 @@ test "RFC 6070 embedded NUL" { |
| 225 | 224 | |
| 226 | 225 | htest.assertEqual(expected, derivedKey[0..]); |
| 227 | 226 | } |
| 227 | |
| 228 | test "Very large dkLen" { |
| 229 | // These iteration tests are slow so we always skip them. Results have been verified. |
| 230 | if (true) { |
| 231 | return error.SkipZigTest; |
| 232 | } |
| 233 | |
| 234 | const p = "password"; |
| 235 | const s = "salt"; |
| 236 | const c = 1; |
| 237 | const dkLen = 1 << 33; |
| 238 | |
| 239 | var derivedKey = try std.testing.allocator.alloc(u8, dkLen); |
| 240 | defer { |
| 241 | std.testing.allocator.free(derivedKey); |
| 242 | } |
| 243 | |
| 244 | pbkdf2(derivedKey, p, s, c, crypto.hash.Sha1); |
| 245 | |
| 246 | const expected = "0c60c80f961f0e71f3a9b524af6012062fe037a6"; |
| 247 | |
| 248 | htest.assertEqual(expected, derivedKey[0..]); |
| 249 | } |