diff --git a/src/constants.ts b/src/constants.ts index ea34768..78f9e77 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,12 +1,7 @@ -export const AES_ALGORITHM = 'AES-GCM'; -export const AES_KEY_BIT_LENGTH = 256; -export const AUX_BYTE_LEN = 16; -export const IV_LEN_BYTES = 16; +export const AES_KEY_BYTE_LENGTH = 32; +export const IV_LEN_BYTES = 12; -export const KEY_WRAPPING_ALGORITHM = 'AES-KW'; -export const KEY_FORMAT = 'raw'; export const CONTEXT_WRAPPING = 'CRYPTO library 2025-08-22 18:10:00 key derived from ecc and kyber secrets'; - export const CONTEXT_ENC_KEYSTORE = 'CRYPTO library 2025-07-30 16:18:03 key for opening encryption keys keystore'; export const CONTEXT_RECOVERY = 'CRYPTO library 2025-07-30 16:20:00 key for account recovery'; export const CONTEXT_INDEX = 'CRYPTO library 2025-07-30 17:20:00 key for protecting current search indices'; @@ -23,8 +18,6 @@ export const KYBER768_PUBLIC_KEY_LENGTH = 1184; export const KYBER768_SECRET_KEY_LENGTH = 2400; export const KYBER_SEED_LENGTH = 64; -export const HASH_BIT_LEN = 256; - export const MAX_CACHE_SIZE = 600000000; // 600 MB export const MAX_EMAIL_PER_BATCH = 100; export const DB_LABEL = 'email'; diff --git a/src/derive-key/deriveKeysFromKey.ts b/src/derive-key/deriveKeysFromKey.ts index 0a86aed..9c60b59 100644 --- a/src/derive-key/deriveKeysFromKey.ts +++ b/src/derive-key/deriveKeysFromKey.ts @@ -1,5 +1,5 @@ import { blake3 } from '@noble/hashes/blake3.js'; -import { AES_KEY_BIT_LENGTH, CONTEXT_DERIVE } from '../constants'; +import { AES_KEY_BYTE_LENGTH, CONTEXT_DERIVE } from '../constants'; import { UTF8ToUint8 } from '../utils'; /** @@ -39,8 +39,8 @@ export function deriveSymmetricKeyFromTwoKeysAndContext( context: string, ): Uint8Array { try { - if (key2.length != AES_KEY_BIT_LENGTH / 8 || key1.length != AES_KEY_BIT_LENGTH / 8) { - throw new Error(`Input key length must be exactly ${AES_KEY_BIT_LENGTH / 8} bytes`); + if (key2.length != AES_KEY_BYTE_LENGTH || key1.length != AES_KEY_BYTE_LENGTH) { + throw new Error(`Input key length must be exactly ${AES_KEY_BYTE_LENGTH} bytes`); } const key = blake3(key1, { key: key2 }); return blake3(key, { context: UTF8ToUint8(context) }); diff --git a/src/email-crypto/core.ts b/src/email-crypto/core.ts index b9b13f1..d539af7 100644 --- a/src/email-crypto/core.ts +++ b/src/email-crypto/core.ts @@ -3,7 +3,7 @@ import { encryptSymmetrically, decryptSymmetrically, genSymmetricKey } from '../ import { encapsulateHybrid, decapsulateHybrid } from '../hybrid-crypto'; import { wrapKey, unwrapKey } from '../key-wrapper'; import { getKeyFromPassword, getKeyFromPasswordAndSalt } from '../derive-key'; -import { UTF8ToUint8, base64ToUint8Array, uint8ArrayToBase64, uint8ToUTF8, uuidToBytes } from '../utils'; +import { UTF8ToUint8, base64ToUint8Array, uint8ArrayToBase64, uint8ToUTF8 } from '../utils'; import { getAux } from './utils'; /** @@ -29,12 +29,12 @@ export async function encryptEmailBody( let params = email.params; if (isSubjectEncrypted) { - const result = await encryptEmailContentAndSubjectSymmetrically(email.body, email.params.subject, aux, email.id); + const result = await encryptEmailContentAndSubjectSymmetrically(email.body, email.params.subject, aux); enc = result.enc; encryptionKey = result.encryptionKey; params = { ...email.params, subject: result.encSubject }; } else { - const result = await encryptEmailContentSymmetrically(email.body, aux, email.id); + const result = await encryptEmailContentSymmetrically(email.body, aux); enc = result.enc; encryptionKey = result.encryptionKey; } @@ -86,20 +86,18 @@ export async function decryptEmailBody( * * @param email - The email to encrypt. * @param aux - The auxiliary data (e.g., email ID or timestamp) for AEAD. - * @param emailID - The unique identifier of the email. * @returns The resulting ciphertext and the used symmetric key */ export async function encryptEmailContentSymmetrically( email: EmailBody, aux: Uint8Array, - emailID: string, ): Promise<{ enc: EmailBodyEncrypted; encryptionKey: Uint8Array }> { try { if (!email.text) { throw new Error('Invalid input'); } const encryptionKey = genSymmetricKey(); - const enc = await encryptEmailContentSymmetricallyWithKey(email, encryptionKey, aux, emailID); + const enc = await encryptEmailContentSymmetricallyWithKey(email, encryptionKey, aux); return { enc, encryptionKey }; } catch (error) { throw new Error('Failed to symmetrically encrypt email', { cause: error }); @@ -112,21 +110,19 @@ export async function encryptEmailContentSymmetrically( * @param email - The email to encrypt. * @param subject - The email subject to encrypt. * @param aux - The auxiliary data (e.g., email ID or timestamp) for AEAD. - * @param emailID - The unique identifier of the email. * @returns The resulting ciphertext and the used symmetric key */ export async function encryptEmailContentAndSubjectSymmetrically( email: EmailBody, subject: string, aux: Uint8Array, - emailID: string, ): Promise<{ enc: EmailBodyEncrypted; encSubject: string; encryptionKey: Uint8Array }> { try { if (!subject || !email.text) { throw new Error('Invalid input'); } const encryptionKey = genSymmetricKey(); - const enc = await encryptEmailContentSymmetricallyWithKey(email, encryptionKey, aux, emailID); + const enc = await encryptEmailContentSymmetricallyWithKey(email, encryptionKey, aux); const subjectBuff = UTF8ToUint8(subject); const subjectEnc = await encryptSymmetrically(encryptionKey, subjectBuff, aux); const encSubject = uint8ArrayToBase64(subjectEnc); @@ -168,24 +164,21 @@ export async function decryptEmailAndSubjectSymmetrically( * @param emailBody - The email body to encrypt. * @param encryptionKey - The symmetric key for encryption. * @param aux - The auxiliary data (e.g., email ID or timestamp) for AEAD. - * @param emailID - The unique identifier of the email. * @returns The resulting encrypted emailBody */ export async function encryptEmailContentSymmetricallyWithKey( emailBody: EmailBody, encryptionKey: Uint8Array, aux: Uint8Array, - emailID: string, ): Promise { try { - const freeField = uuidToBytes(emailID); const text = UTF8ToUint8(emailBody.text); - const encryptedText = await encryptSymmetrically(encryptionKey, text, aux, freeField); + const encryptedText = await encryptSymmetrically(encryptionKey, text, aux); const encText = uint8ArrayToBase64(encryptedText); const result: EmailBodyEncrypted = { encText }; if (emailBody.attachments) { - const encryptedAttachements = await encryptEmailAttachements(emailBody.attachments, encryptionKey, aux, emailID); + const encryptedAttachements = await encryptEmailAttachements(emailBody.attachments, encryptionKey, aux); result.encAttachments = encryptedAttachements?.map(uint8ArrayToBase64); } return result; @@ -200,21 +193,18 @@ export async function encryptEmailContentSymmetricallyWithKey( * @param attachments - The attachments. * @param encryptionKey - The symmetric key. * @param aux - The auxiliary data (e.g., email ID or timestamp) for AEAD. - * @param emailID - The unique identifier of the email. * @returns The decrypted email attackements */ async function encryptEmailAttachements( attachments: string[], encryptionKey: Uint8Array, aux: Uint8Array, - emailID: string, ): Promise { try { - const freeField = uuidToBytes(emailID); const encryptedAttachments = await Promise.all( attachments.map((attachment) => { const binaryAttachment = UTF8ToUint8(attachment); - return encryptSymmetrically(encryptionKey, binaryAttachment, aux, freeField); + return encryptSymmetrically(encryptionKey, binaryAttachment, aux); }), ); return encryptedAttachments; diff --git a/src/email-search/indexedDB.ts b/src/email-search/indexedDB.ts index 5258323..b6cce3a 100644 --- a/src/email-search/indexedDB.ts +++ b/src/email-search/indexedDB.ts @@ -91,7 +91,7 @@ export const encryptAndStoreEmail = async ( ): Promise => { try { const aux = getAux(newEmailToStore.params, false); - const enc = await encryptEmailContentSymmetricallyWithKey(newEmailToStore.body, indexKey, aux, newEmailToStore.id); + const enc = await encryptEmailContentSymmetricallyWithKey(newEmailToStore.body, indexKey, aux); const encryptedEmail: StoredEmail = { enc, params: newEmailToStore.params, id: newEmailToStore.id }; await esDB.put(DB_LABEL, encryptedEmail); } catch (error) { @@ -115,7 +115,7 @@ export const encryptAndStoreManyEmail = async ( const encryptedEmails = await Promise.all( newEmailsToStore.map(async (email: Email) => { const aux = getAux(email.params, false); - const enc = await encryptEmailContentSymmetricallyWithKey(email.body, indexKey, aux, email.id); + const enc = await encryptEmailContentSymmetricallyWithKey(email.body, indexKey, aux); return { enc, params: email.params, id: email.id }; }), diff --git a/src/hash/mac.ts b/src/hash/mac.ts index 95e2012..8b554df 100644 --- a/src/hash/mac.ts +++ b/src/hash/mac.ts @@ -1,5 +1,5 @@ import { bytesToHex } from '@noble/hashes/utils.js'; -import { AES_KEY_BIT_LENGTH } from '../constants'; +import { AES_KEY_BYTE_LENGTH } from '../constants'; import { getBytesFromData, hashDataArrayWithKey } from './blake3'; /** @@ -11,7 +11,7 @@ import { getBytesFromData, hashDataArrayWithKey } from './blake3'; */ export function computeMac(keyMaterial: Uint8Array, data: Uint8Array[]): string { try { - const key = getBytesFromData(AES_KEY_BIT_LENGTH / 8, keyMaterial); + const key = getBytesFromData(AES_KEY_BYTE_LENGTH, keyMaterial); const hash = hashDataArrayWithKey(key, data); return bytesToHex(hash); } catch (error) { diff --git a/src/index.ts b/src/index.ts index e03fac2..8b93549 100644 --- a/src/index.ts +++ b/src/index.ts @@ -55,14 +55,7 @@ export { export { unwrapKey, wrapKey } from './key-wrapper'; export { createEncryptionAndRecoveryKeystores, openEncryptionKeystore, openRecoveryKeystore } from './keystore-crypto'; export { generateKyberKeys, encapsulateKyber, decapsulateKyber } from './post-quantum-crypto'; -export { - encryptSymmetrically, - decryptSymmetrically, - importSymmetricCryptoKey, - exportSymmetricCryptoKey, - genSymmetricCryptoKey, - genSymmetricKey, -} from './symmetric-crypto'; +export { encryptSymmetrically, decryptSymmetrically, genSymmetricKey } from './symmetric-crypto'; export { uint8ArrayToHex, UTF8ToUint8, diff --git a/src/keystore-crypto/core.ts b/src/keystore-crypto/core.ts index 69707c7..a124123 100644 --- a/src/keystore-crypto/core.ts +++ b/src/keystore-crypto/core.ts @@ -1,7 +1,7 @@ import { encryptSymmetrically, decryptSymmetrically } from '../symmetric-crypto'; import { base64ToUint8Array, uint8ArrayToBase64, UTF8ToUint8, mnemonicToBytes } from '../utils'; import { deriveSymmetricKeyFromContext } from '../derive-key'; -import { CONTEXT_ENC_KEYSTORE, AES_KEY_BIT_LENGTH, CONTEXT_RECOVERY } from '../constants'; +import { CONTEXT_ENC_KEYSTORE, AES_KEY_BYTE_LENGTH, CONTEXT_RECOVERY } from '../constants'; import { getBytesFromData } from '../hash'; import { EncryptedKeystore, HybridKeyPair, KeystoreType } from '../types'; @@ -70,7 +70,7 @@ export async function decryptKeystoreContent( */ export async function deriveRecoveryKey(recoveryCodes: string): Promise { const recoverCodesArray = mnemonicToBytes(recoveryCodes); - const recoveryCodesBuffer = getBytesFromData(AES_KEY_BIT_LENGTH / 8, recoverCodesArray); + const recoveryCodesBuffer = getBytesFromData(AES_KEY_BYTE_LENGTH, recoverCodesArray); return deriveSymmetricKeyFromContext(CONTEXT_RECOVERY, recoveryCodesBuffer); } diff --git a/src/symmetric-crypto/aes.ts b/src/symmetric-crypto/aes.ts index e4ef1cf..5488a30 100644 --- a/src/symmetric-crypto/aes.ts +++ b/src/symmetric-crypto/aes.ts @@ -1,25 +1,23 @@ -import { createNISTbasedIV, encryptMessage, decryptMessage } from './core'; -import { concatBytes } from '@noble/hashes/utils.js'; -import { IV_LEN_BYTES } from '../constants'; +import { concatBytes, randomBytes } from '@noble/hashes/utils.js'; +import { IV_LEN_BYTES, AES_KEY_BYTE_LENGTH } from '../constants'; +import { gcm as aeadCipher } from '@noble/ciphers/webcrypto.js'; /** * Symmetrically encrypts the message * * @param encryptionKey - The symmetric key used for message encryption * @param message - The message to encrypt - * @param freeField - The context of the message (required for IV generation) - * @param aux - The auxilary string + * @param aux - The auxilary string (e.g., context string or timestamp) for AEAD. * @returns The resulting ciphertext. */ export async function encryptSymmetrically( encryptionKey: Uint8Array, message: Uint8Array, - aux: Uint8Array, - freeField?: Uint8Array, + aux?: Uint8Array, ): Promise { try { - const iv = createNISTbasedIV(freeField); - const ciphertext = await encryptMessage(message, encryptionKey, iv, aux); + const iv = randomBytes(IV_LEN_BYTES); + const ciphertext = await aeadCipher(encryptionKey, iv, aux).encrypt(message); return concatBytes(ciphertext, iv); } catch (error) { throw new Error('Failed to encrypt symmetrically', { cause: error }); @@ -31,20 +29,29 @@ export async function encryptSymmetrically( * * @param encryptionKey - The symmetric key used for message encryption * @param encryptedMessage - The ciphertext - * @param aux - The auxilary string + * @param aux - The auxilary string (e.g., context string or timestamp) for AEAD. * @returns The resulting ciphertext. */ export async function decryptSymmetrically( encryptionKey: Uint8Array, encryptedMessage: Uint8Array, - aux: Uint8Array, + aux?: Uint8Array, ): Promise { try { const ciphertext = encryptedMessage.slice(0, encryptedMessage.length - IV_LEN_BYTES); const iv = encryptedMessage.slice(encryptedMessage.length - IV_LEN_BYTES); - const result = await decryptMessage(ciphertext, iv, encryptionKey, aux); + const result = await aeadCipher(encryptionKey, iv, aux).decrypt(ciphertext); return result; } catch (error) { throw new Error('Failed to decrypt symmetrically', { cause: error }); } } + +/** + * Generates symmetric key as Uint8Array + * + * @returns The generated Uint8Array. + */ +export function genSymmetricKey(): Uint8Array { + return randomBytes(AES_KEY_BYTE_LENGTH); +} diff --git a/src/symmetric-crypto/core.ts b/src/symmetric-crypto/core.ts deleted file mode 100644 index a95c506..0000000 --- a/src/symmetric-crypto/core.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { gcm as aeadCipher } from '@noble/ciphers/webcrypto.js'; -import { randomBytes } from '@noble/post-quantum/utils.js'; -import { getBytesFromData } from '../hash'; -import { IV_LEN_BYTES } from '../constants'; - -/** - * Creates an initialization vector (IV) using RGB-based construction (8.2.2 NIST Special Publication 800-38D) - * Constructs a 128-bits IV from 2 fileds: the random field (at least 96 bits) and the free field (32 bits). - * If free filed is empty, then the entier 128-bit IV is sampled randomly. - * - * @param freeFiled - The string with an unrestricted content. Can be a device identifier, etc. - * @returns The resulting 128-bits initialization vector. - */ -export function createNISTbasedIV(freeField?: Uint8Array): Uint8Array { - try { - if (!freeField) { - return randomBytes(IV_LEN_BYTES); - } - - const iv = new Uint8Array(16); - - const randFiled = randomBytes(12); - iv.set(randFiled, 0); - - const freeFiledFixedLength = getBytesFromData(4, freeField); - iv.set(freeFiledFixedLength, 12); - - return iv; - } catch (error) { - throw new Error('Failed to create IV', { cause: error }); - } -} - -/** - * Symmetrically encrypts message - * - * @param message - The message to encrypt - * @param encryptionKey - The encryption key - * @param iv - The initialization vector - * @param additionalData - The auxilary data - * @returns The resulting ciphertext - */ -export async function encryptMessage( - message: Uint8Array, - encryptionKey: Uint8Array, - iv: Uint8Array, - additionalData: Uint8Array, -): Promise { - return aeadCipher(encryptionKey, iv, additionalData).encrypt(message); -} - -/** - * Symmetrically decrypts message - * - * @param ciphertext - The encrypted message - * @param ciphertext - The initialization vector - * @param encryptionKey - The encryption key - * @param additionalData - The auxilary data - * @returns The resulting decrypted message - */ -export async function decryptMessage( - ciphertext: Uint8Array, - iv: Uint8Array, - encryptionKey: Uint8Array, - additionalData: Uint8Array, -): Promise { - return aeadCipher(encryptionKey, iv, additionalData).decrypt(ciphertext); -} diff --git a/src/symmetric-crypto/index.ts b/src/symmetric-crypto/index.ts index 897cfc5..37b4091 100644 --- a/src/symmetric-crypto/index.ts +++ b/src/symmetric-crypto/index.ts @@ -1,2 +1 @@ -export * from './keys'; export * from './aes'; diff --git a/src/symmetric-crypto/keys.ts b/src/symmetric-crypto/keys.ts deleted file mode 100644 index 6bc6504..0000000 --- a/src/symmetric-crypto/keys.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { AES_ALGORITHM, AES_KEY_BIT_LENGTH, KEY_FORMAT } from '../constants'; -import { randomBytes } from '@noble/post-quantum/utils.js'; - -/** - * Converts Uint8Array into CryptoKey - * - * @param keyData - The Uint8Array representation of the symmetric key - * @returns The resulting symmetric CryptoKey. - */ -export async function importSymmetricCryptoKey(keyData: Uint8Array | ArrayBuffer): Promise { - return crypto.subtle.importKey( - KEY_FORMAT, - new Uint8Array(keyData), - { - name: AES_ALGORITHM, - length: AES_KEY_BIT_LENGTH, - }, - true, - ['encrypt', 'decrypt'], - ); -} - -/** - * Converts CryptoKey into Uint8Array - * - * @param key - The symmetric CryptoKey - * @returns The resulting Uint8Array. - */ -export async function exportSymmetricCryptoKey(key: CryptoKey): Promise { - try { - const rawKey = await crypto.subtle.exportKey(KEY_FORMAT, key); - return new Uint8Array(rawKey); - } catch (error) { - throw new Error('Failed to export symmetric CryptoKey', { cause: error }); - } -} - -/** - * Generates symmetric CryptoKey - * - * @returns The generated CryptoKey. - */ -export async function genSymmetricCryptoKey(): Promise { - return crypto.subtle.generateKey( - { - name: AES_ALGORITHM, - length: AES_KEY_BIT_LENGTH, - }, - true, - ['encrypt', 'decrypt'], - ); -} - -/** - * Generates symmetric key as Uint8Array - * - * @returns The generated Uint8Array. - */ -export function genSymmetricKey(): Uint8Array { - return randomBytes(AES_KEY_BIT_LENGTH / 8); -} diff --git a/src/utils/genMnemonic.ts b/src/utils/genMnemonic.ts index 0ca9c99..d657a89 100644 --- a/src/utils/genMnemonic.ts +++ b/src/utils/genMnemonic.ts @@ -1,13 +1,13 @@ import * as bip39 from '@scure/bip39'; import { wordlist } from '@scure/bip39/wordlists/english.js'; -import { AES_KEY_BIT_LENGTH } from '../constants'; +import { AES_KEY_BYTE_LENGTH } from '../constants'; /** * Generates a mnemonic * * @returns The generated mnemonic. */ export function genMnemonic(): string { - return bip39.generateMnemonic(wordlist, AES_KEY_BIT_LENGTH); + return bip39.generateMnemonic(wordlist, AES_KEY_BYTE_LENGTH * 8); } /** diff --git a/tests/derive-keys/deriveKeys.test.ts b/tests/derive-keys/deriveKeys.test.ts index 1cac68a..6a1a542 100644 --- a/tests/derive-keys/deriveKeys.test.ts +++ b/tests/derive-keys/deriveKeys.test.ts @@ -1,10 +1,7 @@ import { describe, expect, it } from 'vitest'; -import { - deriveSymmetricKeyFromTwoKeys, - deriveSymmetricKeyFromContext -} from '../../src/derive-key'; +import { deriveSymmetricKeyFromTwoKeys, deriveSymmetricKeyFromContext } from '../../src/derive-key'; import { uint8ArrayToHex } from '../../src/utils'; -import { AES_KEY_BIT_LENGTH } from '../../src/constants'; +import { AES_KEY_BYTE_LENGTH } from '../../src/constants'; import { genSymmetricKey } from '../../src/symmetric-crypto'; describe('Test derive key', () => { @@ -16,7 +13,7 @@ describe('Test derive key', () => { return result; } it('should derive symmetric key from two keys', async () => { - const context = 'BLAKE3 2019-12-27 16:29:52 test vectors context'; + const context = 'BLAKE3 2019-12-27 16:29:52 test vectors context'; const input = createTestInput(63); const blake3TestResult = 'b6451e30b953c206e34644c6803724e9d2725e0893039cfc49584f991f451af3'; const result = deriveSymmetricKeyFromContext(context, input); @@ -28,7 +25,7 @@ describe('Test derive key', () => { const key1 = genSymmetricKey(); const key2 = genSymmetricKey(); const key = await deriveSymmetricKeyFromTwoKeys(key1, key2); - expect(key.length).toBe(AES_KEY_BIT_LENGTH / 8); + expect(key.length).toBe(AES_KEY_BYTE_LENGTH); }); it('derive symmetric key from two keys should fail for small key', async () => { diff --git a/tests/email-crypto/core.test.ts b/tests/email-crypto/core.test.ts index 7e31c14..65070fd 100644 --- a/tests/email-crypto/core.test.ts +++ b/tests/email-crypto/core.test.ts @@ -34,8 +34,6 @@ describe('Test email crypto functions', () => { replyToEmailID: generateUuid(), }; - const id = generateUuid(); - const aux = getAux(emailParams, false); it('should generate email id', async () => { @@ -46,13 +44,13 @@ describe('Test email crypto functions', () => { }); it('should encrypt and decrypt email', async () => { - const { enc, encryptionKey } = await encryptEmailContentSymmetrically(emailBody, aux, id); + const { enc, encryptionKey } = await encryptEmailContentSymmetrically(emailBody, aux); const result = await decryptEmailSymmetrically(encryptionKey, aux, enc); expect(result).toEqual(emailBody); }); it('should throw an error if decryption fails', async () => { - const { enc, encryptionKey } = await encryptEmailContentSymmetrically(emailBody, aux, id); + const { enc, encryptionKey } = await encryptEmailContentSymmetrically(emailBody, aux); const bad_encryptionKey = await genSymmetricKey(); await expect(decryptEmailSymmetrically(bad_encryptionKey, aux, enc)).rejects.toThrowError( /Failed to symmetrically decrypt email/, @@ -69,7 +67,6 @@ describe('Test email crypto functions', () => { emailBody, emailParams.subject, aux, - id, ); await expect(decryptEmailAndSubjectSymmetrically(bad_encryptionKey, aux, encSubject, enc)).rejects.toThrowError( /Failed to symmetrically decrypt email and subject/, @@ -94,12 +91,12 @@ describe('Test email crypto functions', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const bad_email: any = {}; bad_email.self = bad_email; - await expect(encryptEmailContentSymmetrically(bad_email, aux, id)).rejects.toThrowError( + await expect(encryptEmailContentSymmetrically(bad_email, aux)).rejects.toThrowError( /Failed to symmetrically encrypt email/, ); - await expect( - encryptEmailContentAndSubjectSymmetrically(bad_email, emailParams.subject, aux, id), - ).rejects.toThrowError(/Failed to symmetrically encrypt email and subject/); + await expect(encryptEmailContentAndSubjectSymmetrically(bad_email, emailParams.subject, aux)).rejects.toThrowError( + /Failed to symmetrically encrypt email and subject/, + ); }); }); diff --git a/tests/key-wrapper/aesWrapper.test.ts b/tests/key-wrapper/aesWrapper.test.ts index 51c8e04..e6f913b 100644 --- a/tests/key-wrapper/aesWrapper.test.ts +++ b/tests/key-wrapper/aesWrapper.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest'; import { wrapKey, unwrapKey, deriveWrappingKey } from '../../src/key-wrapper'; import { genSymmetricKey } from '../../src/symmetric-crypto'; -import { AES_KEY_BIT_LENGTH } from '../../src/constants'; +import { AES_KEY_BYTE_LENGTH } from '../../src/constants'; describe('Test key wrapping functions', () => { it('should scuessfully derive wrapping key', async () => { @@ -11,7 +11,7 @@ describe('Test key wrapping functions', () => { const result = await deriveWrappingKey(secret1, secret2); expect(result).toBeInstanceOf(Uint8Array); - expect(result.length).toBe(AES_KEY_BIT_LENGTH / 8); + expect(result.length).toBe(AES_KEY_BYTE_LENGTH); }); it('should scuessfully wrap and unwrap key', async () => { diff --git a/tests/keystore-crypto/keys.test.ts b/tests/keystore-crypto/keys.test.ts index 9ea07fb..67d5208 100644 --- a/tests/keystore-crypto/keys.test.ts +++ b/tests/keystore-crypto/keys.test.ts @@ -1,14 +1,14 @@ import { describe, expect, it } from 'vitest'; import { deriveEncryptionKeystoreKey, deriveRecoveryKey } from '../../src/keystore-crypto/core'; -import { genSymmetricKey } from '../../src/symmetric-crypto/keys'; -import { AES_KEY_BIT_LENGTH } from '../../src/constants'; +import { genSymmetricKey } from '../../src/symmetric-crypto'; +import { AES_KEY_BYTE_LENGTH } from '../../src/constants'; import { genMnemonic } from '../../src/utils'; describe('Test keystore key generation functions', () => { it('correct symmetric key length', async () => { const baseKey = genSymmetricKey(); const key = await deriveEncryptionKeystoreKey(baseKey); - expect(key.length).toBe(AES_KEY_BIT_LENGTH / 8); + expect(key.length).toBe(AES_KEY_BYTE_LENGTH); }); it('should give different derived keys for the same baseKey', async () => { diff --git a/tests/symmetric-crypto/aes.test.ts b/tests/symmetric-crypto/aes.test.ts index a69c7c4..6fed8b9 100644 --- a/tests/symmetric-crypto/aes.test.ts +++ b/tests/symmetric-crypto/aes.test.ts @@ -1,14 +1,14 @@ import { describe, expect, it } from 'vitest'; import { encryptSymmetrically, decryptSymmetrically, genSymmetricKey } from '../../src/symmetric-crypto'; +import { AES_KEY_BYTE_LENGTH } from '../../src/constants'; describe('Test symmetric functions', () => { - it('should sucessfully encrypt and decrypt', async () => { + it('should sucessfully encrypt and decrypt with additional data', async () => { const key = genSymmetricKey(); const message = new Uint8Array([12, 42, 32, 44, 88, 89, 99, 100]); const aux = new TextEncoder().encode('additional data'); - const freeField = new Uint8Array([1, 2, 3]); - const enc = await encryptSymmetrically(key, message, aux, freeField); + const enc = await encryptSymmetrically(key, message, aux); const result = await decryptSymmetrically(key, enc, aux); expect(result).toStrictEqual(message); @@ -18,4 +18,26 @@ describe('Test symmetric functions', () => { expect(result_2).toStrictEqual(message); expect(enc_2).not.toBe(enc); }); + + it('should sucessfully encrypt and decrypt without additional data', async () => { + const key = genSymmetricKey(); + const message = new Uint8Array([12, 42, 32, 44, 88, 89, 99, 100]); + + const enc = await encryptSymmetrically(key, message); + const result = await decryptSymmetrically(key, enc); + + expect(result).toStrictEqual(message); + + const enc_2 = await encryptSymmetrically(key, message); + const result_2 = await decryptSymmetrically(key, enc_2); + expect(result_2).toStrictEqual(message); + expect(enc_2).not.toBe(enc); + }); + + it('should sucessfully generate key', async () => { + const key = genSymmetricKey(); + + expect(key).toBeInstanceOf(Uint8Array); + expect(key.length).toBe(AES_KEY_BYTE_LENGTH); + }); }); diff --git a/tests/symmetric-crypto/core.test.ts b/tests/symmetric-crypto/core.test.ts deleted file mode 100644 index 62656a1..0000000 --- a/tests/symmetric-crypto/core.test.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { createNISTbasedIV } from '../../src/symmetric-crypto/core'; -import { getBytesFromData } from '../../src/hash'; - -describe('Test symmetric functions', () => { - it('should generate iv as expected', async () => { - const freeField = new TextEncoder().encode('4'); - const iv = createNISTbasedIV(freeField); - const number = iv.slice(12); - - const hash = getBytesFromData(4, freeField); - - expect(number).toStrictEqual(hash); - expect(iv.length).toBe(16); - - const iv_new = createNISTbasedIV(freeField); - expect(iv).not.toEqual(iv_new); - - const iv_empry_free_field = createNISTbasedIV(); - expect((await iv_empry_free_field).length).toEqual(16); - }); -}); diff --git a/tests/symmetric-crypto/keys.test.ts b/tests/symmetric-crypto/keys.test.ts deleted file mode 100644 index 77188d9..0000000 --- a/tests/symmetric-crypto/keys.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { exportSymmetricCryptoKey, genSymmetricCryptoKey, genSymmetricKey } from '../../src/symmetric-crypto'; -import { AES_ALGORITHM, AES_KEY_BIT_LENGTH } from '../../src/constants'; - -describe('Test symmetric key functions', () => { - it('should sucessfully generate crypto key', async () => { - const key = await genSymmetricCryptoKey(); - - expect(key).toBeInstanceOf(CryptoKey); - expect(key.type).toBe('secret'); - expect(key.extractable).toBeTruthy(); - expect(key.usages).toContain('encrypt'); - expect(key.usages).toContain('decrypt'); - - const alg = key.algorithm as AesKeyAlgorithm; - expect(alg.name).toBe(AES_ALGORITHM); - expect(alg.length).toBe(AES_KEY_BIT_LENGTH); - }); - - it('should sucessfully generate key', async () => { - const key = genSymmetricKey(); - - expect(key).toBeInstanceOf(Uint8Array); - expect(key.length).toBe(AES_KEY_BIT_LENGTH / 8); - }); - - it('should throw an error if secret key is non exportable', async () => { - const non_exportable_key = await crypto.subtle.generateKey( - { - name: AES_ALGORITHM, - length: AES_KEY_BIT_LENGTH, - }, - false, - ['encrypt', 'decrypt'], - ); - await expect(exportSymmetricCryptoKey(non_exportable_key)).rejects.toThrowError( - /Failed to export symmetric CryptoKey/, - ); - }); -});