summaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
Diffstat (limited to 'std')
-rw-r--r--std/hash/sha1.ts73
-rw-r--r--std/hash/sha1_test.ts56
2 files changed, 126 insertions, 3 deletions
diff --git a/std/hash/sha1.ts b/std/hash/sha1.ts
index 19563088b..b30ccb6b6 100644
--- a/std/hash/sha1.ts
+++ b/std/hash/sha1.ts
@@ -33,6 +33,9 @@ export class Sha1 {
#lastByteIndex = 0;
constructor(sharedMemory = false) {
+ this.init(sharedMemory);
+ }
+ protected init(sharedMemory: boolean) {
if (sharedMemory) {
// deno-fmt-ignore
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
@@ -50,7 +53,6 @@ export class Sha1 {
this.#block = this.#start = this.#bytes = this.#hBytes = 0;
this.#finalized = this.#hashed = false;
}
-
update(message: Message): this {
if (this.#finalized) {
return this;
@@ -121,7 +123,7 @@ export class Sha1 {
return this;
}
- private finalize(): void {
+ protected finalize(): void {
if (this.#finalized) {
return;
}
@@ -383,3 +385,70 @@ export class Sha1 {
return buffer;
}
}
+export class HmacSha1 extends Sha1 {
+ #sharedMemory: boolean;
+ #inner: boolean;
+ #oKeyPad: number[];
+ constructor(secretKey: Message, sharedMemory = false) {
+ super(sharedMemory);
+ let key: number[] | Uint8Array | undefined;
+ if (typeof secretKey === "string") {
+ const bytes: number[] = [];
+ const length: number = secretKey.length;
+ let index = 0;
+ for (let i = 0; i < length; i++) {
+ let code = secretKey.charCodeAt(i);
+ if (code < 0x80) {
+ bytes[index++] = code;
+ } else if (code < 0x800) {
+ bytes[index++] = 0xc0 | (code >> 6);
+ bytes[index++] = 0x80 | (code & 0x3f);
+ } else if (code < 0xd800 || code >= 0xe000) {
+ bytes[index++] = 0xe0 | (code >> 12);
+ bytes[index++] = 0x80 | ((code >> 6) & 0x3f);
+ bytes[index++] = 0x80 | (code & 0x3f);
+ } else {
+ code = 0x10000 +
+ (((code & 0x3ff) << 10) | (secretKey.charCodeAt(++i) & 0x3ff));
+ bytes[index++] = 0xf0 | (code >> 18);
+ bytes[index++] = 0x80 | ((code >> 12) & 0x3f);
+ bytes[index++] = 0x80 | ((code >> 6) & 0x3f);
+ bytes[index++] = 0x80 | (code & 0x3f);
+ }
+ }
+ key = bytes;
+ } else {
+ if (secretKey instanceof ArrayBuffer) {
+ key = new Uint8Array(secretKey);
+ } else {
+ key = secretKey;
+ }
+ }
+ if (key.length > 64) {
+ key = new Sha1(true).update(key).array();
+ }
+ const oKeyPad: number[] = [];
+ const iKeyPad: number[] = [];
+ for (let i = 0; i < 64; i++) {
+ const b = key[i] || 0;
+ oKeyPad[i] = 0x5c ^ b;
+ iKeyPad[i] = 0x36 ^ b;
+ }
+
+ this.update(iKeyPad);
+ this.#oKeyPad = oKeyPad;
+ this.#inner = true;
+ this.#sharedMemory = sharedMemory;
+ }
+ protected finalize(): void {
+ super.finalize();
+ if (this.#inner) {
+ this.#inner = false;
+ const innerHash = this.array();
+ super.init(this.#sharedMemory);
+ this.update(this.#oKeyPad);
+ this.update(innerHash);
+ super.finalize();
+ }
+ }
+}
diff --git a/std/hash/sha1_test.ts b/std/hash/sha1_test.ts
index 2caaff49b..fae57e2f2 100644
--- a/std/hash/sha1_test.ts
+++ b/std/hash/sha1_test.ts
@@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { assertEquals } from "../testing/asserts.ts";
-import { Message, Sha1 } from "./sha1.ts";
+import { HmacSha1, Message, Sha1 } from "./sha1.ts";
import { dirname, fromFileUrl, join, resolve } from "../path/mod.ts";
const moduleDir = dirname(fromFileUrl(import.meta.url));
@@ -20,6 +20,7 @@ function toHexString(value: number[] | ArrayBuffer): string {
// deno-fmt-ignore
const fixtures: {
sha1: Record<string, Record<string, Message>>;
+ sha1Hmac: Record<string, Record<string, [Message, Message]>>;
} = {
sha1: {
"ascii": {
@@ -61,6 +62,40 @@ const fixtures: {
'5ba93c9db0cff93f52b521d7420e43f6eda2784f': new ArrayBuffer(1)
}
},
+ sha1Hmac:{
+
+ "Test Vectors": {
+ "b617318655057264e28bc0b6fb378c8ef146be00": [
+ [0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b],
+ "Hi There"
+ ],
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79": [
+ "Jefe",
+ "what do ya want for nothing?"
+ ],
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3": [
+ [0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa],
+ [0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd]
+ ],
+ "4c9007f4026250c6bc8414f9bf50c86c2d7235da": [
+ [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19],
+ [0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd]
+ ],
+ "90d0dace1c1bdc957339307803160335bde6df2b": [
+ [0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa],
+ "Test Using Larger Than Block-Size Key - Hash Key First"
+ ],
+ "217e44bb08b6e06a2d6c30f3cb9f537f97c63356": [
+ [0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa],
+ "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+ ]
+ },
+ "UTF8": {
+ "f495de6d0f1b5681070a024bbaed5b5f42847306": ["中文", "中文"],
+ "58891d68487ffebddba5925abedec77a5a578db2": ["aécio", "aécio"],
+ "a1816bff2dae324c283aeab564d5edb5170fbada": ["𠜎", "𠜎"]
+ }
+ },
};
const methods = ["array", "arrayBuffer", "digest", "hex"] as const;
@@ -103,6 +138,25 @@ for (const method of methods) {
}
}
+for (const method of methods) {
+ for (const [name, tests] of Object.entries(fixtures.sha1Hmac)) {
+ let i = 1;
+ for (const [expected, [key, message]] of Object.entries(tests)) {
+ Deno.test({
+ name: `hmacSha1.${method}() - ${name} - #${i++}`,
+ fn() {
+ const algorithm = new HmacSha1(key);
+ algorithm.update(message);
+ const actual = method === "hex"
+ ? algorithm[method]()
+ : toHexString(algorithm[method]());
+ assertEquals(actual, expected);
+ },
+ });
+ }
+ }
+}
+
Deno.test("[hash/sha1] test Uint8Array from Reader", async () => {
const data = await Deno.readFile(join(testdataDir, "hashtest"));