Création d'un composable pour la gestion de la crypto, mise en place de l'initialisation de la première liste et sauvegarde de celle-ci. TODO NEXT : Récupération de la liste en la déchiffrant, mise en place d'une masterKey dérivée du mot de passe pour les utilisateurs non google, basculement vers la page des listes après connexion google etc.
This commit is contained in:
199
app/composables/crypto.ts
Normal file
199
app/composables/crypto.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user