blob: b8013cef58e1f56e9a72ad7e2790564b8f952d3e [file] [log] [blame]
/**
* @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;
}
}