import { Observable } from "rxjs"; import { ProfileOrganizationResponse } from "../../admin-console/models/response/profile-organization.response"; import { ProfileProviderOrganizationResponse } from "../../admin-console/models/response/profile-provider-organization.response"; import { ProfileProviderResponse } from "../../admin-console/models/response/profile-provider.response"; import { KdfConfig } from "../../auth/models/domain/kdf-config"; import { OrganizationId, ProviderId, UserId } from "../../types/guid"; import { UserKey, MasterKey, OrgKey, ProviderKey, PinKey, CipherKey } from "../../types/key"; import { KeySuffixOptions, HashPurpose } from "../enums"; import { EncArrayBuffer } from "../models/domain/enc-array-buffer"; import { EncString } from "../models/domain/enc-string"; import { SymmetricCryptoKey } from "../models/domain/symmetric-crypto-key"; export abstract class CryptoService { abstract activeUserKey$: Observable; /** * Returns the an observable key for the given user id. * * @note this observable represents only user keys stored in memory. A null value does not indicate that we cannot load a user key from storage. * @param userId The desired user */ abstract getInMemoryUserKeyFor$(userId: UserId): Observable; /** * Sets the provided user key and stores * any other necessary versions (such as auto, biometrics, * or pin) * * @throws when key is null. Lock the account to clear a key * @param key The user key to set * @param userId The desired user */ abstract setUserKey(key: UserKey, userId?: string): Promise; /** * Gets the user key from memory and sets it again, * kicking off a refresh of any additional keys * (such as auto, biometrics, or pin) */ abstract refreshAdditionalKeys(): Promise; /** * Observable value that returns whether or not the currently active user has ever had auser key, * i.e. has ever been unlocked/decrypted. This is key for differentiating between TDE locked and standard locked states. */ abstract everHadUserKey$: Observable; /** * Retrieves the user key * @param userId The desired user * @returns The user key */ abstract getUserKey(userId?: string): Promise; /** * Checks if the user is using an old encryption scheme that used the master key * for encryption of data instead of the user key. */ abstract isLegacyUser(masterKey?: MasterKey, userId?: string): Promise; /** * Use for encryption/decryption of data in order to support legacy * encryption models. It will return the user key if available, * if not it will return the master key. * @param userId The desired user */ abstract getUserKeyWithLegacySupport(userId?: string): Promise; /** * Retrieves the user key from storage * @param keySuffix The desired version of the user's key to retrieve * @param userId The desired user * @returns The user key */ abstract getUserKeyFromStorage(keySuffix: KeySuffixOptions, userId?: string): Promise; /** * Determines whether the user key is available for the given user. * @param userId The desired user. If not provided, the active user will be used. If no active user exists, the method will return false. * @returns True if the user key is available */ abstract hasUserKey(userId?: UserId): Promise; /** * Determines whether the user key is available for the given user in memory. * @param userId The desired user. If not provided, the active user will be used. If no active user exists, the method will return false. * @returns True if the user key is available */ abstract hasUserKeyInMemory(userId?: string): Promise; /** * @param keySuffix The desired version of the user's key to check * @param userId The desired user * @returns True if the provided version of the user key is stored */ abstract hasUserKeyStored(keySuffix: KeySuffixOptions, userId?: string): Promise; /** * Generates a new user key * @param masterKey The user's master key * @returns A new user key and the master key protected version of it */ abstract makeUserKey(key: MasterKey): Promise<[UserKey, EncString]>; /** * Clears the user's stored version of the user key * @param keySuffix The desired version of the key to clear * @param userId The desired user */ abstract clearStoredUserKey(keySuffix: KeySuffixOptions, userId?: string): Promise; /** * Stores the master key encrypted user key * @param userKeyMasterKey The master key encrypted user key to set * @param userId The desired user */ abstract setMasterKeyEncryptedUserKey(UserKeyMasterKey: string, userId?: string): Promise; /** * @param password The user's master password that will be used to derive a master key if one isn't found * @param userId The desired user */ abstract getOrDeriveMasterKey(password: string, userId?: string): Promise; /** * Generates a master key from the provided password * @param password The user's master password * @param email The user's email * @param KdfConfig The user's key derivation function configuration * @returns A master key derived from the provided password */ abstract makeMasterKey(password: string, email: string, KdfConfig: KdfConfig): Promise; /** * Encrypts the existing (or provided) user key with the * provided master key * @param masterKey The user's master key * @param userKey The user key * @returns The user key and the master key protected version of it */ abstract encryptUserKeyWithMasterKey( masterKey: MasterKey, userKey?: UserKey, ): Promise<[UserKey, EncString]>; /** * Decrypts the user key with the provided master key * @param masterKey The user's master key * @param userKey The user's encrypted symmetric key * @param userId The desired user * @returns The user key */ abstract decryptUserKeyWithMasterKey( masterKey: MasterKey, userKey?: EncString, userId?: string, ): Promise; /** * Creates a master password hash from the user's master password. Can * be used for local authentication or for server authentication depending * on the hashPurpose provided. * @param password The user's master password * @param key The user's master key * @param hashPurpose The iterations to use for the hash * @returns The user's master password hash */ abstract hashMasterKey( password: string, key: MasterKey, hashPurpose?: HashPurpose, ): Promise; /** * Compares the provided master password to the stored password hash and server password hash. * Updates the stored hash if outdated. * @param masterPassword The user's master password * @param key The user's master key * @returns True if the provided master password matches either the stored * key hash or the server key hash */ abstract compareAndUpdateKeyHash(masterPassword: string, masterKey: MasterKey): Promise; /** * Stores the encrypted organization keys and clears any decrypted * organization keys currently in memory * @param orgs The organizations to set keys for * @param providerOrgs The provider organizations to set keys for */ abstract setOrgKeys( orgs: ProfileOrganizationResponse[], providerOrgs: ProfileProviderOrganizationResponse[], ): Promise; abstract activeUserOrgKeys$: Observable>; /** * Returns the organization's symmetric key * @deprecated Use the observable activeUserOrgKeys$ and `map` to the desired orgKey instead * @param orgId The desired organization * @returns The organization's symmetric key */ abstract getOrgKey(orgId: string): Promise; /** * @deprecated Use the observable activeUserOrgKeys$ instead * @returns A record of the organization Ids to their symmetric keys */ abstract getOrgKeys(): Promise>; /** * Uses the org key to derive a new symmetric key for encrypting data * @param orgKey The organization's symmetric key */ abstract makeDataEncKey( key: T, ): Promise<[SymmetricCryptoKey, EncString]>; /** * Stores the encrypted provider keys and clears any decrypted * provider keys currently in memory * @param providers The providers to set keys for */ abstract activeUserProviderKeys$: Observable>; abstract setProviderKeys(orgs: ProfileProviderResponse[]): Promise; /** * @param providerId The desired provider * @returns The provider's symmetric key */ abstract getProviderKey(providerId: string): Promise; /** * @returns A record of the provider Ids to their symmetric keys */ abstract getProviderKeys(): Promise>; /** * Returns the public key from memory. If not available, extracts it * from the private key and stores it in memory * @returns The user's public key */ abstract getPublicKey(): Promise; /** * Creates a new organization key and encrypts it with the user's public key. * This method can also return Provider keys for creating new Provider users. * @returns The new encrypted org key and the decrypted key itself */ abstract makeOrgKey(): Promise<[EncString, T]>; /** * Sets the user's encrypted private key in storage and * clears the decrypted private key from memory * Note: does not clear the private key if null is provided * @param encPrivateKey An encrypted private key */ abstract setPrivateKey(encPrivateKey: string): Promise; /** * Returns the private key from memory. If not available, decrypts it * from storage and stores it in memory * @returns The user's private key */ abstract getPrivateKey(): Promise; /** * Generates a fingerprint phrase for the user based on their public key * @param fingerprintMaterial Fingerprint material * @param publicKey The user's public key * @returns The user's fingerprint phrase */ abstract getFingerprint(fingerprintMaterial: string, publicKey?: Uint8Array): Promise; /** * Generates a new keypair * @param key A key to encrypt the private key with. If not provided, * defaults to the user key * @returns A new keypair: [publicKey in Base64, encrypted privateKey] */ abstract makeKeyPair(key?: SymmetricCryptoKey): Promise<[string, EncString]>; /** * @param pin The user's pin * @param salt The user's salt * @param kdfConfig The user's kdf config * @returns A key derived from the user's pin */ abstract makePinKey(pin: string, salt: string, kdfConfig: KdfConfig): Promise; /** * Clears the user's pin keys from storage * Note: This will remove the stored pin and as a result, * disable pin protection for the user * @param userId The desired user */ abstract clearPinKeys(userId?: string): Promise; /** * Decrypts the user key with their pin * @param pin The user's PIN * @param salt The user's salt * @param kdfConfig The user's KDF config * @param pinProtectedUserKey The user's PIN protected symmetric key, if not provided * it will be retrieved from storage * @returns The decrypted user key */ abstract decryptUserKeyWithPin( pin: string, salt: string, kdfConfig: KdfConfig, protectedKeyCs?: EncString, ): Promise; /** * Creates a new Pin key that encrypts the user key instead of the * master key. Clears the old Pin key from state. * @param masterPasswordOnRestart True if Master Password on Restart is enabled * @param pin User's PIN * @param email User's email * @param kdfConfig User's KdfConfig * @param oldPinKey The old Pin key from state (retrieved from different * places depending on if Master Password on Restart was enabled) * @returns The user key */ abstract decryptAndMigrateOldPinKey( masterPasswordOnRestart: boolean, pin: string, email: string, kdfConfig: KdfConfig, oldPinKey: EncString, ): Promise; /** * Replaces old master auto keys with new user auto keys */ abstract migrateAutoKeyIfNeeded(userId?: string): Promise; /** * @param keyMaterial The key material to derive the send key from * @returns A new send key */ abstract makeSendKey(keyMaterial: Uint8Array): Promise; /** * Clears all of the user's keys from storage * @param userId The user's Id */ abstract clearKeys(userId?: string): Promise; /** * RSA encrypts a value. * @param data The data to encrypt * @param publicKey The public key to use for encryption, if not provided, the user's public key will be used * @returns The encrypted data */ abstract rsaEncrypt(data: Uint8Array, publicKey?: Uint8Array): Promise; /** * Decrypts a value using RSA. * @param encValue The encrypted value to decrypt * @param privateKeyValue The private key to use for decryption * @returns The decrypted value */ abstract rsaDecrypt(encValue: string, privateKeyValue?: Uint8Array): Promise; abstract randomNumber(min: number, max: number): Promise; /** * Generates a new cipher key * @returns A new cipher key */ abstract makeCipherKey(): Promise; /** * Initialize all necessary crypto keys needed for a new account. * Warning! This completely replaces any existing keys! * @returns The user's newly created public key, private key, and encrypted private key */ abstract initAccount(): Promise<{ userKey: UserKey; publicKey: string; privateKey: EncString; }>; /** * @deprecated Left for migration purposes. Use decryptUserKeyWithPin instead. */ abstract decryptMasterKeyWithPin( pin: string, salt: string, kdfConfig: KdfConfig, protectedKeyCs?: EncString, ): Promise; /** * Previously, the master key was used for any additional key like the biometrics or pin key. * We have switched to using the user key for these purposes. This method is for clearing the state * of the older keys on logout or post migration. * @param keySuffix The desired type of key to clear * @param userId The desired user */ abstract clearDeprecatedKeys(keySuffix: KeySuffixOptions, userId?: string): Promise; /** * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.encrypt */ abstract encrypt(plainValue: string | Uint8Array, key?: SymmetricCryptoKey): Promise; /** * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.encryptToBytes */ abstract encryptToBytes( plainValue: Uint8Array, key?: SymmetricCryptoKey, ): Promise; /** * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.decryptToBytes */ abstract decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise; /** * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.decryptToUtf8 */ abstract decryptToUtf8(encString: EncString, key?: SymmetricCryptoKey): Promise; /** * @deprecated July 25 2022: Get the key you need from CryptoService (getKeyForUserEncryption or getOrgKey) * and then call encryptService.decryptToBytes */ abstract decryptFromBytes( encBuffer: EncArrayBuffer, key: SymmetricCryptoKey, ): Promise; }