Implement sym box

This commit is contained in:
2024-05-14 15:24:01 +02:00
parent e4f6bf241a
commit 435976e837
2 changed files with 111 additions and 10 deletions
+54 -10
View File
@@ -1,23 +1,67 @@
import type {Result} from 'result'
import {Result} from 'result'
import * as misc from 'misc'
export type Key = void
export type Key = CryptoKey
export class SecretBox<T> {
public static gen_key() : Key {
throw "todo"
private readonly cipher: Uint8Array
private readonly iv: Uint8Array
private readonly phantom!: T
private constructor(iv: Uint8Array, cipher: Uint8Array) {
this.iv = iv
this.cipher = cipher
}
public static encrypt<T>(key: Key, data: Uint8Array) : SecretBox<T> {
throw "todo"
public static async gen_key(extractable: boolean = false): Promise<Key> {
return window.crypto.subtle.generateKey(
{
name: "AES-GCM",
length: 256,
},
extractable,
["encrypt", "decrypt"]
)
}
public decrypt(key: Key) : Result<Uint8Array> {
throw "todo"
public static async encrypt<T>(key: Key, data: Uint8Array): Promise<Result<SecretBox<T>>> {
const iv = window.crypto.getRandomValues(new Uint8Array(12))
const algorithm = {name: "AES-GCM", iv}
try {
const cipher = await window.crypto.subtle.encrypt(algorithm, key, data)
return Result.ok(new SecretBox(iv, new Uint8Array(cipher)))
} catch (_) {}
return Result.error([])
}
public async decrypt(key: Key): Promise<Result<Uint8Array>> {
const algorithm = {name: "AES-GCM", iv: this.iv}
try {
const cipher = await window.crypto.subtle.decrypt(algorithm, key, this.cipher)
const buffer = new Uint8Array(cipher)
return Result.ok(buffer)
} catch (_) {}
return Result.error([])
}
public toString() : string {
throw "todo"
const iv = misc.a2b64(this.iv)
const cipher = misc.a2b64(this.cipher)
return `${iv}.${cipher}`
}
public static fromString<T>(data: string) : Result<SecretBox<T>> {
throw "todo"
const parts = data.split(".")
if (parts.length !== 2) return Result.error([])
const iv = misc.b642a(parts[0])
const cipher = misc.b642a(parts[1])
if (iv.error()) return Result.error([])
if (cipher.error()) return Result.error([])
return Result.ok(new SecretBox(iv.unwrap(), cipher.unwrap()))
}
}