blob: ae4beebb473ba83cfd66bd91d88443738af92c9a [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
goog.module('tink.signature.EcdsaUtil');
const EllipticCurves = goog.require('tink.subtle.EllipticCurves');
const PbEcdsaKeyFormat = goog.require('proto.google.crypto.tink.EcdsaKeyFormat');
const PbEcdsaParams = goog.require('proto.google.crypto.tink.EcdsaParams');
const PbEcdsaPrivateKey = goog.require('proto.google.crypto.tink.EcdsaPrivateKey');
const PbEcdsaPublicKey = goog.require('proto.google.crypto.tink.EcdsaPublicKey');
const PbEcdsaSignatureEncodingType = goog.require('proto.google.crypto.tink.EcdsaSignatureEncoding');
const SecurityException = goog.require('tink.exception.SecurityException');
const Util = goog.require('tink.Util');
const Validators = goog.require('tink.subtle.Validators');
/**
* @package
* @param {!PbEcdsaKeyFormat} keyFormat
*/
const validateKeyFormat = function(keyFormat) {
const params = keyFormat.getParams();
if (!params) {
throw new SecurityException('Invalid key format - missing params.');
}
validateParams(params);
};
/**
* @package
* @param {!PbEcdsaPrivateKey} key
* @param {number} privateKeyManagerVersion
* @param {number} publicKeyManagerVersion
*/
const validatePrivateKey = function(
key, privateKeyManagerVersion, publicKeyManagerVersion) {
Validators.validateVersion(key.getVersion(), privateKeyManagerVersion);
if (!key.getKeyValue()) {
throw new SecurityException(
'Invalid private key - missing private key value.');
}
const publicKey = key.getPublicKey();
if (!publicKey) {
throw new SecurityException(
'Invalid private key - missing public key information.');
}
validatePublicKey(publicKey, publicKeyManagerVersion);
};
/**
* @package
* @param {!PbEcdsaPublicKey} key
* @param {number} publicKeyManagerVersion
*/
const validatePublicKey = function(key, publicKeyManagerVersion) {
Validators.validateVersion(key.getVersion(), publicKeyManagerVersion);
const params = key.getParams();
if (!params) {
throw new SecurityException('Invalid public key - missing params.');
}
validateParams(params);
if (!key.getX() || !key.getY()) {
throw new SecurityException(
'Invalid public key - missing value of X or Y.');
}
};
/**
* @package
* @param {!PbEcdsaParams} params
*/
const validateParams = function(params) {
if (params.getEncoding() === PbEcdsaSignatureEncodingType.UNKNOWN_ENCODING) {
throw new SecurityException(
'Invalid public key - missing signature encoding.');
}
const hash = Util.hashTypeProtoToString(params.getHashType());
const curve = EllipticCurves.curveToString(
Util.curveTypeProtoToSubtle(params.getCurve()));
Validators.validateEcdsaParams(curve, hash);
};
/**
* @param {!PbEcdsaSignatureEncodingType} encodingTypeProto
* @return {!EllipticCurves.EcdsaSignatureEncodingType}
*/
const encodingTypeProtoToEnum = function(encodingTypeProto) {
switch (encodingTypeProto) {
case PbEcdsaSignatureEncodingType.DER:
return EllipticCurves.EcdsaSignatureEncodingType.DER;
case PbEcdsaSignatureEncodingType.IEEE_P1363:
return EllipticCurves.EcdsaSignatureEncodingType.IEEE_P1363;
default:
throw new SecurityException('Unknown ECDSA signature encoding type.');
}
};
/**
* WARNING: This method assumes that the given key proto is valid.
*
* @package
* @param {!PbEcdsaPrivateKey|!PbEcdsaPublicKey} key
* @return {!webCrypto.JsonWebKey}
*/
const getJsonWebKeyFromProto = function(key) {
let /** @type {!PbEcdsaPublicKey} */ publicKey;
let /** @type {!Uint8Array} */ d;
if (key instanceof PbEcdsaPrivateKey) {
publicKey = /** @type{!PbEcdsaPublicKey} */ (key.getPublicKey());
} else {
publicKey = key;
}
const curveType =
Util.curveTypeProtoToSubtle(publicKey.getParams().getCurve());
const expectedLength = EllipticCurves.fieldSizeInBytes(curveType);
let x = Util.bigEndianNumberToCorrectLength(
publicKey.getX_asU8(), expectedLength);
let y = Util.bigEndianNumberToCorrectLength(
publicKey.getY_asU8(), expectedLength);
if (key instanceof PbEcdsaPrivateKey) {
d = Util.bigEndianNumberToCorrectLength(
key.getKeyValue_asU8(), expectedLength);
}
return EllipticCurves.getJsonWebKey(curveType, x, y, d);
};
exports = {
encodingTypeProtoToEnum,
validateKeyFormat,
validateParams,
validatePublicKey,
validatePrivateKey,
getJsonWebKeyFromProto,
};