This repository has been archived on 2023-04-04. You can view files and clone it, but cannot push or open issues or pull requests.
webcrypto/src/mechs/hmac/hmac.ts

85 lines
2.9 KiB
TypeScript
Raw Normal View History

2019-01-25 10:43:13 +00:00
import crypto from "crypto";
2020-03-13 11:06:53 +00:00
import { JsonParser, JsonSerializer } from "@peculiar/json-schema";
2019-01-25 10:43:13 +00:00
import * as core from "webcrypto-core";
2020-03-13 15:20:02 +00:00
import { setCryptoKey, getCryptoKey } from "../storage";
2019-01-25 10:43:13 +00:00
import { HmacCryptoKey } from "./key";
export class HmacProvider extends core.HmacProvider {
public async onGenerateKey(algorithm: HmacKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
2020-04-18 20:17:36 +00:00
const length = (algorithm.length || this.getDefaultLength((algorithm.hash as Algorithm).name)) >> 3 << 3;
2019-01-25 10:43:13 +00:00
const key = new HmacCryptoKey();
key.algorithm = {
...algorithm as any,
length,
2019-01-25 10:43:13 +00:00
name: this.name,
};
key.extractable = extractable;
key.usages = keyUsages;
key.data = crypto.randomBytes(length >> 3);
2020-03-13 15:20:02 +00:00
return setCryptoKey(key);
2019-01-25 10:43:13 +00:00
}
2022-03-02 18:35:31 +00:00
public override async onSign(algorithm: Algorithm, key: HmacCryptoKey, data: ArrayBuffer): Promise<ArrayBuffer> {
2019-01-25 10:43:13 +00:00
const hash = key.algorithm.hash.name.replace("-", "");
2020-03-13 15:20:02 +00:00
const hmac = crypto.createHmac(hash, getCryptoKey(key).data)
2019-01-25 10:43:13 +00:00
.update(Buffer.from(data)).digest();
return new Uint8Array(hmac).buffer;
}
2022-03-02 18:35:31 +00:00
public override async onVerify(algorithm: Algorithm, key: HmacCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise<boolean> {
2019-01-25 10:43:13 +00:00
const hash = key.algorithm.hash.name.replace("-", "");
2020-03-13 15:20:02 +00:00
const hmac = crypto.createHmac(hash, getCryptoKey(key).data)
2019-01-25 10:43:13 +00:00
.update(Buffer.from(data)).digest();
return hmac.compare(Buffer.from(signature)) === 0;
}
public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: HmacImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey> {
let key: HmacCryptoKey;
switch (format.toLowerCase()) {
case "jwk":
2019-01-25 12:48:21 +00:00
key = JsonParser.fromJSON(keyData, { targetSchema: HmacCryptoKey });
2019-01-25 10:43:13 +00:00
break;
case "raw":
key = new HmacCryptoKey();
key.data = Buffer.from(keyData as ArrayBuffer);
break;
default:
throw new core.OperationError("format: Must be 'jwk' or 'raw'");
}
key.algorithm = {
hash: { name: (algorithm.hash as Algorithm).name },
name: this.name,
length: key.data.length << 3,
};
key.extractable = extractable;
key.usages = keyUsages;
2020-03-13 15:20:02 +00:00
return setCryptoKey(key);
2019-01-25 10:43:13 +00:00
}
public async onExportKey(format: KeyFormat, key: HmacCryptoKey): Promise<JsonWebKey | ArrayBuffer> {
switch (format.toLowerCase()) {
case "jwk":
2020-03-13 15:20:02 +00:00
return JsonSerializer.toJSON(getCryptoKey(key));
2019-01-25 10:43:13 +00:00
case "raw":
2020-03-13 15:20:02 +00:00
return new Uint8Array(getCryptoKey(key).data).buffer;
2019-01-25 10:43:13 +00:00
default:
throw new core.OperationError("format: Must be 'jwk' or 'raw'");
}
}
2022-03-02 18:35:31 +00:00
public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) {
2019-01-25 10:43:13 +00:00
super.checkCryptoKey(key, keyUsage);
2020-03-13 15:20:02 +00:00
if (!(getCryptoKey(key) instanceof HmacCryptoKey)) {
2019-01-25 10:43:13 +00:00
throw new TypeError("key: Is not HMAC CryptoKey");
}
}
}