react-native-quick-crypto
Version:
A fast implementation of Node's `crypto` module written in C/C++ JSI
130 lines (122 loc) • 3.65 kB
text/typescript
import type { HashAlgorithm } from '.';
export enum HashContext {
Node,
WebCrypto,
JwkRsa,
JwkRsaPss,
JwkRsaOaep,
JwkHmac,
}
// WebCrypto and JWK use a bunch of different names for the
// standard set of SHA-* digest algorithms... which is ... fun.
// Here we provide a utility for mapping between them in order
// make it easier in the code.
type HashNames = {
[]: { [key in HashContext as string]: string };
};
const kHashNames: HashNames = {
sha1: {
[]: 'sha1',
[]: 'SHA-1',
[]: 'RS1',
[]: 'PS1',
[]: 'RSA-OAEP',
[]: 'HS1',
},
sha224: {
[]: 'sha224',
[]: 'SHA-224',
[]: 'RS224',
[]: 'PS224',
[]: 'RSA-OAEP-224',
[]: 'HS224',
},
sha256: {
[]: 'sha256',
[]: 'SHA-256',
[]: 'RS256',
[]: 'PS256',
[]: 'RSA-OAEP-256',
[]: 'HS256',
},
sha384: {
[]: 'sha384',
[]: 'SHA-384',
[]: 'RS384',
[]: 'PS384',
[]: 'RSA-OAEP-384',
[]: 'HS384',
},
sha512: {
[]: 'sha512',
[]: 'SHA-512',
[]: 'RS512',
[]: 'PS512',
[]: 'RSA-OAEP-512',
[]: 'HS512',
},
ripemd160: {
[]: 'ripemd160',
[]: 'RIPEMD-160',
},
'sha3-256': {
[]: 'sha3-256',
[]: 'SHA3-256',
},
'sha3-384': {
[]: 'sha3-384',
[]: 'SHA3-384',
},
'sha3-512': {
[]: 'sha3-512',
[]: 'SHA3-512',
},
shake128: {
[]: 'shake128',
[]: 'cSHAKE128',
},
shake256: {
[]: 'shake256',
[]: 'cSHAKE256',
},
};
{
// Index the aliases
const keys: string[] = Object.keys(kHashNames);
for (let n: number = 0; n < keys.length; n++) {
const contexts: string[] = Object.keys(kHashNames[keys[n]!]!);
for (let i: number = 0; i < contexts.length; i++) {
const alias: string = kHashNames[keys[n]!]![contexts[i]!]!.toLowerCase();
if (kHashNames[alias] === undefined)
kHashNames[alias] = kHashNames[keys[n]!]!;
}
}
// Add OpenSSL legacy RSA-* aliases (e.g. RSA-SHA256 -> sha256)
for (let n: number = 0; n < keys.length; n++) {
const key = keys[n]!;
if (key.startsWith('sha') || key === 'ripemd160') {
const rsaAlias = 'rsa-' + key;
if (kHashNames[rsaAlias] === undefined) {
kHashNames[rsaAlias] = kHashNames[key]!;
}
}
}
}
export function normalizeHashName(
algo: string | HashAlgorithm | { name: string } | undefined,
context: HashContext = HashContext.Node,
): string {
if (typeof algo !== 'undefined') {
const hashName =
typeof algo === 'string' ? algo : algo.name || algo.toString();
const normAlgo = hashName.toLowerCase();
try {
const alias = kHashNames[normAlgo]![context];
if (alias) return alias;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_e) {
// ignore
}
}
throw new Error(`Invalid Hash Algorithm: ${algo}`);
}