mirror of
https://github.com/ramvignesh-b/pi-ku.git
synced 2026-05-04 08:56:52 +00:00
feat: implement on-demand sharing key derivation
This commit is contained in:
@@ -190,3 +190,44 @@ describe("Sharing Key Decryption", () => {
|
|||||||
expect(decryptedLetter).toBe(letterContent);
|
expect(decryptedLetter).toBe(letterContent);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("extractSharingKey", () => {
|
||||||
|
let masterKey: CryptoKey;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
utils = new CryptoUtils();
|
||||||
|
await utils.initialize();
|
||||||
|
const bundle = await CryptoUtils.deriveKeyBundle(
|
||||||
|
"password",
|
||||||
|
"test@test.com",
|
||||||
|
);
|
||||||
|
masterKey = bundle.masterKey;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the same key that encryptLetter embedded as sharingKey", async () => {
|
||||||
|
const encrypted = await utils.encryptLetter("any content", masterKey);
|
||||||
|
|
||||||
|
const extracted = await utils.extractSharingKey(
|
||||||
|
encrypted.encrypted_dek,
|
||||||
|
masterKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(extracted).toBe(encrypted.sharingKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("extracted key should decrypt the ciphertext produced by encryptLetter", async () => {
|
||||||
|
const plaintext = "hello from the owner";
|
||||||
|
const encrypted = await utils.encryptLetter(plaintext, masterKey);
|
||||||
|
|
||||||
|
const extracted = await utils.extractSharingKey(
|
||||||
|
encrypted.encrypted_dek,
|
||||||
|
masterKey,
|
||||||
|
);
|
||||||
|
const decrypted = await utils.decryptLetterWithSharingKey(
|
||||||
|
encrypted.encrypted_content,
|
||||||
|
extracted,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(decrypted).toBe(plaintext);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -309,4 +309,24 @@ export class CryptoUtils {
|
|||||||
);
|
);
|
||||||
return URL.createObjectURL(new Blob([bytes]));
|
return URL.createObjectURL(new Blob([bytes]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-derives the sharing key (raw DEK) on demand (browser only, not sent to server).
|
||||||
|
public async extractSharingKey(
|
||||||
|
encrypted_dek: string,
|
||||||
|
masterKey: CryptoKey,
|
||||||
|
): Promise<string> {
|
||||||
|
const [dekIv, wrappedDek] = this.unpackWithIv(encrypted_dek);
|
||||||
|
const rawDek = await crypto.subtle.unwrapKey(
|
||||||
|
"raw",
|
||||||
|
wrappedDek,
|
||||||
|
masterKey,
|
||||||
|
{ name: "AES-GCM", iv: dekIv },
|
||||||
|
CryptoUtils.AES_GCM,
|
||||||
|
true,
|
||||||
|
["decrypt"],
|
||||||
|
);
|
||||||
|
return this.toBase64(
|
||||||
|
new Uint8Array(await crypto.subtle.exportKey("raw", rawDek)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user