-
Notifications
You must be signed in to change notification settings - Fork 0
[_] Switch to noble hybrid #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,11 @@ | ||
| import { generateEccKeys } from '../asymmetric-crypto'; | ||
| import { generateKyberKeys } from '../post-quantum-crypto'; | ||
| import { EmailKeys } from '../types'; | ||
| import { genHybridKeys } from '../hybrid-crypto'; | ||
| import { HybridKeyPair } from '../types'; | ||
|
|
||
| /** | ||
| * Generates public and private keys for email service. | ||
| * | ||
| * @returns The user's private and public keys | ||
| */ | ||
| export async function generateEmailKeys(): Promise<EmailKeys> { | ||
| try { | ||
| const kyberKeys = generateKyberKeys(); | ||
| const keys = await generateEccKeys(); | ||
|
|
||
| const emailKeys: EmailKeys = { | ||
| publicKeys: { | ||
| eccPublicKey: keys.publicKey, | ||
| kyberPublicKey: kyberKeys.publicKey, | ||
| }, | ||
| privateKeys: { | ||
| eccPrivateKey: keys.privateKey, | ||
| kyberPrivateKey: kyberKeys.secretKey, | ||
| }, | ||
| }; | ||
|
|
||
| return emailKeys; | ||
| } catch (error) { | ||
| throw new Error('Failed to generate keys for email service', { cause: error }); | ||
| } | ||
| export async function generateEmailKeys(): Promise<HybridKeyPair> { | ||
| return genHybridKeys(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import { PublicKeys, PrivateKeys, HybridEncryptedEmail, Email, UserWithPublicKeys } from '../types'; | ||
| import { HybridEncryptedEmail, Email, UserWithPublicKey } from '../types'; | ||
| import { decryptEmailBody, encryptKeysHybrid, decryptKeysHybrid, encryptEmailBody } from './core'; | ||
|
|
||
| /** | ||
|
|
@@ -12,13 +12,12 @@ import { decryptEmailBody, encryptKeysHybrid, decryptKeysHybrid, encryptEmailBod | |
| */ | ||
| export async function encryptEmailHybrid( | ||
| email: Email, | ||
| recipient: UserWithPublicKeys, | ||
| senderPrivateKey: PrivateKeys, | ||
| recipient: UserWithPublicKey, | ||
| isSubjectEncrypted: boolean = false, | ||
| ): Promise<HybridEncryptedEmail> { | ||
| try { | ||
| const { encryptionKey, params, enc } = await encryptEmailBody(email, isSubjectEncrypted); | ||
| const encryptedKey = await encryptKeysHybrid(encryptionKey, recipient.publicKeys, senderPrivateKey); | ||
| const encryptedKey = await encryptKeysHybrid(encryptionKey, recipient.publicHybridKey); | ||
| return { enc, encryptedKey, recipientEmail: recipient.email, params, isSubjectEncrypted, id: email.id }; | ||
| } catch (error) { | ||
| throw new Error('Failed to encrypt email with hybrid encryption', { cause: error }); | ||
|
|
@@ -36,16 +35,15 @@ export async function encryptEmailHybrid( | |
| */ | ||
| export async function encryptEmailHybridForMultipleRecipients( | ||
| email: Email, | ||
| recipients: UserWithPublicKeys[], | ||
| senderPrivateKey: PrivateKeys, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
| recipients: UserWithPublicKey[], | ||
| isSubjectEncrypted: boolean = false, | ||
| ): Promise<HybridEncryptedEmail[]> { | ||
| try { | ||
| const { encryptionKey, params, enc } = await encryptEmailBody(email, isSubjectEncrypted); | ||
|
|
||
| const encryptedEmails: HybridEncryptedEmail[] = []; | ||
| for (const recipient of recipients) { | ||
| const encryptedKey = await encryptKeysHybrid(encryptionKey, recipient.publicKeys, senderPrivateKey); | ||
| const encryptedKey = await encryptKeysHybrid(encryptionKey, recipient.publicHybridKey); | ||
| encryptedEmails.push({ | ||
| enc, | ||
| encryptedKey, | ||
|
|
@@ -66,17 +64,16 @@ export async function encryptEmailHybridForMultipleRecipients( | |
| * | ||
| * @param encryptedEmail - The encrypted email. | ||
| * @param senderPublicKeys - The public key of the sender. | ||
| * @param recipientPrivateKeys - The private key of the recipient. | ||
| * @param recipientPrivateHybridKeys - The private key of the recipient. | ||
| * @returns The decrypted email | ||
| */ | ||
| export async function decryptEmailHybrid( | ||
| encryptedEmail: HybridEncryptedEmail, | ||
| senderPublicKeys: PublicKeys, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same (also remember to remove the params from the JSDoc) :)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true, will check
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
| recipientPrivateKeys: PrivateKeys, | ||
| recipientPrivateHybridKeys: Uint8Array, | ||
| ): Promise<Email> { | ||
| try { | ||
| const { isSubjectEncrypted, params: encParams, enc, encryptedKey, id } = encryptedEmail; | ||
| const encryptionKey = await decryptKeysHybrid(encryptedKey, senderPublicKeys, recipientPrivateKeys); | ||
| const encryptionKey = await decryptKeysHybrid(encryptedKey, recipientPrivateHybridKeys); | ||
| const { body, params } = await decryptEmailBody(enc, encParams, encryptionKey, isSubjectEncrypted); | ||
| return { body, params, id }; | ||
| } catch (error) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,9 @@ | ||
| import { encryptSymmetrically, decryptSymmetrically } from '../symmetric-crypto'; | ||
| import { base64ToUint8Array, uint8ArrayToBase64, UTF8ToUint8, mnemonicToBytes, publicKeyToBase64 } from '../utils'; | ||
| 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 { getBytesFromData } from '../hash'; | ||
| import { EmailKeys, EncryptedKeystore, KeystoreType } from '../types'; | ||
| import { exportPrivateKey, importPrivateKey, importPublicKey } from '../asymmetric-crypto'; | ||
| import { EncryptedKeystore, HybridKeyPair, KeystoreType } from '../types'; | ||
|
|
||
| /** | ||
| * Encrypts the keystore content using symmetric encryption | ||
|
|
@@ -17,28 +16,20 @@ import { exportPrivateKey, importPrivateKey, importPublicKey } from '../asymmetr | |
| */ | ||
| export async function encryptKeystoreContent( | ||
| secretKey: Uint8Array, | ||
| keys: EmailKeys, | ||
| keys: HybridKeyPair, | ||
| userEmail: string, | ||
| type: KeystoreType, | ||
| ): Promise<EncryptedKeystore> { | ||
| try { | ||
| const aux = UTF8ToUint8(userEmail + type); | ||
| const publicKeys = await publicKeyToBase64(keys.publicKeys); | ||
| const kyberPrivateKeyEnc = await encryptSymmetrically(secretKey, keys.privateKeys.kyberPrivateKey, aux); | ||
| const eccPrivateKey = await exportPrivateKey(keys.privateKeys.eccPrivateKey); | ||
| const eccPrivateKeyEnc = await encryptSymmetrically(secretKey, eccPrivateKey, aux); | ||
| const encryptedKeys = { | ||
| publicKeys, | ||
| privateKeys: { | ||
| kyberPrivateKeyBase64: uint8ArrayToBase64(kyberPrivateKeyEnc), | ||
| eccPrivateKeyBase64: uint8ArrayToBase64(eccPrivateKeyEnc), | ||
| }, | ||
| }; | ||
| const publicKey = uint8ArrayToBase64(keys.publicKey); | ||
| const secretKeyEncrypted = await encryptSymmetrically(secretKey, keys.secretKey, aux); | ||
|
|
||
| const keystore: EncryptedKeystore = { | ||
| userEmail, | ||
| type, | ||
| encryptedKeys, | ||
| publicKey, | ||
| privateKeyEncrypted: uint8ArrayToBase64(secretKeyEncrypted), | ||
| }; | ||
| return keystore; | ||
| } catch (error) { | ||
|
|
@@ -49,37 +40,25 @@ export async function encryptKeystoreContent( | |
| /** | ||
| * Decrypts the keystore content using symmetric encryption | ||
| * | ||
| * @param secretKey - The symmetric key to decrypt the keystore content | ||
| * @param kesytoreOpeningKey - The symmetric key to decrypt the keystore content | ||
| * @param encryptedKeys - The encrypted keystore content | ||
| * @param userEmail - The ID of the user | ||
| * @param tag - The keystore type-specific tag string | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these params being used in the function?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. was before, fixed |
||
| * @returns The decrypted keystore content | ||
| */ | ||
| export async function decryptKeystoreContent( | ||
| secretKey: Uint8Array, | ||
| kesytoreOpeningKey: Uint8Array, | ||
| encryptedKeystore: EncryptedKeystore, | ||
| ): Promise<EmailKeys> { | ||
| ): Promise<HybridKeyPair> { | ||
| try { | ||
| const aux = UTF8ToUint8(encryptedKeystore.userEmail + encryptedKeystore.type); | ||
| const kyberPublicKey = base64ToUint8Array(encryptedKeystore.encryptedKeys.publicKeys.kyberPublicKeyBase64); | ||
| const eccPublicArray = base64ToUint8Array(encryptedKeystore.encryptedKeys.publicKeys.eccPublicKeyBase64); | ||
| const eccPublicKey = await importPublicKey(eccPublicArray); | ||
| const encKyberPrivateKey = base64ToUint8Array(encryptedKeystore.encryptedKeys.privateKeys.kyberPrivateKeyBase64); | ||
| const kyberPrivateKey = await decryptSymmetrically(secretKey, encKyberPrivateKey, aux); | ||
| const eccEncArray = base64ToUint8Array(encryptedKeystore.encryptedKeys.privateKeys.eccPrivateKeyBase64); | ||
| const eccKey = await decryptSymmetrically(secretKey, eccEncArray, aux); | ||
| const eccPrivateKey = await importPrivateKey(eccKey); | ||
| const keys = { | ||
| publicKeys: { | ||
| kyberPublicKey, | ||
| eccPublicKey, | ||
| }, | ||
| privateKeys: { | ||
| kyberPrivateKey, | ||
| eccPrivateKey, | ||
| }, | ||
| const publicKey = base64ToUint8Array(encryptedKeystore.publicKey); | ||
| const ciphertext = base64ToUint8Array(encryptedKeystore.privateKeyEncrypted); | ||
| const secretKey = await decryptSymmetrically(kesytoreOpeningKey, ciphertext, aux); | ||
| return { | ||
| publicKey, | ||
| secretKey, | ||
| }; | ||
| return keys; | ||
| } catch (error) { | ||
| throw new Error('Failed to decrypt keystore content', { cause: error }); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why sender key has been removed here? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because X-Wing doesn't need it. Before, I was doing ECC secret derivation, Kyber KEM encapsulation that gave another secret, then deriving one key from both secrets. X-Wing does it differently; they take public key of the intended recipient as input and handle everything else. The hybrid key is this:
