Skip to content

Commit

Permalink
feat: add HMAC algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
aykxt committed Mar 14, 2021
1 parent cf46ca7 commit bd08fa8
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
2 changes: 2 additions & 0 deletions deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { createHash } from "https://deno.land/std@0.90.0/hash/mod.ts";
export type { SupportedAlgorithm } from "https://deno.land/std@0.90.0/hash/mod.ts";
1 change: 1 addition & 0 deletions dev_deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export {
assertThrows,
} from "https://deno.land/std@0.90.0/testing/asserts.ts";
export { parse as parseArgs } from "https://deno.land/std@0.90.0/flags/mod.ts";
export { encodeToString as encodeToHex } from "https://deno.land/x/std@0.90.0/encoding/hex.ts";
1 change: 1 addition & 0 deletions hmac.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { hmac } from "./src/hmac/mod.ts";
66 changes: 66 additions & 0 deletions src/hmac/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { createHash, SupportedAlgorithm } from "../../deps.ts";

export type { SupportedAlgorithm };

const blockSizes: Record<SupportedAlgorithm, number> = {
"sha3-512": 72,
"sha3-384": 48,
"sha3-256": 136,
"sha3-224": 144,
sha512: 128,
sha384: 128,
sha256: 64,
sha224: 64,
sha1: 64,
md5: 64,
md4: 64,
md2: 16,
ripemd320: 64,
ripemd160: 64,
keccak512: 72,
keccak384: 48,
keccak256: 136,
keccak224: 144,
};

export function hmac(
hash: SupportedAlgorithm,
key: Uint8Array,
data: Uint8Array,
): Uint8Array {
const blockSize = blockSizes[hash];

if (key.length > blockSize) {
key = new Uint8Array(createHash(hash).update(key).digest());
}

if (key.length < blockSize) {
const keylong = new Uint8Array(blockSize);
keylong.set(key, 0);
key = keylong;
}

const opad = new Uint8Array(blockSize);
const ipad = new Uint8Array(blockSize);

for (let i = 0; i < blockSize; i++) {
opad[i] = key[i] ^ 0x5c;
ipad[i] = key[i] ^ 0x36;
}

return new Uint8Array(
createHash(hash).update(
concat(
opad,
new Uint8Array(createHash(hash).update(concat(ipad, data)).digest()),
),
).digest(),
);
}

function concat(a: Uint8Array, b: Uint8Array) {
const arr = new Uint8Array(a.length + b.length);
arr.set(a, 0);
arr.set(b, a.length);
return arr;
}
27 changes: 27 additions & 0 deletions tests/hmac.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { hmac } from "../hmac.ts";
import { assertEquals, encodeToHex } from "../dev_deps.ts";

const encoder = new TextEncoder();
const key = encoder.encode("secret");
const data = encoder.encode("hello world!");

Deno.test("HMAC-SHA1", () => {
assertEquals(
encodeToHex(hmac("sha1", key, data)),
"a4df5f9d237ab0ca3241f042bcf6059a4ef491c4",
);
});

Deno.test("HMAC-SHA256", () => {
assertEquals(
encodeToHex(hmac("sha256", key, data)),
"72069731bf291b463aecb218bc227abce3d403d76da67faef2d48d3cb43b2f54",
);
});

Deno.test("HMAC-SHA512", () => {
assertEquals(
encodeToHex(hmac("sha512", key, data)),
"563069fb7c8512ffe6ced927289ac5e6f30a360c1099c61b62e3a91636a2563c95524ab5a0f4fe41f86e990a9f732dbf60d4f6c85761dafbd4953c24c758f936",
);
});

0 comments on commit bd08fa8

Please sign in to comment.