import { newUser, ResolvedNewUserResponse } from "index"; import { DecryptionError } from "./error"; import { ApplicationDataEncryptor } from "encryption/data/application-data-encryptor"; import { EncryptedData } from "encryption/data/asymmetric-data-encryptor"; describe("basic application encryptor usage", () => { // These things take a long time to create due to key generation. Use the same data across multiple tests let appCreatingUser: ResolvedNewUserResponse; let appSharedUser: ResolvedNewUserResponse; let appEncryptor: ApplicationDataEncryptor; let appPublicKey: JsonWebKey; // eslint-disable-next-line @typescript-eslint/no-unused-vars let appCreatingUserEncryptedPrivateKey: EncryptedData; let appSharedUserEncryptedPrivateKey: EncryptedData; beforeAll(async function() { appCreatingUser = await newUser("123456789"); appSharedUser = await newUser("987654321"); appEncryptor = await appCreatingUser.encryptor.createApplicationEncryptor(); appPublicKey = await appEncryptor.exportPublicKey(); appCreatingUserEncryptedPrivateKey = await appEncryptor.encryptPrivateKey( appCreatingUser.userDoc.encryption_key_pair.public_key ); appSharedUserEncryptedPrivateKey = await appEncryptor.encryptPrivateKey( appSharedUser.userDoc.encryption_key_pair.public_key ); // We need a long timeout as key generation can take a while }, 30000); test("a user cannot instantiate an application with someone else's encrypted private key", async function() { await expect( appCreatingUser.encryptor.loadApplicationEncryptorForDecryption( appPublicKey, appSharedUserEncryptedPrivateKey ) ).rejects.toThrowError( new DecryptionError( "The WAEPriK (Wrapped Application Encryption Private Key) for this application cannot be decrypted by this user.", "It probably belongs to another user." ) ); }); test("a shared application encryptor can decode data shared with the aplication", async function() { const dataToEncrypt = "Something super secret"; const encryptedData = await appEncryptor.encrypt(dataToEncrypt); const receivedApplicationEncryptor = await appSharedUser.encryptor.loadApplicationEncryptorForDecryption( appPublicKey, appSharedUserEncryptedPrivateKey ); expect(await receivedApplicationEncryptor.decrypt(encryptedData)).toBe( dataToEncrypt ); }); test("data can be shared with an application, and decrypted by another user using the application", async function() { const dataToEncrypt = "Something super secret"; const encryptedData = await appCreatingUser.encryptor.encrypt( dataToEncrypt ); const sharedDataKey = await appCreatingUser.encryptor.share( encryptedData, appPublicKey ); const receivedApplicationEncryptor = await appSharedUser.encryptor.loadApplicationEncryptorForDecryption( appPublicKey, appSharedUserEncryptedPrivateKey ); const decryptedData = await receivedApplicationEncryptor.decrypt( encryptedData, sharedDataKey ); expect(decryptedData).toBe(dataToEncrypt); }); test("data shared with one application cannot be decrypted by another application", async function() { const dataToEncrypt = "Something super secret"; const encryptedData = await appCreatingUser.encryptor.encrypt( dataToEncrypt ); const sharedDataKey = await appCreatingUser.encryptor.share( encryptedData, appPublicKey ); const otherApplicationEncryptor = await appCreatingUser.encryptor.createApplicationEncryptor(); await expect( otherApplicationEncryptor.decrypt(encryptedData, sharedDataKey) ).rejects.toThrowError( new DecryptionError( "Failed to decrypt WDEK (Wrapped Data Encryption Key).", "The WDEK probably belongs to another user or application." ) ); }); test("data shared with an application cannot be decrypted with the wrong key", async function() { const encryptedData = await appCreatingUser.encryptor.encrypt( "Something super secret" ); const someOtherEncryptedData = await appCreatingUser.encryptor.encrypt( "aaa" ); const wrongKey = await appCreatingUser.encryptor.share( someOtherEncryptedData, appPublicKey ); const receivedApplicationEncryptor = await appSharedUser.encryptor.loadApplicationEncryptorForDecryption( appPublicKey, appSharedUserEncryptedPrivateKey ); await expect( receivedApplicationEncryptor.decrypt(encryptedData, wrongKey) ).rejects.toThrowError( new DecryptionError( "The WD (Wrapped Data) supplied cannot be decrypted by the WDEK (Wrapped Data Key Encryption Key) supplied.", "The key is probably for different WD." ) ); }); test("data shared with an application can be shared with another application", async function() { const app2Encryptor = await appCreatingUser.encryptor.createApplicationEncryptor(); const app2PublicKey = await app2Encryptor.exportPublicKey(); const dataToEncrypt = "Something super secret"; const encryptedData = await appSharedUser.encryptor.encrypt( dataToEncrypt ); const sharedDataKey = await appSharedUser.encryptor.share( encryptedData, appPublicKey ); const app2SharedDataKey = await appEncryptor.share( encryptedData, app2PublicKey, sharedDataKey ); // app1 shouldn't be able to decrypt with the key we created for app2 await expect( appEncryptor.decrypt(encryptedData, app2SharedDataKey) ).rejects.toThrowError( new DecryptionError( "Failed to decrypt WDEK (Wrapped Data Encryption Key).", undefined ) ); // app2 shouldn't be able to decrypt with the key we created for app1 await expect( app2Encryptor.decrypt(encryptedData, sharedDataKey) ).rejects.toThrowError( new DecryptionError( "Failed to decrypt WDEK (Wrapped Data Encryption Key).", undefined ) ); expect( await app2Encryptor.decrypt(encryptedData, app2SharedDataKey) ).toBe(dataToEncrypt); }); test("data can be shared with an application, and decrypted by another user using the application after the data has been updated", async function() { const originalDataToEncrypt = "Something super secret"; const encryptedData = await appCreatingUser.encryptor.encrypt( originalDataToEncrypt ); const sharedDataKey = await appCreatingUser.encryptor.share( encryptedData, appPublicKey ); const newDataToEncrypt = "Something different"; const newEncryptedData = await appCreatingUser.encryptor.update( newDataToEncrypt, encryptedData ); const receivedApplicationEncryptor = await appSharedUser.encryptor.loadApplicationEncryptorForDecryption( appPublicKey, appSharedUserEncryptedPrivateKey ); const decryptedData = await receivedApplicationEncryptor.decrypt( newEncryptedData, sharedDataKey ); expect(decryptedData).toBe(newDataToEncrypt); }); });