import logger from 'log' import SecretBox from './secret-box' import {DHusage, ecdh} from './kdf' import * as consts from './const' import * as misc from './misc.ts' const log = logger('crypto:private-box') export default class PrivateBox { private constructor( private readonly pubkey: CryptoKey, private readonly box: SecretBox ) {} public static async gen(extractable: boolean = true): Promise { log.trace('generate keypair') return await crypto.subtle.generateKey(consts.ECDH, extractable, ['deriveBits']) as CryptoKeyPair } public static async encrypt(data: Uint8Array, pubkey: CryptoKey, context?: string): Promise { log.trace('encrypt') const tmp_pair = await PrivateBox.gen(false) const key = await ecdh(tmp_pair.privateKey, pubkey, DHusage.box, context) // TODO : null const box = await SecretBox.encrypt(data, key) return new this(tmp_pair.publicKey, box) } public async decrypt(privkey: CryptoKey, context?: string): Promise { log.trace('decrypt') const key = await ecdh(privkey, this.pubkey, DHusage.box, context) // TODO : null return await this.box.decrypt(key) } public async toString(): Promise { log.trace('toString') const pubkey = await PrivateBox.pubkey_toString(this.pubkey) const box = this.box.toString() return `${pubkey}.${box}` } public static async fromString(data: string): Promise { log.trace('fromString') const parts = data.split('.') if (parts.length < 2) return null const pubkey = await PrivateBox.pubkey_fromString(parts[0]) if (pubkey === null) return null const box = SecretBox.fromString(parts.slice(1).join('.')) if (box === null) return null return new PrivateBox(pubkey, box) } public static async pubkey_toString(pubkey: CryptoKey): Promise { return await misc.pubkey_toString(pubkey) } public static async pubkey_fromString(pubkey: string): Promise { return await misc.pubkey_fromString(pubkey, misc.Usage.ecdh) } }