Files
List_ultimate/app/composables/crypto.ts

199 lines
3.4 KiB
TypeScript

import sodium from "libsodium-wrappers"
export type KeyPair = {
publicKey: Uint8Array
privateKey: Uint8Array
}
export type EncryptedPayload = {
nonce: Uint8Array
cipher: Uint8Array
}
export type EncryptedPrivateKey = {
nonce: Uint8Array
cipher: Uint8Array
salt: Uint8Array
}
export const useCryptoStore = () => {
let ready = false
const init = async (): Promise<void> => {
if (!ready) {
await sodium.ready
ready = true
}
}
/**
* USER KEY PAIR
*/
const generateUserKeyPair = (): KeyPair => {
const pair = sodium.crypto_box_keypair()
return {
publicKey: pair.publicKey,
privateKey: pair.privateKey
}
}
/**
* MASTER KEY
*/
const generateMasterKey = (): Uint8Array => {
return sodium.randombytes_buf(
sodium.crypto_secretbox_KEYBYTES
)
}
/**
* ENCRYPT PRIVATE KEY
*/
const encryptPrivateKey = (
privateKey: Uint8Array,
masterKey: Uint8Array
): EncryptedPayload => {
const nonce = sodium.randombytes_buf(
sodium.crypto_secretbox_NONCEBYTES
)
const cipher = sodium.crypto_secretbox_easy(
privateKey,
nonce,
masterKey
)
return { nonce, cipher }
}
/**
* DECRYPT PRIVATE KEY
*/
const decryptPrivateKey = (
encrypted: EncryptedPayload,
masterKey: Uint8Array
): Uint8Array => {
return sodium.crypto_secretbox_open_easy(
encrypted.cipher,
encrypted.nonce,
masterKey
)
}
/**
* LIST KEY
*/
const generateListKey = (): Uint8Array => {
return sodium.randombytes_buf(
sodium.crypto_aead_xchacha20poly1305_ietf_KEYBYTES
)
}
/**
* ENCRYPT LIST DATA
*/
const encryptList = (
data: string,
listKey: Uint8Array
): EncryptedPayload => {
const nonce = sodium.randombytes_buf(
sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
)
const cipher = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
sodium.from_string(data),
null,
null,
nonce,
listKey
)
return { nonce, cipher }
}
/**
* DECRYPT LIST DATA
*/
const decryptList = (
encrypted: EncryptedPayload,
listKey: Uint8Array
): string => {
const decrypted = sodium.crypto_aead_xchacha20poly1305_ietf_decrypt(
null,
encrypted.cipher,
null,
encrypted.nonce,
listKey
)
return sodium.to_string(decrypted)
}
/**
* ENCRYPT LIST KEY FOR USER
*/
const encryptListKeyForUser = (
listKey: Uint8Array,
recipientPublicKey: Uint8Array,
senderPrivateKey: Uint8Array
): EncryptedPayload => {
const nonce = sodium.randombytes_buf(
sodium.crypto_box_NONCEBYTES
)
const cipher = sodium.crypto_box_easy(
listKey,
nonce,
recipientPublicKey,
senderPrivateKey
)
return { nonce, cipher }
}
/**
* DECRYPT LIST KEY
*/
const decryptListKey = (
encrypted: EncryptedPayload,
senderPublicKey: Uint8Array,
recipientPrivateKey: Uint8Array
): Uint8Array => {
return sodium.crypto_box_open_easy(
encrypted.cipher,
encrypted.nonce,
senderPublicKey,
recipientPrivateKey
)
}
return {
init,
generateUserKeyPair,
generateMasterKey,
encryptPrivateKey,
decryptPrivateKey,
generateListKey,
encryptList,
decryptList,
encryptListKeyForUser,
decryptListKey
}
}