mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-11-01 18:19:43 +00:00
Add E2EE key pair verification before send
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
1 parent
69f43ffb7d
commit
0ffa7fa952
6 files changed
+148
-29
No files matched your search
@@ -150,7 +150,7 @@ export async function wrapAESKey(
|
||||
|
||||
/**
|
||||
* Unwrap (decrypt) an AES key with an RSA private key
|
||||
*
|
||||
*
|
||||
* @param wrappedKeyBase64 - The wrapped key as base64 string
|
||||
* @param privateKeyJwk - The user's RSA private key
|
||||
* @returns The unwrapped AES key as ArrayBuffer
|
||||
@@ -162,10 +162,65 @@ export async function unwrapAESKey(
|
||||
const subtle = getSubtle();
|
||||
const rsaKey = await importPrivateKey(privateKeyJwk);
|
||||
const wrappedKey = base64ToArrayBuffer(wrappedKeyBase64);
|
||||
|
||||
|
||||
return await subtle.decrypt(
|
||||
{ name: KEY_WRAP_ALGORITHM },
|
||||
rsaKey,
|
||||
wrappedKey
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a public/private key pair actually work together.
|
||||
* This catches key mismatches that could cause unrecoverable encrypted messages.
|
||||
*
|
||||
* @param publicKeyJwk - The RSA public key
|
||||
* @param privateKeyJwk - The RSA private key
|
||||
* @returns true if the keys work together, false otherwise
|
||||
*/
|
||||
export async function verifyKeyPair(
|
||||
publicKeyJwk: RSAPublicKeyJWK,
|
||||
privateKeyJwk: RSAPrivateKeyJWK
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const subtle = getSubtle();
|
||||
|
||||
// Create test data (32 bytes - same as AES-256 key)
|
||||
const testData = getRandomValues(new Uint8Array(32));
|
||||
|
||||
// Import keys
|
||||
const publicKey = await importPublicKey(publicKeyJwk);
|
||||
const privateKey = await importPrivateKey(privateKeyJwk);
|
||||
|
||||
// Encrypt with public key
|
||||
const encrypted = await subtle.encrypt(
|
||||
{ name: KEY_WRAP_ALGORITHM },
|
||||
publicKey,
|
||||
testData as BufferSource
|
||||
);
|
||||
|
||||
// Decrypt with private key
|
||||
const decrypted = await subtle.decrypt(
|
||||
{ name: KEY_WRAP_ALGORITHM },
|
||||
privateKey,
|
||||
encrypted
|
||||
);
|
||||
|
||||
// Verify the data matches
|
||||
const decryptedArray = new Uint8Array(decrypted);
|
||||
if (decryptedArray.length !== testData.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < testData.length; i++) {
|
||||
if (testData[i] !== decryptedArray[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('[E2EE] Key pair verification failed:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -65,3 +65,6 @@ export { triggerKeyRotation } from './triggerKeyRotation';
|
||||
|
||||
// Stale Key Repair
|
||||
export { repairStaleKey } from './repairStaleKey';
|
||||
|
||||
// Crypto Operations
|
||||
export { verifyKeyPair } from './crypto';
|
||||
Reference in new issue
Block a user