diff --git a/src/secret-wrap.ts b/src/secret-wrap.ts new file mode 100644 index 0000000..7f39aa5 --- /dev/null +++ b/src/secret-wrap.ts @@ -0,0 +1,83 @@ +import logger from 'log' +import {a2b64, b642a} from 'misc' + +const log = logger('crypto:secret-wrap') + +export class SecretWrap { + constructor( + private readonly cipher: Uint8Array, + private readonly algorithm: KeyAlgorithm, + private readonly usages: KeyUsage[], + private readonly type: "raw" | "pkcs8", + private readonly iv: Uint8Array, + ) {} + + public static gen_key() : Promise { + log.trace("generate key") + return crypto.subtle.generateKey( + { + name: "AES-GCM", + length: 256, + }, + true, + ["wrapKey", "unwrapKey"], + ) + } + + private static format(type: KeyType) : "raw" | "pkcs8" { + switch (type) { + case "private": return "pkcs8" + case "secret": return "raw" + default: throw "Don't wrap public keys please..." + } + } + + public static async encrypt(data: CryptoKey, key: CryptoKey) : Promise { + log.trace("encrypt") + const format = this.format(data.type) + const iv = crypto.getRandomValues(new Uint8Array(12)) + const box = await crypto.subtle.wrapKey( + format, + data, + key, + { + name: "AES-GCM", + iv, + }, + ) + return new SecretWrap(new Uint8Array(box), data.algorithm, data.usages, format, iv) + } + public async decrypt(key: CryptoKey) : Promise { + log.trace("decrypt") + return crypto.subtle.unwrapKey( + this.type, + this.cipher, + key, + { + name: "AES-GCM", + iv: this.iv, + }, + this.algorithm, + true, + this.usages + ) + } + + public toString() : string { + log.trace("toString") + return JSON.stringify({ + cipher: a2b64(this.cipher), + iv: a2b64(this.iv), + algorithm: this.algorithm, + usages: this.usages, + type: this.type, + }) + } + public static fromString(data: string) : SecretWrap { + log.trace("fromString") + const obj = JSON.parse(data) + const cipher = b642a(obj.cipher).expect("Failed to decode cipher") + const iv = b642a(obj.iv).expect("Failed to decode IV") + return new SecretWrap(cipher, obj.algorithm, obj.usages, obj.type, iv) + } +}