/*
* Copyright 2018 Scytl Secure Electronic Voting SA
*
* All rights reserved
*
* See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
*/
/* jshint node:true */
'use strict';
var RsaPublicKey = require('./rsa-public-key');
var RsaPrivateKey = require('./rsa-private-key');
var KeyPair = require('./keypair');
var KeyPairGenerator = require('./keypair-generator');
var Signer = require('./signer');
var SignatureVerifier = require('./signature-verifier');
var AsymmetricEncrypter = require('./encrypter');
var AsymmetricDecrypter = require('./decrypter');
var validator = require('./input-validator');
var cryptoPolicy = require('scytl-cryptopolicy');
var secureRandom = require('scytl-securerandom');
var forge = require('node-forge');
module.exports = AsymmetricCryptographyService;
/**
* @class AsymmetricCryptographyService
* @classdesc The asymmetric cryptography service API. To instantiate this
* object, use the method {@link newService}.
* @hideconstructor
* @param {Object}
* [options] An object containing optional arguments.
* @param {Policy}
* [options.policy=Default policy] The cryptographic policy to use.
* @param {SecureRandomService}
* [options.secureRandomService=Created internally] The secure random
* service to use.
*/
function AsymmetricCryptographyService(options) {
options = options || {};
var policy_;
if (options.policy) {
policy_ = options.policy;
} else {
policy_ = cryptoPolicy.newInstance();
}
var secureRandomService_;
if (options.secureRandomService) {
secureRandomService_ = options.secureRandomService;
} else {
secureRandomService_ = secureRandom.newService();
}
/**
* Creates a new RsaPublicKey object from a provided RSA public key or its
* components.
*
* @function newRsaPublicKey
* @memberof AsymmetricCryptographyService
* @param {Object}
* params An object containing the input parameters for the
* RsaPublicKey object creation.
* @param {string}
* params.pem a PEM string representation of the key. Any
* additional parameters will be ignored.
* @param {number}
* params.n The modulus of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.e The public exponent of the key. Required if
* params.pem
is undefined.
* @returns {RsaPublicKey} The new RsaPublicKey object.
*/
this.newRsaPublicKey = function(params) {
validator.checkIsObjectWithProperties(
params, 'Parameters object for creation of RsaPublicKey object');
if (!params.pem) {
checkPublicKeyData(params);
return new RsaPublicKey(params);
} else {
validator.checkIsNonEmptyString(
params.pem, 'RSA public key, PEM encoded');
var forgePublicKey = forge.pki.publicKeyFromPem(params.pem);
if (typeof forgePublicKey.encrypt === 'undefined') {
throw new Error(
'PEM encoding of public key for creation of RsaPublicKey object is corrupt');
}
return new RsaPublicKey({n: forgePublicKey.n, e: forgePublicKey.e});
}
};
/**
* Creates a new RsaPrivateKey object from a provided RSA private key or its
* components.
*
* @function newRsaPrivateKey
* @memberof AsymmetricCryptographyService
* @param {Object}
* params An object containing the input parameters for the
* RsaPrivateKey object creation.
* @param {Object}
* params An object containing the required input parameters.
* @param {string}
* params.pem a PEM string representation of the key. Any
* additional parameters will be ignored.
* @param {number}
* params.n The modulus of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.e The public exponent of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.d The private exponent of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.p The first prime of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.q The second prime of the key Required if
* params.pem
is undefined.
* @param {number}
* params.dP The first exponent of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.dQ The second exponent of the key. Required if
* params.pem
is undefined.
* @param {number}
* params.qInv The coefficient of the key. Required if
* params.pem
is undefined.
* @returns {RsaPrivateKey} The new RsaPrivateKey object.
*/
this.newRsaPrivateKey = function(params) {
validator.checkIsObjectWithProperties(
params, 'Parameters object for creation of RsaPrivateKey object');
if (!params.pem) {
checkPrivateKeyData(params);
return new RsaPrivateKey(params);
} else {
validator.checkIsNonEmptyString(
params.pem, 'RSA public key, PEM encoded');
var forgePrivateKey = forge.pki.privateKeyFromPem(params.pem);
if (typeof forgePrivateKey.decrypt === 'undefined') {
throw new Error(
'PEM encoding of private key for creation of RsaPrivateKey object is corrupt');
}
return new RsaPrivateKey({
n: forgePrivateKey.n,
e: forgePrivateKey.e,
d: forgePrivateKey.d,
p: forgePrivateKey.p,
q: forgePrivateKey.q,
dP: forgePrivateKey.dP,
dQ: forgePrivateKey.dQ,
qInv: forgePrivateKey.qInv
});
}
};
/**
* Creates a new KeyPair object from a provided key pair.
*
* @function newKeyPair
* @memberof AsymmetricCryptographyService
* @param {string}
* publicKey The public key comprising the key pair, in PEM
* format.
* @param {string}
* privateKey The private key comprising the key pair, in PEM
* format.
* @returns {KeyPair} The new KeyPair object.
*/
this.newKeyPair = function(publicKey, privateKey) {
validator.checkIsNonEmptyString(publicKey, 'Public key, PEM encoded');
validator.checkIsNonEmptyString(privateKey, 'Private key, PEM encoded');
return new KeyPair(publicKey, privateKey);
};
/**
* Creates a new KeyPairGenerator object for generating key pairs.
*
* @function newKeyPairGenerator
* @memberof AsymmetricCryptographyService
* @returns {RsaKeyPairGenerator} The new RsaKeyPairGenerator object.
*/
this.newKeyPairGenerator = function() {
return new KeyPairGenerator(policy_, secureRandomService_);
};
/**
* Creates a new Signer object for digitally signing data. It must be
* initialized with a private key.
*
* @function newSigner
* @memberof AsymmetricCryptographyService
* @returns {Signer} The new Signer object.
*/
this.newSigner = function() {
return new Signer(policy_, secureRandomService_);
};
/**
* Creates a new SignatureVerifier object for verifying a digital
* signatures. It must be initialized with a public key.
*
* @function newSignatureVerifier
* @memberof AsymmetricCryptographyService
* @returns {SignatureVerifier} The new SignatureVerifier object.
*/
this.newSignatureVerifier = function() {
return new SignatureVerifier(policy_, secureRandomService_);
};
/**
* Creates a new AsymmetricEncrypter object for encrypting data. It must be
* initialized with a public key.
*
* @function newEncrypter
* @memberof AsymmetricCryptographyService
* @returns {AsymmetricEncrypter} The new AsymmetricEncrypter object.
*/
this.newEncrypter = function() {
return new AsymmetricEncrypter(policy_, secureRandomService_);
};
/**
* Creates a new AsymmetricDecrypter object for decrypting data. It must be
* initialized with a private key.
*
* @function newDecrypter
* @memberof AsymmetricCryptographyService
* @returns {AsymmetricDecrypter} The new AsymmetricDecrypter object.
*/
this.newDecrypter = function() {
return new AsymmetricDecrypter(policy_);
};
function checkPublicKeyData(params) {
validator.checkIsPositiveBigInteger(params.n, 'RSA public key modulus');
validator.checkIsPositiveBigInteger(
params.e, 'RSA public key public exponent');
}
function checkPrivateKeyData(params) {
validator.checkIsPositiveBigInteger(params.n, 'RSA private key modulus');
validator.checkIsPositiveBigInteger(
params.e, 'RSA private key public exponent');
validator.checkIsPositiveBigInteger(
params.d, 'RSA private key private exponent');
validator.checkIsPositiveBigInteger(
params.p, 'RSA private key first prime');
validator.checkIsPositiveBigInteger(
params.q, 'RSA private key second prime');
validator.checkIsPositiveBigInteger(
params.dP, 'RSA private key first exponent');
validator.checkIsPositiveBigInteger(
params.dQ, 'RSA private key second exponent');
validator.checkIsPositiveBigInteger(
params.qInv, 'RSA private key coefficient');
}
}