Skip to content

Commit bec4308

Browse files
committed
refactor: minor code refactoring
1 parent 4623321 commit bec4308

File tree

1 file changed

+15
-18
lines changed

1 file changed

+15
-18
lines changed

mod.ts

+15-18
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
11
/*!
2-
* keygrip
2+
* Based on https://github.com/crypto-utils/keygrip/blob/master/index.js
33
* Copyright(c) 2011-2014 Jed Schmidt
44
* Copyright(c) 2020 Christian Norrman
55
* MIT Licensed
66
*/
7-
8-
import { HmacSha256, HmacSha512 } from './deps.ts';
9-
10-
const SANITIZE_REGEXP = /\/|\+|=/g;
11-
const SANITIZE_REPLACERS = {
12-
"/": "_",
13-
"+": "-",
14-
"=": "",
15-
} as Record<string, string>;
7+
import { HmacSha256, HmacSha512, base64url } from './deps.ts';
168

179
export enum Algorithm {
1810
SHA256 = 'sha256',
@@ -21,10 +13,9 @@ export enum Algorithm {
2113

2214
export class Keygrip {
2315
#keys: string[];
24-
#decoder: TextDecoder;
2516
#algo: Algorithm;
2617

27-
constructor(keys: string[], algo: Algorithm=Algorithm.SHA256, enc: string='base64') {
18+
constructor(keys: string[], algo: Algorithm=Algorithm.SHA256) {
2819
if (!keys || !keys.length) {
2920
throw new Error('Keys must be provided.');
3021
} else if (algo != 'sha256' && algo != 'sha512') {
@@ -33,7 +24,6 @@ export class Keygrip {
3324

3425
this.#keys = keys;
3526
this.#algo = algo;
36-
this.#decoder = new TextDecoder(enc);
3727
}
3828

3929
sign(data: string, key?: string): string {
@@ -47,20 +37,27 @@ export class Keygrip {
4737
const hash = new HmacSha512(key);
4838
buffer = hash.update(data).arrayBuffer();
4939
} else {
50-
// Required for typescript
5140
throw new Error('Algorithm invalid');
5241
}
5342

54-
return this.#decoder
55-
.decode(buffer)
56-
.replace(SANITIZE_REGEXP, s => SANITIZE_REPLACERS[s]);
43+
return base64url.encode(buffer);
5744
}
5845

5946
verify(data: string, digest: string): boolean {
6047
return this.index(data, digest) != -1;
6148
}
6249

6350
index(data: string, digest: string): number {
64-
return this.#keys.findIndex(key => digest === this.sign(data, key));
51+
return this.#keys.findIndex(key => this.compare(digest, this.sign(data, key)));
52+
}
53+
54+
// Timing safe compare using Brad Hill's Double HMAC pattern
55+
private compare(a: string, b: string): boolean {
56+
const key = crypto.getRandomValues(new Uint8Array(32));
57+
const hmac = new HmacSha256(key);
58+
const ah = hmac.update(a).digest();
59+
const bh = hmac.update(b).digest();
60+
61+
return ah.length === bh.length && ah.every((x, i) => x === bh[i]);
6562
}
6663
}

0 commit comments

Comments
 (0)