We aim to have:
- An 'A' score on Maintainability Rating
- An 'A' score on Security Rating
- Less than 3% duplicated lines
- A 90% tests coverage
- Runs .ts linter
- Runs unit tests with Vitest
Builds the app for production to the build folder.
asymmetric-crypto- Asymmetric elliptic curves cryptography (curve P-521) for generating keys and deriving a shared secret between two userssymmetric-crypto- Symmetric encryption operations (AES-GCM) for data encryption and decryptionpost-quantum-crypto- Post-quantum cryptographic algorithms (MLKEMs) for generating keys and deriving a shared secret between two usershash- Cryptographic hashing functions (BLAKE3) for data integrity, commitments and secret extensions
derive-key- Key derivation functions for deriving cryptographic keys from base key (BLAKE3 in KDF mode)derive-password- Key derivation functions for deriving cryptographic keys from passwords (ARGON2)key-wrapper- Key wrapping and unwrapping functions for secure symmetric key storage and transportkeystore-crypto- Keystore cryptographic operations for securing user's keys
email-crypto- End-to-end email encryption and decryption using hybrid cryptography and password-protectionemail-search- Email indexing on the client side to enable search while preserving privacy
storage-service- Abstraction layer for accessing Local Storage and Session Storageutils- Type converter functions and access to enviromental variablestypes- TypeScript type definitions for all library interfaces and data structuresconstants- Cryptographic constants, algorithm identifiers, and configuration values
import {
generateEccKeys,
deriveSecretKey,
UTF8ToUint8,
genSymmetricKey,
encryptSymmetrically,
} from 'internxt-crypto';
// Asymmetric encryption
const keysAlice = await generateEccKeys();
const keysBob = await generateEccKeys();
const resultAlice = await deriveSecretKey(keysBob.publicKey, keysAlice.privateKey);
const resultBob = await deriveSecretKey(keysAlice.publicKey, keysBob.privateKey);
expect(resultAlice).toStrictEqual(resultBob);
// Symmetric encryption
const data = UTF8ToUint8('Sensitive information to encrypt'); // convert to Uint8Array
const additionalData = 'Additional non-secret data';
const key = genSymmetricKey();
const ciphertext: Uint8Array = await encryptSymmetrically(key, data, additionalData);
const plainText = await decryptSymmetrically(encryptionKey, ciphertext, additionalData);
expect(data).toStrictEqual(plainText);
// Post qunatum cryptography
const keys = generateKyberKeys();
const { cipherText, sharedSecret } = encapsulateKyber(keys.publicKey);
const result = decapsulateKyber(cipherText, keys.secretKey);
expect(result).toStrictEqual(sharedSecret);
// Hash
const result = hashData(['']);
const expectedResult = 'af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262';
expect(result).toStrictEqual(expectedResult);
// Key derivation
const context = 'BLAKE3 2019-12-27 16:29:52 test vectors context';
const baseKey = genSymmetricKey();
const key = deriveSymmetricKeyFromContext(context, baseKey);
// Key derivation from password
const password = 'your password';
const { key, salt } = await getKeyFromPassword(password);
// Hybrid email encryption
const email: Email = {
text: 'email text',
attachments: ['email attachements'],
};
const { secretKey: bobPrivateKeys, publicKey: bobPublicKeys } = await generateEmailKeys();
const bobWithPublicKeys = {
email: 'bob email',
publicHybridKey: bobPublicKeys,
};
const encryptedEmail = await encryptEmailHybrid(email, bobWithPublicKeys);
const decryptedEmail = await decryptEmailHybrid(encryptedEmail, bobPrivateKeys);
expect(decryptedEmail).toStrictEqual(email);
// Hybrid email and subject encryption
const emailAndSubject: EmailAndSubject = {
text: 'email text',
subject: 'email subject'
attachments: ['email attachements'],
};
const encryptedEmailAndSubject = await encryptEmailAndSubjectHybrid(emailAndSubject, bobWithPublicKeys);
const decryptedEmailAndSubject = await decryptEmailAndSubjectHybrid(encryptedEmailAndSubject, bobPrivateKeys);
expect(encryptedEmailAndSubject.encEmail.encSubject).not.toBe(emailAndSubject.subject);
expect(decryptedEmailAndSubject).toStrictEqual(emailAndSubject);
// password-protected email
const sharedSecret = 'secret shared between Alice and Bob';
const encryptedEmail = await createPwdProtectedEmail(email, sharedSecret);
const decryptedEmail = await decryptPwdProtectedEmail(encryptedEmail, sharedSecret);
expect(decryptedEmail).toStrictEqual(email);
// keystore
const userEmail = 'user email';
const mnemonic = 'user mnemonic';
const { encryptionKeystore, recoveryKeystore, recoveryCodes } = await createEncryptionAndRecoveryKeystores(
userEmail,
mnemonic
);
const resultEnc = await openEncryptionKeystore(encryptionKeystore, mnemonic);
const resultRec = await openRecoveryKeystore(recoveryCodes, recoveryKeystore);
expect(resultEnc).toStrictEqual(resultRec);