Skip to content

Commit

Permalink
feat(KDFs): add PBKDF2 algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
aykxt committed Mar 26, 2021
1 parent d6260ca commit d3a0d78
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ A collection of useful cryptographic algorithms written in Typescript.
### [Key Derivation Functions] (KDFs)

- [HKDF]
- [PBKDF2]

## Examples

Expand Down Expand Up @@ -63,3 +64,4 @@ reviews. **USE AT YOUR OWN RISK**
[HMAC]: https://en.wikipedia.org/wiki/HMAC
[Key Derivation Functions]: https://en.wikipedia.org/wiki/Key_derivation_function
[HKDF]: https://en.wikipedia.org/wiki/HKDF
[PBKDF2]: https://en.wikipedia.org/wiki/PBKDF2
2 changes: 2 additions & 0 deletions pbkdf2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { pbkdf2 } from "./src/pbkdf2/mod.ts";
export type { SupportedAlgorithm } from "./src/pbkdf2/mod.ts";
2 changes: 1 addition & 1 deletion src/hkdf/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function hkdf(
const concat = new Uint8Array(t.length + info.length + 1);
concat.set(t);
concat.set(info, t.length);
concat.set([i + 1], t.length + info.length);
concat[t.length + info.length] = i + 1;
t = hmac(hash, prk, concat);
okm.set(t, hashLen * i);
}
Expand Down
39 changes: 39 additions & 0 deletions src/pbkdf2/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { hmac, outputSizes, SupportedAlgorithm } from "../hmac/mod.ts";

export type { SupportedAlgorithm };

/**
* PKCS #5: Password-Based Key Derivation Function 2 (PBKDF2)
*/
export function pbkdf2(
hash: SupportedAlgorithm,
password: Uint8Array,
salt: Uint8Array,
iterations: number,
keylen: number,
): Uint8Array {
const dk = new Uint8Array(keylen);

const salti = new Uint8Array(salt.length + 4);
const saltiView = new DataView(salti.buffer);
salti.set(salt);

const hashLen = outputSizes[hash];
const len = Math.ceil(keylen / hashLen);

for (let i = 1, offset = 0; i <= len; i++, offset += hashLen) {
saltiView.setUint32(salt.length, i);

const t = hmac(hash, password, salti);
let u = t;

for (let j = 1; j < iterations; j++) {
u = hmac(hash, password, u);
for (let k = 0; k < hashLen; k++) t[k] ^= u[k];
}

dk.set(t, offset);
}

return dk;
}
14 changes: 14 additions & 0 deletions tests/pbkdf2.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { pbkdf2 } from "../src/pbkdf2/mod.ts";
import { assertEquals, encodeToHex } from "../dev_deps.ts";

Deno.test("PBKDF2 HMAC-SHA1", () => {
// https://tools.ietf.org/html/rfc6070#section-2
const te = new TextEncoder();

const password = te.encode("password");
const salt = te.encode("salt");

const dk = pbkdf2("sha1", password, salt, 1, 20);

assertEquals(encodeToHex(dk), "0c60c80f961f0e71f3a9b524af6012062fe037a6");
});

0 comments on commit d3a0d78

Please sign in to comment.