swc/crates/swc_bundler/tests/.cache/deno/020be644443b8947fbca69ea92ebd2ece761d2d0.ts
2021-11-09 20:42:49 +09:00

111 lines
2.4 KiB
TypeScript

// Loaded from https://deno.land/x/djwt@v1.9/_signature.ts
import type { Algorithm } from "./_algorithm.ts";
import {
base64url,
convertHexToUint8Array,
HmacSha256,
HmacSha512,
RSA,
} from "./_depts.ts";
function assertNever(alg: never, message: string): never {
throw new RangeError(message);
}
export function convertHexToBase64url(input: string): string {
return base64url.encode(convertHexToUint8Array(input));
}
/**
* Do a constant time string comparison. Always compare the complete strings
* against each other to get a constant time. This method does not short-cut
* if the two string's length differs.
* CREDIT: https://github.com/Bruce17/safe-compare
*/
function safeCompare(a: string, b: string) {
const strA = String(a);
const lenA = strA.length;
let strB = String(b);
let result = 0;
if (lenA !== strB.length) {
strB = strA;
result = 1;
}
for (var i = 0; i < lenA; i++) {
result |= (strA.charCodeAt(i) ^ strB.charCodeAt(i));
}
return result === 0;
}
async function encrypt(
algorithm: Algorithm,
key: string,
message: string,
): Promise<string> {
switch (algorithm) {
case "none":
return "";
case "HS256":
return new HmacSha256(key).update(message).toString();
case "HS512":
return new HmacSha512(key).update(message).toString();
case "RS256":
return (
await new RSA(RSA.parseKey(key)).sign(message, { hash: "sha256" })
).hex();
default:
assertNever(
algorithm,
"no matching crypto algorithm in the header: " + algorithm,
);
}
}
export async function create(
algorithm: Algorithm,
key: string,
input: string,
): Promise<string> {
return convertHexToBase64url(await encrypt(algorithm, key, input));
}
export async function verify({
signature,
key,
algorithm,
signingInput,
}: {
signature: string;
key: string;
algorithm: Algorithm;
signingInput: string;
}): Promise<boolean> {
switch (algorithm) {
case "none":
case "HS256":
case "HS512": {
return safeCompare(
signature,
(await encrypt(algorithm, key, signingInput)),
);
}
case "RS256": {
return await new RSA(RSA.parseKey(key)).verify(
convertHexToUint8Array(signature),
signingInput,
{ hash: "sha256" },
);
}
default:
assertNever(
algorithm,
"no matching crypto algorithm in the header: " + algorithm,
);
}
}