feat: re-use dek and copntent ivs for a letteer's metadata and content

This commit is contained in:
ramvignesh-b
2026-04-28 20:51:34 +05:30
parent 6cf24731ce
commit 8b28949d73
+8 -7
View File
@@ -30,6 +30,9 @@ export class CryptoUtils {
private static readonly PBKDF2_ITERATIONS = 100_000; private static readonly PBKDF2_ITERATIONS = 100_000;
private static readonly AES_GCM = { name: "AES-GCM", length: 256 }; private static readonly AES_GCM = { name: "AES-GCM", length: 256 };
private readonly contentIV = crypto.getRandomValues(new Uint8Array(12));
private readonly dekIV = crypto.getRandomValues(new Uint8Array(12));
// Generates a fresh Data Encryption Key (DEK) // Generates a fresh Data Encryption Key (DEK)
async initialize() { async initialize() {
this.dek = await crypto.subtle.generateKey(CryptoUtils.AES_GCM, true, [ this.dek = await crypto.subtle.generateKey(CryptoUtils.AES_GCM, true, [
@@ -91,7 +94,7 @@ export class CryptoUtils {
hash: "SHA-256", hash: "SHA-256",
}, },
baseKey, baseKey,
512, // 512 bits to split 512,
); );
// first 256 bits for MasterKey, last 256 bits for AuthHash // first 256 bits for MasterKey, last 256 bits for AuthHash
@@ -123,26 +126,24 @@ export class CryptoUtils {
const plainBytes = new Uint8Array(input); const plainBytes = new Uint8Array(input);
// encrypt the content with the DEK // encrypt the content with the DEK
const contentIv = crypto.getRandomValues(new Uint8Array(12));
const ciphertext = await crypto.subtle.encrypt( const ciphertext = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv: contentIv }, { name: "AES-GCM", iv: this.contentIV },
this.dek, this.dek,
plainBytes, plainBytes,
); );
// wrap the DEK with the Master Key (for self/owner access) // wrap the DEK with the Master Key (for self/owner access)
const dekIv = crypto.getRandomValues(new Uint8Array(12));
const wrappedDek = await crypto.subtle.wrapKey("raw", this.dek, masterKey, { const wrappedDek = await crypto.subtle.wrapKey("raw", this.dek, masterKey, {
name: "AES-GCM", name: "AES-GCM",
iv: dekIv, iv: this.dekIV,
}); });
// export raw DEK for the share URL (recipient access, no master key needed) // export raw DEK for the share URL (recipient access, no master key needed)
const rawDek = await crypto.subtle.exportKey("raw", this.dek); const rawDek = await crypto.subtle.exportKey("raw", this.dek);
return { return {
encryptedContent: this.packWithIv(contentIv, ciphertext), encryptedContent: this.packWithIv(this.contentIV, ciphertext),
encrypted_dek: this.packWithIv(dekIv, wrappedDek), encrypted_dek: this.packWithIv(this.dekIV, wrappedDek),
sharingKey: this.toBase64(new Uint8Array(rawDek)), sharingKey: this.toBase64(new Uint8Array(rawDek)),
}; };
} }