Allow to add context on key derivations
This commit is contained in:
+19
-5
@@ -13,7 +13,7 @@ export enum DHusage {
|
||||
wrap
|
||||
}
|
||||
|
||||
export async function hkdf(key: Uint8Array, usage: Usage): Promise<CryptoKey> {
|
||||
export async function hkdf(key: Uint8Array, usage: Usage, context?: string): Promise<CryptoKey> {
|
||||
log.trace('HKDF')
|
||||
log.trace(`usage : ${usage}`)
|
||||
|
||||
@@ -53,7 +53,7 @@ export async function hkdf(key: Uint8Array, usage: Usage): Promise<CryptoKey> {
|
||||
throw 'Unknown usage for HDKF'
|
||||
}
|
||||
}
|
||||
const info = new TextEncoder().encode(info_txt)
|
||||
const info = new TextEncoder().encode(info_txt + '-' + (context ?? 'key'))
|
||||
|
||||
return await crypto.subtle.deriveKey(
|
||||
{
|
||||
@@ -87,15 +87,29 @@ export async function pbkdf(salt: Uint8Array, password: string): Promise<Uint8Ar
|
||||
|
||||
return new Uint8Array(buffer)
|
||||
}
|
||||
export async function ecdh(privkey: CryptoKey, pubkey: CryptoKey, usage: DHusage): Promise<CryptoKey> {
|
||||
export async function ecdh(privkey: CryptoKey, pubkey: CryptoKey, usage: DHusage, context?: string): Promise<CryptoKey> {
|
||||
log.trace('ecdh')
|
||||
const outputUsage: KeyUsage[] = usage === DHusage.box ? ['encrypt', 'decrypt'] : ['wrapKey', 'unwrapKey']
|
||||
return await crypto.subtle.deriveKey(
|
||||
|
||||
const seed_bits = await crypto.subtle.deriveBits(
|
||||
{
|
||||
name: consts.ECDH.name,
|
||||
public: pubkey
|
||||
},
|
||||
privkey,
|
||||
256
|
||||
)
|
||||
|
||||
const seed = await crypto.subtle.importKey('raw', seed_bits, 'HKDF', false, ['deriveKey'])
|
||||
|
||||
const outputUsage: KeyUsage[] = usage === DHusage.box ? ['encrypt', 'decrypt'] : ['wrapKey', 'unwrapKey']
|
||||
return await crypto.subtle.deriveKey(
|
||||
{
|
||||
name: 'HKDF',
|
||||
hash: 'SHA-512',
|
||||
salt: new Uint8Array(16),
|
||||
info: new TextEncoder().encode('ECDH-' + (context ?? 'key'))
|
||||
},
|
||||
seed,
|
||||
{
|
||||
name: consts.ENCRYPTION,
|
||||
length: 256
|
||||
|
||||
+5
-5
@@ -14,19 +14,19 @@ export default class PrivateBox {
|
||||
|
||||
public static async gen(extractable: boolean = true): Promise<CryptoKeyPair> {
|
||||
log.trace('generate keypair')
|
||||
return await crypto.subtle.generateKey(consts.ECDH, extractable, ['deriveKey']) as CryptoKeyPair
|
||||
return await crypto.subtle.generateKey(consts.ECDH, extractable, ['deriveBits']) as CryptoKeyPair
|
||||
}
|
||||
|
||||
public static async encrypt(data: Uint8Array, pubkey: CryptoKey): Promise<PrivateBox> {
|
||||
public static async encrypt(data: Uint8Array, pubkey: CryptoKey, context?: string): Promise<PrivateBox> {
|
||||
log.trace('encrypt')
|
||||
const tmp_pair = await PrivateBox.gen(false)
|
||||
const key = await ecdh(tmp_pair.privateKey, pubkey, DHusage.box)
|
||||
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): Promise<Uint8Array | null> {
|
||||
public async decrypt(privkey: CryptoKey, context?: string): Promise<Uint8Array | null> {
|
||||
log.trace('decrypt')
|
||||
const key = await ecdh(privkey, this.pubkey, DHusage.box)
|
||||
const key = await ecdh(privkey, this.pubkey, DHusage.box, context) // TODO : null
|
||||
return await this.box.decrypt(key)
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -14,19 +14,19 @@ export default class PrivateWrap {
|
||||
|
||||
public static async gen(extractable: boolean = true): Promise<CryptoKeyPair> {
|
||||
log.trace('generate keypair')
|
||||
return await crypto.subtle.generateKey(consts.ECDH, extractable, ['deriveKey']) as CryptoKeyPair
|
||||
return await crypto.subtle.generateKey(consts.ECDH, extractable, ['deriveBits']) as CryptoKeyPair
|
||||
}
|
||||
|
||||
public static async wrap(data: CryptoKey, pubkey: CryptoKey): Promise<PrivateWrap> {
|
||||
public static async wrap(data: CryptoKey, pubkey: CryptoKey, context?: string): Promise<PrivateWrap> {
|
||||
log.trace('wrap')
|
||||
const tmp_keypair = await PrivateWrap.gen()
|
||||
const kd = await ecdh(tmp_keypair.privateKey, pubkey, DHusage.wrap)
|
||||
const kd = await ecdh(tmp_keypair.privateKey, pubkey, DHusage.wrap, context) // TODO : null
|
||||
const box = await SecretWrap.wrap(data, kd)
|
||||
return new this(box, tmp_keypair.publicKey)
|
||||
}
|
||||
public async unwrap(privkey: CryptoKey): Promise<CryptoKey | null> {
|
||||
public async unwrap(privkey: CryptoKey, context?: string): Promise<CryptoKey | null> {
|
||||
log.trace('unwrap')
|
||||
const kd = await ecdh(privkey, this.pubkey, DHusage.wrap)
|
||||
const kd = await ecdh(privkey, this.pubkey, DHusage.wrap, context) // TODO : null
|
||||
return await this.box.unwrap(kd)
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -11,21 +11,21 @@ export default class PwdBox {
|
||||
private readonly salt: Uint8Array
|
||||
) {}
|
||||
|
||||
private static async derive(pwd: string, salt: Uint8Array): Promise<CryptoKey> {
|
||||
const k = await pbkdf(salt, pwd)
|
||||
return await hkdf(k, Usage.box) as CryptoKey
|
||||
private static async derive(pwd: string, salt: Uint8Array, context?: string): Promise<CryptoKey> {
|
||||
const k = await pbkdf(salt, pwd) // TODO : null
|
||||
return await hkdf(k, Usage.box, context) as CryptoKey // TODO : null
|
||||
}
|
||||
|
||||
public static async encrypt(data: Uint8Array, pwd: string): Promise<PwdBox> {
|
||||
public static async encrypt(data: Uint8Array, pwd: string, context?: string): Promise<PwdBox> {
|
||||
log.trace('encrypt')
|
||||
const salt = crypto.getRandomValues(new Uint8Array(16))
|
||||
const k = await PwdBox.derive(pwd, salt)
|
||||
const box = await SecretBox.encrypt(data, k)
|
||||
const k = await PwdBox.derive(pwd, salt, context) // TODO : null
|
||||
const box = await SecretBox.encrypt(data, k) // TODO : null
|
||||
return new PwdBox(box, salt)
|
||||
}
|
||||
public async decrypt(pwd: string): Promise<Uint8Array | null> {
|
||||
public async decrypt(pwd: string, context?: string): Promise<Uint8Array | null> {
|
||||
log.trace('decrypt')
|
||||
const k = await PwdBox.derive(pwd, this.salt)
|
||||
const k = await PwdBox.derive(pwd, this.salt, context) // TODO : null
|
||||
return await this.box.decrypt(k)
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -11,21 +11,21 @@ export default class PwdWrap {
|
||||
private readonly salt: Uint8Array
|
||||
) {}
|
||||
|
||||
private static async derive(pwd: string, salt: Uint8Array): Promise<CryptoKey> {
|
||||
const k = await pbkdf(salt, pwd)
|
||||
return await hkdf(k, Usage.wrap) as CryptoKey
|
||||
private static async derive(pwd: string, salt: Uint8Array, context?: string): Promise<CryptoKey> {
|
||||
const k = await pbkdf(salt, pwd) // TODO : null
|
||||
return await hkdf(k, Usage.wrap, context) as CryptoKey // TODO : null
|
||||
}
|
||||
|
||||
public static async wrap(data: CryptoKey, pwd: string): Promise<PwdWrap> {
|
||||
public static async wrap(data: CryptoKey, pwd: string, context?: string): Promise<PwdWrap> {
|
||||
log.trace('wrap')
|
||||
const salt = crypto.getRandomValues(new Uint8Array(16))
|
||||
const k = await PwdWrap.derive(pwd, salt)
|
||||
const box = await SecretWrap.wrap(data, k)
|
||||
const k = await PwdWrap.derive(pwd, salt, context) // TODO : null
|
||||
const box = await SecretWrap.wrap(data, k) // TODO : null
|
||||
return new PwdWrap(box, salt)
|
||||
}
|
||||
public async unwrap(pwd: string): Promise<CryptoKey | null> {
|
||||
public async unwrap(pwd: string, context?: string): Promise<CryptoKey | null> {
|
||||
log.trace('unwrap')
|
||||
const k = await PwdWrap.derive(pwd, this.salt)
|
||||
const k = await PwdWrap.derive(pwd, this.salt, context) // TODO : null
|
||||
return await this.box.unwrap(k)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user