| /** |
| * @license |
| * Copyright 2020 Google LLC |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| import {SecurityException} from '../exception/security_exception'; |
| import {CryptoFormat} from '../internal/crypto_format'; |
| import * as PrimitiveSet from '../internal/primitive_set'; |
| import {PrimitiveWrapper} from '../internal/primitive_wrapper'; |
| import {PbKeyStatusType} from '../internal/proto'; |
| import * as Validators from '../subtle/validators'; |
| |
| import {PublicKeyVerify} from './internal/public_key_verify'; |
| |
| /** |
| * @final |
| */ |
| class WrappedPublicKeyVerify extends PublicKeyVerify { |
| // The constructor should be @private, but it is not supported by Closure |
| // (see https://github.com/google/closure-compiler/issues/2761). |
| constructor(private readonly primitiveSet: |
| PrimitiveSet.PrimitiveSet<PublicKeyVerify>) { |
| super(); |
| } |
| |
| static newPublicKeyVerify(primitiveSet: |
| PrimitiveSet.PrimitiveSet<PublicKeyVerify>): |
| PublicKeyVerify { |
| if (!primitiveSet) { |
| throw new SecurityException('Primitive set has to be non-null.'); |
| } |
| return new WrappedPublicKeyVerify(primitiveSet); |
| } |
| |
| async verify(signature: Uint8Array, data: Uint8Array) { |
| Validators.requireUint8Array(signature); |
| Validators.requireUint8Array(data); |
| if (signature.length > CryptoFormat.NON_RAW_PREFIX_SIZE) { |
| const keyId = signature.subarray(0, CryptoFormat.NON_RAW_PREFIX_SIZE); |
| const primitives = await this.primitiveSet.getPrimitives(keyId); |
| const rawSignature = signature.subarray( |
| CryptoFormat.NON_RAW_PREFIX_SIZE, signature.length); |
| let isValid: boolean = false; |
| try { |
| isValid = await this.tryVerification(primitives, rawSignature, data); |
| } catch (e) { |
| // Ignored. |
| } |
| |
| if (isValid) { |
| return isValid; |
| } |
| } |
| const primitives = await this.primitiveSet.getRawPrimitives(); |
| return this.tryVerification(primitives, signature, data); |
| } |
| |
| /** |
| * Tries to verify the signature using each entry in primitives. It |
| * returns false if no entry succeeds. |
| * |
| * |
| */ |
| private async tryVerification( |
| primitives: Array<PrimitiveSet.Entry<PublicKeyVerify>>, |
| signature: Uint8Array, data: Uint8Array): Promise<boolean> { |
| const primitivesLength = primitives.length; |
| for (let i = 0; i < primitivesLength; i++) { |
| if (primitives[i].getKeyStatus() != PbKeyStatusType.ENABLED) { |
| continue; |
| } |
| const primitive = primitives[i].getPrimitive(); |
| let isValid: boolean; |
| try { |
| isValid = await primitive.verify(signature, data); |
| } catch (e) { |
| continue; |
| } |
| if (isValid) { |
| return isValid; |
| } |
| } |
| return false; |
| } |
| } |
| |
| export class PublicKeyVerifyWrapper implements |
| PrimitiveWrapper<PublicKeyVerify> { |
| /** |
| */ |
| wrap(primitiveSet: PrimitiveSet.PrimitiveSet<PublicKeyVerify>) { |
| return WrappedPublicKeyVerify.newPublicKeyVerify(primitiveSet); |
| } |
| |
| /** |
| */ |
| getPrimitiveType() { |
| return PublicKeyVerify; |
| } |
| } |