blob: 46d75e262b08df382309d97e3514f89678034dd0 [file] [log] [blame]
/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {SecurityException} from '../exception/security_exception';
import * as KeyManager from '../internal/key_manager';
import {PbEcdsaParams, PbEcdsaPublicKey, PbKeyData, PbMessage} from '../internal/proto';
import * as Util from '../internal/util';
import * as ecdsaVerify from '../subtle/ecdsa_verify';
import * as EcdsaUtil from './ecdsa_util';
import {PublicKeyVerify} from './internal/public_key_verify';
/**
* @final
*/
class EcdsaPublicKeyFactory implements KeyManager.KeyFactory {
newKey(keyFormat: PbMessage|Uint8Array): never {
throw new SecurityException(
'This operation is not supported for public keys. ' +
'Use EcdsaPrivateKeyManager to generate new keys.');
}
newKeyData(serializedKeyFormat: Uint8Array): never {
throw new SecurityException(
'This operation is not supported for public keys. ' +
'Use EcdsaPrivateKeyManager to generate new keys.');
}
}
/**
* @final
*/
export class EcdsaPublicKeyManager implements
KeyManager.KeyManager<PublicKeyVerify> {
static KEY_TYPE: string =
'type.googleapis.com/google.crypto.tink.EcdsaPublicKey';
private static readonly SUPPORTED_PRIMITIVE = PublicKeyVerify;
static VERSION: number = 0;
keyFactory = new EcdsaPublicKeyFactory();
async getPrimitive(
primitiveType: Util.Constructor<PublicKeyVerify>,
key: PbKeyData|PbMessage) {
if (primitiveType !== this.getPrimitiveType()) {
throw new SecurityException(
'Requested primitive type which is not ' +
'supported by this key manager.');
}
const keyProto = EcdsaPublicKeyManager.getKeyProto(key);
EcdsaUtil.validatePublicKey(keyProto, this.getVersion());
const jwk = EcdsaUtil.getJsonWebKeyFromProto(keyProto);
const params = (keyProto.getParams() as PbEcdsaParams);
const hash = Util.hashTypeProtoToString(params.getHashType());
const encoding = EcdsaUtil.encodingTypeProtoToEnum(params.getEncoding());
return ecdsaVerify.fromJsonWebKey(jwk, hash, encoding);
}
doesSupport(keyType: string) {
return keyType === this.getKeyType();
}
getKeyType() {
return EcdsaPublicKeyManager.KEY_TYPE;
}
getPrimitiveType() {
return EcdsaPublicKeyManager.SUPPORTED_PRIMITIVE;
}
getVersion() {
return EcdsaPublicKeyManager.VERSION;
}
getKeyFactory() {
return this.keyFactory;
}
private static getKeyProto(keyMaterial: PbKeyData|
PbMessage): PbEcdsaPublicKey {
if (keyMaterial instanceof PbKeyData) {
return EcdsaPublicKeyManager.getKeyProtoFromKeyData(keyMaterial);
}
if (keyMaterial instanceof PbEcdsaPublicKey) {
return keyMaterial;
}
throw new SecurityException(
'Key type is not supported. This key manager supports ' +
EcdsaPublicKeyManager.KEY_TYPE + '.');
}
private static getKeyProtoFromKeyData(keyData: PbKeyData): PbEcdsaPublicKey {
if (keyData.getTypeUrl() !== EcdsaPublicKeyManager.KEY_TYPE) {
throw new SecurityException(
'Key type ' + keyData.getTypeUrl() + ' is not supported. This key ' +
'manager supports ' + EcdsaPublicKeyManager.KEY_TYPE + '.');
}
let key: PbEcdsaPublicKey;
try {
key = PbEcdsaPublicKey.deserializeBinary(keyData.getValue_asU8());
} catch (e) {
throw new SecurityException(
'Input cannot be parsed as ' + EcdsaPublicKeyManager.KEY_TYPE +
' key-proto.');
}
if (!key.getParams() || !key.getX_asU8() || !key.getY_asU8()) {
throw new SecurityException(
'Input cannot be parsed as ' + EcdsaPublicKeyManager.KEY_TYPE +
' key-proto.');
}
return key;
}
}