/* * 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'); } }