diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts index 3e36fd334ec..fcf31523f77 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts @@ -9,6 +9,7 @@ import { Decryptable } from "@bitwarden/common/platform/interfaces/decryptable.i import { Encrypted } from "@bitwarden/common/platform/interfaces/encrypted"; import { InitializerMetadata } from "@bitwarden/common/platform/interfaces/initializer-metadata.interface"; import { Utils } from "@bitwarden/common/platform/misc/utils"; +import { required, validate } from "@bitwarden/common/platform/misc/validate"; import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { PureCrypto } from "@bitwarden/sdk-internal"; @@ -61,36 +62,22 @@ export class EncryptServiceImplementation implements EncryptService { return PureCrypto.symmetric_decrypt_filedata(encBuffer.buffer, key.toEncoded()); } + @validate async wrapDecapsulationKey( - decapsulationKeyPkcs8: Uint8Array, - wrappingKey: SymmetricCryptoKey, + @required decapsulationKeyPkcs8: Uint8Array, + @required wrappingKey: SymmetricCryptoKey, ): Promise { - if (decapsulationKeyPkcs8 == null) { - throw new Error("No decapsulation key provided for wrapping."); - } - - if (wrappingKey == null) { - throw new Error("No wrappingKey provided for wrapping."); - } - await SdkLoadService.Ready; return new EncString( PureCrypto.wrap_decapsulation_key(decapsulationKeyPkcs8, wrappingKey.toEncoded()), ); } + @validate async wrapEncapsulationKey( - encapsulationKeySpki: Uint8Array, - wrappingKey: SymmetricCryptoKey, + @required encapsulationKeySpki: Uint8Array, + @required wrappingKey: SymmetricCryptoKey, ): Promise { - if (encapsulationKeySpki == null) { - throw new Error("No encapsulation key provided for wrapping."); - } - - if (wrappingKey == null) { - throw new Error("No wrappingKey provided for wrapping."); - } - await SdkLoadService.Ready; return new EncString( PureCrypto.wrap_encapsulation_key(encapsulationKeySpki, wrappingKey.toEncoded()), diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts b/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts index 4cc76d45f50..2df361f4deb 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.spec.ts @@ -115,15 +115,11 @@ describe("EncryptService", () => { }); it("fails if encapsulation key is null", async () => { const wrappingKey = new SymmetricCryptoKey(makeStaticByteArray(64)); - await expect(encryptService.wrapEncapsulationKey(null, wrappingKey)).rejects.toThrow( - "No encapsulation key provided for wrapping.", - ); + expect(() => encryptService.wrapEncapsulationKey(null, wrappingKey)).toThrow(); }); it("fails if wrapping key is null", async () => { const encapsulationKey = makeStaticByteArray(64); - await expect(encryptService.wrapEncapsulationKey(encapsulationKey, null)).rejects.toThrow( - "No wrappingKey provided for wrapping.", - ); + expect(() => encryptService.wrapEncapsulationKey(encapsulationKey, null)).toThrow(); }); }); diff --git a/libs/common/src/platform/misc/validate.ts b/libs/common/src/platform/misc/validate.ts new file mode 100644 index 00000000000..1a1533013ae --- /dev/null +++ b/libs/common/src/platform/misc/validate.ts @@ -0,0 +1,38 @@ +import "reflect-metadata"; +const requiredMetadataKey = Symbol("required"); + +export function required(target: object, propertyKey: string | symbol, parameterIndex: number) { + const existingRequiredParameters: number[] = + Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || []; + existingRequiredParameters.push(parameterIndex); + Reflect.defineMetadata(requiredMetadataKey, existingRequiredParameters, target, propertyKey); +} + +export function validate( + target: any, + propertyName: string, + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + descriptor: TypedPropertyDescriptor, +) { + const method = descriptor.value!; + + descriptor.value = function (...args: any[]) { + const requiredParameters: number[] = Reflect.getOwnMetadata( + requiredMetadataKey, + target, + propertyName, + ); + if (requiredParameters) { + for (const parameterIndex of requiredParameters) { + if ( + parameterIndex >= args.length || + args[parameterIndex] === undefined || + args[parameterIndex] === null + ) { + throw new Error("Missing required argument."); + } + } + } + return method.apply(this, args); + }; +}