Implement PrivateWrap
ci/woodpecker/push/test Pipeline failed

Closes #7
This commit is contained in:
2024-05-14 22:24:33 +02:00
parent 3d2fe5f517
commit 528ccbdad7
3 changed files with 197 additions and 0 deletions
+1
View File
@@ -1,3 +1,4 @@
export {PrivateBox} from './asymmetric'
export {SecretBox} from './symmetric'
export {PwdBox} from './pwd'
export {PrivateWrap} from './private-wrap'
+110
View File
@@ -0,0 +1,110 @@
import {Result} from 'result'
import * as misc from 'misc'
export type PubKey = CryptoKey
export type PrivKey = CryptoKey
export type KeyPair = [PrivKey, PubKey]
const algorithm: RsaOaepParams = {name: "RSA-OAEP"}
export class PrivateWrap {
private readonly wrapped_key: Uint8Array
private readonly usage: KeyUsage[]
private readonly algorithm: Algorithm
private readonly format: KeyFormat
private constructor(key: Uint8Array, algorithm: Algorithm, usage: KeyUsage[], format: KeyFormat) {
this.wrapped_key = key
this.algorithm = algorithm
this.usage = usage
this.format = format
}
/**
* Create a new keypair for signing
* @param extractable if the keys must be extractable or not
* @return [privkey, pubkey] keys
*/
public static async gen_key(extractable: boolean = false) : Promise<KeyPair> {
let key = await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096,
publicExponent: new Uint8Array([1, 0, 1]),
hash: {name: "SHA-512"},
},
extractable,
["wrapKey", "unwrapKey"]
)
return [key.privateKey, key.publicKey]
}
/**
* Wrap a key using a public key
*
* Kinda makes sense, but it can't wrap an RSA encryption key
* @param pubkey used to wrap
* @param key to wrap
* @return an error if the key is not extractable
*/
public static async wrap(pubkey: PubKey, key: CryptoKey) : Promise<Result<PrivateWrap>> {
const format = key.type === "secret" ? "raw" : "pkcs8"
try {
const wrapped = await window.crypto.subtle.wrapKey(
format,
key,
pubkey,
algorithm
)
return Result.ok(new PrivateWrap(new Uint8Array(wrapped), key.algorithm, key.usages, format))
} catch (_) {}
return Result.error([])
}
/**
* Unwrap a key using a private key
* @param privkey used to unwrap
*/
public async unwrap(privkey: PrivKey) : Promise<Result<CryptoKey>> {
try {
const key = await window.crypto.subtle.unwrapKey(
this.format,
this.wrapped_key,
privkey,
algorithm,
this.algorithm,
true,
this.usage
)
return Result.ok(key)
} catch(_) {}
return Result.error([])
}
public toString() : string {
const wrapped_key = misc.a2b64(this.wrapped_key)
return JSON.stringify({
wrapped_key,
algorithm: this.algorithm,
usage: this.usage,
format: this.format,
})
}
public static fromString(data: string) : Result<PrivateWrap> {
try {
const {wrapped_key: wrapped_key64, algorithm, usage, format}: {wrapped_key: string, algorithm: Algorithm, usage: KeyUsage[], format: KeyFormat} = JSON.parse(data)
const key = misc.b642a(wrapped_key64)
if (key.error()) return Result.error([])
return Result.ok(new PrivateWrap(key.unwrap(), algorithm, usage, format))
} catch (_) {}
return Result.error([])
}
}