diff --git a/libs/common/src/platform/abstractions/crypto.service.ts b/libs/common/src/platform/abstractions/crypto.service.ts index 83e45a89fc4..34451b8b784 100644 --- a/libs/common/src/platform/abstractions/crypto.service.ts +++ b/libs/common/src/platform/abstractions/crypto.service.ts @@ -37,6 +37,7 @@ export abstract class CryptoService { masterKey: MasterKey, userSymKey?: UserSymKey ) => Promise<[UserSymKey, EncString]>; + decryptUserSymKeyWithMasterKey: (masterKey: MasterKey, userId?: string) => Promise; hashPassword: (password: string, key: MasterKey, hashPurpose?: HashPurpose) => Promise; setKeyHash: (keyHash: string) => Promise; getKeyHash: () => Promise; diff --git a/libs/common/src/platform/services/crypto.service.ts b/libs/common/src/platform/services/crypto.service.ts index 6710f687169..b3443726d94 100644 --- a/libs/common/src/platform/services/crypto.service.ts +++ b/libs/common/src/platform/services/crypto.service.ts @@ -229,6 +229,42 @@ export class CryptoService implements CryptoServiceAbstraction { return this.buildProtectedUserSymKey(masterKey, userSymKey.key); } + /** + * Decrypts the user symmetric key with the provided master key + * @param masterKey The user's master key + * @param userId The desired user + * @returns The user's symmetric key + */ + async decryptUserSymKeyWithMasterKey(masterKey: MasterKey, userId?: string): Promise { + masterKey ||= await this.getMasterKey(); + if (masterKey == null) { + throw new Error("No Master Key found."); + } + + // TODO: Do we need to let this be passed in as well? + const userSymKeyMasterKey = await this.stateService.getUserSymKeyMasterKey({ userId: userId }); + if (userSymKeyMasterKey == null) { + throw new Error("No User Key found."); + } + + let decUserKey: ArrayBuffer; + const encUserKey = new EncString(userSymKeyMasterKey); + if (encUserKey.encryptionType === EncryptionType.AesCbc256_B64) { + decUserKey = await this.decryptToBytes(encUserKey, masterKey); + } else if (encUserKey.encryptionType === EncryptionType.AesCbc256_HmacSha256_B64) { + const newKey = await this.stretchKey(masterKey); + decUserKey = await this.decryptToBytes(encUserKey, newKey); + } else { + throw new Error("Unsupported encryption type."); + } + if (decUserKey == null) { + return null; + } + + // TODO: Do we want to set the user key here? + return new SymmetricCryptoKey(decUserKey) as UserSymKey; + } + /** * Creates a master password hash from the user's master password. Can * be used for local authentication or for server authentication depending