Untitled

mail@pastecode.io avatar
unknown
javascript
17 days ago
5.7 kB
3
Indexable
Never
import sodium from "libsodium-wrappers-sumo"

const transformValueToHex = async (value: string | Uint8Array) => {
	await sodium.ready

	return sodium.to_hex(value)
}

const transformValueToBin = async (value: string) => {
	await sodium.ready

	return sodium.from_hex(value)
}

const generateMasterKey = async (password: string, userNonce = null) => {
	try {
		await sodium.ready

		const nonce = sodium.randombytes_buf(sodium.crypto_pwhash_SALTBYTES)
		const key = sodium.crypto_pwhash(
			sodium.crypto_secretbox_KEYBYTES, // Taille de la clé
			password, // Mot de passe pour la dérivation
			userNonce ? userNonce : nonce, // Sel pour la dérivation
			sodium.crypto_pwhash_OPSLIMIT_MODERATE, // Nombre d'opérations (complexité)
			sodium.crypto_pwhash_MEMLIMIT_MODERATE, // Mémoire utilisée
			sodium.crypto_pwhash_ALG_ARGON2ID13, // Algorithme Argon2id
		)

		return { key: key, nonce: userNonce ? userNonce : nonce }
	} catch (error) {
		console.error(
			"Erreur lors de la génération de la clé maîtresse:",
			error,
		)
	}
}

const generateKeyPair = async (masterKey: Uint8Array) => {
	await sodium.ready

	const keyPair = sodium.crypto_box_keypair()
	const { encryptedPrivateKey, noncePrivate } = await encryptPrivateKey(
		keyPair.privateKey,
		masterKey,
	)

	const noncePublic = sodium.randombytes_buf(
		sodium.crypto_secretbox_NONCEBYTES,
	)

	return {
		publicKey: keyPair.publicKey,
		privateKey: encryptedPrivateKey,
		noncePrivateKey: noncePrivate,
		noncePublic: noncePublic,
	}
}

const generateCredentialKeyPair = async (publicKey: string) => {
	await sodium.ready

	const keyPair = sodium.crypto_box_keypair()

	const encryptedCategoryPrivateKey = sodium.crypto_box_seal(
		keyPair.privateKey,
		sodium.from_hex(publicKey),
	)

	return {
		credentialPublicKey: sodium.to_hex(keyPair.publicKey),
		credentialPrivateKey: sodium.to_hex(encryptedCategoryPrivateKey),
	}
}

const encryptPublicKey = async (
	publicKey: string,
	isForDemo: boolean,
	firstHash: Uint8Array,
	secondHash: Uint8Array,
) => {
	await sodium.ready

	const textEncoder = new TextEncoder()

	const nonceEncryptedPublicKey = sodium.randombytes_buf(
		sodium.crypto_secretbox_NONCEBYTES,
	)

	const firstHashForDemo = textEncoder.encode("0123456789abcdefghijvbnm")

	const secondHashForDemo = textEncoder.encode(
		"827ccb0eea8a706c4c34a16891f84e7b",
	)

	// Ici les hash sont en dur, mais seront dynamiques plus tard
	const encryptedPublicKey = sodium.crypto_secretbox_easy(
		publicKey,
		isForDemo ? secondHashForDemo : secondHash,
		isForDemo ? firstHashForDemo : firstHash,
	)

	return { encryptedPublicKey, nonceEncryptedPublicKey }
}

// Chiffre la clé privée, renvoie la clé chiffrée avec son nonce pour l'envoyer en base

const encryptPrivateKey = async (
	privateKey: Uint8Array,
	masterKey: Uint8Array,
) => {
	await sodium.ready

	const noncePrivate = sodium.randombytes_buf(
		sodium.crypto_secretbox_NONCEBYTES,
	)

	const encryptedPrivateKey = sodium.crypto_secretbox_easy(
		privateKey,
		noncePrivate,
		masterKey,
	)

	return { encryptedPrivateKey, noncePrivate }
}

// Décrypte les mdp, fichiers... Avec la clé privée
const decryptPrivateKey = async (
	encryptedPrivateKey: string,
	privateKeyNonce: Uint8Array,
	masterKey: Uint8Array,
) => {
	await sodium.ready

	try {
		const decrypted = sodium.crypto_secretbox_open_easy(
			encryptedPrivateKey,
			privateKeyNonce,
			masterKey,
		)
		return { decrypted }
	} catch (e) {
		console.error(e)
		return { decryptedError: e }
	}
}

// Gérer le chiffrement avec la clé publique

const encryptWithPublicKey = async (data: string, publicKey: string) => {
	await sodium.ready

	const encryptedData = sodium.crypto_box_seal(
		data,
		sodium.from_hex(publicKey),
	)

	return encryptedData
}

const encryptPasswordWithPublicKey = async (
	data: string,
	publicKey: string,
) => {
	await sodium.ready

	const encodedData = sodium.from_string(data)

	const encryptedData = sodium.crypto_box_seal(
		encodedData,
		sodium.from_hex(publicKey),
	)

	return encryptedData
}

const importKey = async (masterKey: Uint8Array) => {
	return await window.crypto.subtle.importKey(
		"raw",
		masterKey,
		{ name: "AES-GCM" },
		false,
		["encrypt", "decrypt"],
	)
}

const encryptString = async (str: string, key: CryptoKey) => {
	const iv = window.crypto.getRandomValues(new Uint8Array(12))
	const encoder = new TextEncoder()
	const encoded = encoder.encode(str)
	const encrypted = await window.crypto.subtle.encrypt(
		{ name: "AES-GCM", iv },
		key,
		encoded,
	)

	return { encrypted, iv }
}

const handleEncrypt = async (dataToEncrypt: string, masterKey: Uint8Array) => {
	try {
		const key = await importKey(masterKey)
		const encrypted = await encryptString(dataToEncrypt, key)

		return encrypted
	} catch (error) {
		console.error("Erreur lors du chiffrement:", error)
	}
}

// Gestion du déchiffrement
const handleDecrypt = async (encryptedData: string, privateKey: Uint8Array) => {
	try {
		await sodium.ready

		const publicKey = sodium.crypto_scalarmult_base(privateKey)

		const decryptedKey = sodium.crypto_box_seal_open(
			sodium.from_hex(encryptedData),
			publicKey,
			privateKey,
		)

		return sodium.from_hex(sodium.to_string(decryptedKey))
	} catch (error) {
		console.error("Erreur lors du déchiffrement:", error)
	}
}

const signTokenWithKey = async (tokenXLS: string, key: Uint8Array) => {
	await sodium.ready

	return sodium.crypto_sign_detached(tokenXLS, key)
}

export {
	generateMasterKey,
	generateKeyPair,
	generateCredentialKeyPair,
	encryptPublicKey,
	encryptPrivateKey,
	decryptPrivateKey,
	encryptWithPublicKey,
	encryptPasswordWithPublicKey,
	importKey,
	handleEncrypt,
	handleDecrypt,
	transformValueToBin,
	transformValueToHex,
	signTokenWithKey,
}
Leave a Comment