Implement boxes

This commit is contained in:
2024-05-21 16:00:16 +02:00
parent e515c80f36
commit d845ae1391
15 changed files with 920 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
import {beforeAll, expect, test} from 'bun:test'
import {type KeyPair, PrivateBox} from 'boxes/asymmetric'
let k1!: KeyPair;
let k2!: KeyPair;
beforeAll(async () => {
k1 = await PrivateBox.gen_keypair(false)
k2 = await PrivateBox.gen_keypair(true)
expect(k1[0].extractable).toBe(false)
expect(k1[1].extractable).toBe(true)
expect(k2[0].extractable).toBe(true)
expect(k2[1].extractable).toBe(true)
})
test('base case', async () => {
const [priv, pub] = k1
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await PrivateBox.encrypt<Uint8Array>(pub, data)).expect("Should encrypt the data")
const result = (await box.decrypt(priv)).expect("Should decrypt the data")
expect(result).toEqual(data)
})
test('toString and fromString are inverses', async () => {
const [priv, pub] = k1
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await PrivateBox.encrypt<Uint8Array>(pub, data)).expect("Should encrypt the data")
const str = box.toString()
const box2 = PrivateBox.fromString<Uint8Array>(str).expect("Should parse the string")
expect(box).toEqual(box2)
const plain = (await box2.decrypt(priv)).expect("Should decrypt the data")
expect(plain).toEqual(data)
})
test('Tampered cipher fails', async () => {
const [priv, pub] = k1
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await PrivateBox.encrypt<Uint8Array>(pub, data)).expect("Should encrypt the data")
// @ts-expect-error : Bypass privacy for test
box.cipher[0] += 1
;(await box.decrypt(priv)).expect_err("Should fail to decrypt the data")
})
test('Wrong pubkey should fail', async () => {
const [_priv, pub] = k1
const [priv, _pub] = k2
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await PrivateBox.encrypt(pub, data)).expect("Should encrypt the data")
;(await box.decrypt(priv)).expect_err("Should fail to decrypt the data")
})
+86
View File
@@ -0,0 +1,86 @@
import {beforeAll, expect, test} from 'bun:test'
import {PrivateWrap, type KeyPair} from 'boxes/private-wrap'
import * as sym from 'boxes/symmetric'
import * as signature from 'signature'
let k1!: KeyPair;
let k2!: KeyPair;
let kw_sym!: sym.Key;
let kw_sig!: signature.KeyPair;
let kw_sym_non!: sym.Key;
let kw_sig_non!: signature.KeyPair;
beforeAll(async () => {
k1 = await PrivateWrap.gen_key(false)
k2 = await PrivateWrap.gen_key(true)
expect(k1[0].extractable).toBe(false)
expect(k1[1].extractable).toBe(true)
expect(k2[0].extractable).toBe(true)
expect(k2[1].extractable).toBe(true)
kw_sym = await sym.SecretBox.gen_key(true)
expect(kw_sym.extractable).toBe(true)
kw_sig = await signature.gen_keypair(true)
expect(kw_sig[0].extractable).toBe(true)
kw_sym_non = await sym.SecretBox.gen_key(false)
expect(kw_sym_non.extractable).toBe(false)
kw_sig_non = await signature.gen_keypair(false)
expect(kw_sig_non[0].extractable).toBe(false)
})
test('base case', async () => {
const [priv, pub] = k1
expect(pub.type).toBe("public")
const sym = (await PrivateWrap.wrap(pub, kw_sym)).expect("Should wrap the sym key")
const rsym = (await sym.unwrap(priv)).expect("Should unwrap the sym key")
expect(rsym).toEqual(kw_sym)
const sig = (await PrivateWrap.wrap(pub, kw_sig[0])).expect("Should wrap the signature key")
const rsig = (await sig.unwrap(priv)).expect("Should unwrap the signature key")
expect(rsig).toEqual(kw_sig[0])
})
test('toString and fromString and inverses', async () => {
const [_priv, pub] = k1
const sym = (await PrivateWrap.wrap(pub, kw_sym)).expect("Should wrap the sym key")
const sym_str = sym.toString()
const rsym = (PrivateWrap.fromString(sym_str)).expect("Should parse the sym key")
expect(rsym).toEqual(sym)
const sig = (await PrivateWrap.wrap(pub, kw_sig[0])).expect("Should wrap the signature key")
const sig_str = sig.toString()
const rsig = (PrivateWrap.fromString(sig_str)).expect("Should parse the signature key")
expect(rsig).toEqual(sig)
})
test("Can't wrap with private key", async () => {
const [priv, _pub] = k1
;(await PrivateWrap.wrap(priv, kw_sym)).expect_err("Shouldn't wrap with private key")
})
test("Can't unwrap with public key", async () => {
const [_priv, pub] = k1
const sym = (await PrivateWrap.wrap(pub, kw_sym)).expect("Should wrap the sym key")
;(await sym.unwrap(pub)).expect_err("Shouldn't unwrap with public key")
})
test("Can't unwrap with wrong private key", async () => {
const [_priv, pub] = k1
const sym = (await PrivateWrap.wrap(pub, kw_sym)).expect("Should wrap the sym key")
const [priv, _pub] = k2
;(await sym.unwrap(priv)).expect_err("Shouldn't unwrap with wrong private key")
})
test("Can't wrap if not extractable", async () => {
const [_priv, pub] = k1
;(await PrivateWrap.wrap(pub, kw_sym_non)).expect_err("Shouldn't wrap if not extractable")
;(await PrivateWrap.wrap(pub, kw_sig_non[0])).expect_err("Shouldn't wrap if not extractable")
})
+53
View File
@@ -0,0 +1,53 @@
import {beforeAll, expect, test} from 'bun:test'
import {PwdWrap} from '../../src/boxes'
import * as sym from '../../src/boxes/symmetric'
import * as asym from '../../src/boxes/asymmetric'
let kw_sym!: sym.Key;
let kw_asym!: asym.KeyPair;
beforeAll(async () => {
kw_sym = await sym.SecretBox.gen_key(true)
expect(kw_sym.extractable).toBe(true)
kw_asym = await asym.PrivateBox.gen_keypair(true)
expect(kw_asym[0].extractable).toBe(true)
})
test('base case', async () => {
const pwd = "password"
const testit = async (key: CryptoKey) => {
console.log(`Testing ${key.type} key with usage ${key.usages}`)
const wrapped = (await PwdWrap.wrap(pwd, key)).expect("Should wrap the key")
const unwrapped = (await wrapped.unwrap(pwd)).expect("Should unwrap the key")
expect(unwrapped).toEqual(key)
}
await testit(kw_sym)
await testit(kw_asym[0])
})
test('Fails with wrong password', async () => {
const pwd1 = "AwesomePassword123!"
const pwd2 = "AwesomePassword321!"
expect(pwd1).not.toEqual(pwd2)
const wrapped = (await PwdWrap.wrap(pwd1, kw_sym)).expect("Should wrap the key")
;(await wrapped.unwrap(pwd2)).expect_err("Shouldn't unwrap the key with wrong password")
})
test('toString and fromString are inverses', async () => {
const pwd = "password"
const wrapped = (await PwdWrap.wrap(pwd, kw_sym)).expect("Should wrap the key")
const str = wrapped.toString()
const wrapped2 = PwdWrap.fromString(str).expect("Should unwrap the key")
expect(wrapped2).toEqual(wrapped)
const unwrapped = (await wrapped.unwrap(pwd)).expect("Should unwrap the key")
expect(unwrapped).toEqual(kw_sym)
})
+52
View File
@@ -0,0 +1,52 @@
import {expect, test} from 'bun:test'
import * as pwd from 'boxes/pwd'
test('base case', async () => {
const password = "AwesomePassword123!"
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = await pwd.PwdBox.encrypt<Uint8Array>(password, data)
const result = (await box.decrypt(password)).expect("Should decrypt the data")
expect(result).toEqual(data)
})
test('wrong password', async () => {
const password1 = "AwesomePassword123!"
const password2 = "AwesomePassword321!"
expect(password1).not.toEqual(password2)
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = await pwd.PwdBox.encrypt<Uint8Array>(password1, data)
;(await box.decrypt(password2)).expect_err("Should not decrypt the data with the wrong password")
})
test('toString and fromString are inverses', async () => {
const password = "AwesomePassword123!"
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = await pwd.PwdBox.encrypt<Uint8Array>(password, data)
const str = box.toString()
const box2 = pwd.PwdBox.fromString<Uint8Array>(str).expect("Should be able to parse the string")
expect(box2).toEqual(box)
const result = (await box2.decrypt(password)).expect("Should decrypt the data")
expect(result).toEqual(data)
})
test('tampered salt should fail', async () => {
const password = "AwesomePassword123!"
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = await pwd.PwdBox.encrypt<Uint8Array>(password, data)
// @ts-expect-error : I know salt is private, but I want to test it
box.salt[0] += 1
;(await box.decrypt(password)).expect_err("Should not decrypt the data with a tampered salt")
})
+102
View File
@@ -0,0 +1,102 @@
import {beforeAll, expect, test} from 'bun:test'
import {SecretWrap, type Key} from 'boxes/secret-wrap'
import * as sym from 'boxes/symmetric'
import * as asym from 'boxes/asymmetric'
import * as signature from 'signature'
import * as pwrap from 'boxes/private-wrap'
let k1!: Key;
let k2!: Key;
let kw_wrap!: sym.Key;
let kw_sym!: sym.Key;
let kw_sig!: signature.KeyPair;
let kw_asym!: asym.KeyPair;
let kw_priv!: pwrap.KeyPair;
let kw_wrap_non!: sym.Key;
let kw_sym_non!: sym.Key;
let kw_sig_non!: signature.KeyPair;
let kw_asym_non!: asym.KeyPair;
let kw_priv_non!: pwrap.KeyPair;
beforeAll(async () => {
k1 = await SecretWrap.gen_key(false)
k2 = await SecretWrap.gen_key(true)
expect(k1.extractable).toBe(false)
expect(k2.extractable).toBe(true)
kw_wrap = await sym.SecretBox.gen_key(true)
expect(kw_wrap.extractable).toBe(true)
kw_asym = await asym.PrivateBox.gen_keypair(true)
expect(kw_asym[0].extractable).toBe(true)
kw_priv = await pwrap.PrivateWrap.gen_key(true)
expect(kw_priv[0].extractable).toBe(true)
kw_sym = await sym.SecretBox.gen_key(true)
expect(kw_sym.extractable).toBe(true)
kw_sig = await signature.gen_keypair(true)
expect(kw_sig[0].extractable).toBe(true)
kw_wrap_non = await sym.SecretBox.gen_key(false)
expect(kw_wrap_non.extractable).toBe(false)
kw_asym_non = await asym.PrivateBox.gen_keypair(false)
expect(kw_asym_non[0].extractable).toBe(false)
kw_priv_non = await pwrap.PrivateWrap.gen_key(false)
expect(kw_priv_non[0].extractable).toBe(false)
kw_sym_non = await sym.SecretBox.gen_key(false)
expect(kw_sym_non.extractable).toBe(false)
kw_sig_non = await signature.gen_keypair(false)
expect(kw_sig_non[0].extractable).toBe(false)
})
test('base case', async () => {
const testit = async (key: CryptoKey) => {
console.log(`Testing ${key.type} key with usage ${key.usages}`)
const wrapped = (await SecretWrap.wrap_key(k1, key)).expect("Should wrap the key")
const unwrapped = (await wrapped.unwrap(k1)).expect("Should unwrap the key")
expect(unwrapped).toEqual(key)
}
await testit(kw_wrap)
await testit(kw_asym[0])
await testit(kw_priv[0])
await testit(kw_sym)
await testit(kw_sig[0])
})
test("toString and fromString and inverses", async () => {
const testit = async (key: CryptoKey) => {
console.log(`Testing ${key.type} key with usage ${key.usages}`)
const wrapped = (await SecretWrap.wrap_key(k1, key)).expect("Should wrap the key")
const wrapped_str = wrapped.toString()
const unwrapped = (SecretWrap.fromString(wrapped_str)).expect("Should parse the key")
expect(unwrapped).toEqual(wrapped)
}
await testit(kw_wrap)
await testit(kw_asym[0])
await testit(kw_priv[0])
await testit(kw_sym)
await testit(kw_sig[0])
})
test("Can't unwrap with wrong key", async () => {
const wrapped = (await SecretWrap.wrap_key(k1, kw_wrap)).expect("Should wrap the key")
;(await wrapped.unwrap(k2)).expect_err("Shouldn't unwrap with wrong key")
})
test("Can't wrap if key is not extractable", async () => {
;(await SecretWrap.wrap_key(k1, kw_wrap_non)).expect_err("Shouldn't wrap if key is not extractable")
;(await SecretWrap.wrap_key(k1, kw_asym_non[0])).expect_err("Shouldn't wrap if key is not extractable")
;(await SecretWrap.wrap_key(k1, kw_priv_non[0])).expect_err("Shouldn't wrap if key is not extractable")
;(await SecretWrap.wrap_key(k1, kw_sym_non)).expect_err("Shouldn't wrap if key is not extractable")
;(await SecretWrap.wrap_key(k1, kw_sig_non[0])).expect_err("Shouldn't wrap if key is not extractable")
})
test("tampered IV", async () => {
const wrapped = (await SecretWrap.wrap_key(k1, kw_wrap)).expect("Should wrap the key")
// @ts-expect-error
wrapped.iv[0] += 1
;(await wrapped.unwrap(k1)).expect_err("Shouldn't unwrap with tampered IV")
})
+57
View File
@@ -0,0 +1,57 @@
import {expect, test} from 'bun:test'
import * as symmetric from 'boxes/symmetric'
test('base case', async () => {
const key = await symmetric.SecretBox.gen_key()
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await symmetric.SecretBox.encrypt<Uint8Array>(key, data)).expect("Should encrypt the data")
const result = (await box.decrypt(key)).expect("Should decrypt the data")
expect(result).toEqual(data)
})
test('toString and fromString are inverses', async () => {
const key = await symmetric.SecretBox.gen_key()
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await symmetric.SecretBox.encrypt<Uint8Array>(key, data)).expect("Should encrypt the data")
const str = box.toString()
const box2 = symmetric.SecretBox.fromString<Uint8Array>(str).expect("Should parse the string")
expect(box).toEqual(box2)
const plain = (await box2.decrypt(key)).expect("Should decrypt the data")
expect(plain).toEqual(data)
})
test('tampered cipher fails', async () => {
const key = await symmetric.SecretBox.gen_key()
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await symmetric.SecretBox.encrypt<Uint8Array>(key, data)).expect("Should encrypt the data")
// @ts-expect-error : This is a test, so it's OK to access private field
box.cipher[0] += 1
;(await box.decrypt(key)).expect_err("Should fail to decrypt the data")
})
test('Wrong key fails', async () => {
const key1 = await symmetric.SecretBox.gen_key()
const key2 = await symmetric.SecretBox.gen_key()
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await symmetric.SecretBox.encrypt(key1, data)).expect("Should encrypt the data")
;(await box.decrypt(key2)).expect_err("Should fail to decrypt the data")
})
test('tampered IV fails', async () => {
const key = await symmetric.SecretBox.gen_key()
const data = new Uint8Array([1, 2, 3, 4, 5])
const box = (await symmetric.SecretBox.encrypt<Uint8Array>(key, data)).expect("Should encrypt the data")
// @ts-expect-error : This is a test, so it's OK to access private field
box.iv[0] += 1
;(await box.decrypt(key)).expect_err("Should fail to decrypt the data")
})