123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * 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 DigitalEnvelope = require('./envelope');
- var EncryptedSecretKeyPair = require('./encrypted-secret-keypair');
- var cryptoPolicy = require('scytl-cryptopolicy');
- var asymmetric = require('scytl-asymmetric');
- var symmetric = require('scytl-symmetric');
- var validator = require('./input-validator');
- var bitwise = require('scytl-bitwise');
- var codec = require('scytl-codec');
- module.exports = DigitalEnvelopeGenerator;
- /**
- * @class DigitalEnvelopeGenerator
- * @classdesc The digital envelope generator API. To instantiate this object,
- * use the method {@link DigitalEnvelopeService.newGenerator}.
- * @hideconstructor
- * @param {Object}
- * [options] An object containing optional arguments.
- * @param {Policy}
- * [options.policy=Default policy] The cryptographic policy to use.
- * @param {SymmetricCryptographyService}
- * [options.symmetricCryptographyService=Created internally] The
- * symmetric cryptography service to use.
- * @param {AsymmetricCryptographyService}
- * [options.asymmetricCryptographyService=Created internally] The
- * asymmetric cryptography service to use.
- */
- function DigitalEnvelopeGenerator(options) {
- options = options || {};
- var policy = cryptoPolicy.newInstance();
- if (options.policy) {
- policy.symmetric = options.policy.digitalEnvelope.symmetric;
- policy.asymmetric.cipher = options.policy.digitalEnvelope.asymmetric.cipher;
- }
- var symmetricService;
- if (options.symmetricCryptographyService) {
- symmetricService = options.symmetricCryptographyService;
- } else {
- symmetricService = symmetric.newService({policy: policy});
- }
- var asymmetricService;
- if (options.asymmetricCryptographyService) {
- asymmetricService = options.asymmetricCryptographyService;
- } else {
- asymmetricService = asymmetric.newService({policy: policy});
- }
- var secretKeyGenerator_ = symmetricService.newKeyGenerator();
- var symmetricCipher_ = symmetricService.newCipher();
- var macHandler_ = symmetricService.newMacHandler();
- var asymmetricEncrypter_ = asymmetricService.newEncrypter();
- var publicKeys_;
- /**
- * Initializes the Digital envelope generator with one or more public keys.
- *
- * @function init
- * @memberof DigitalEnvelopeGenerator
- * @param {...string}
- * arguments A comma separated list of the public keys, each in
- * PEM format.
- * @returns {DigitalEnvelopeGenerator} A reference to this object, to
- * facilitate method chaining.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.init = function() {
- publicKeys_ = Array.prototype.slice.call(arguments);
- validator.checkIsNonEmptyStringArray(
- publicKeys_,
- 'public keys (PEM encoded) to initialize digital envelope generator');
- return this;
- };
- /**
- * Generates a digital envelope, given the data to store in the envelope.
- * The envelope can be generated with one or more public keys, each of whose
- * corresponding private key can be used to open the envelope. Before using
- * this method, the generator must have been initialized with at least one
- * public key, via the method {@link DigitalEnvelopeGenerator.init}.
- *
- * @function generate
- * @memberof DigitalEnvelopeGenerator
- * @param {Uint8Array|
- * string} data The data to store in the digital envelope. Data
- * of type <code>string</code> will be UTF-8 encoded.
- * @returns {DigitalEnvelope} The generated digital envelope.
- * @throws {Error}
- * If the input data validation fails or the digital envelope
- * could not be generated.
- */
- this.generate = function(data) {
- if (typeof publicKeys_ === 'undefined') {
- throw new Error(
- 'Could not generate digital envelope; Envelope generator has not been initialized with any public key');
- }
- if (typeof data === 'string') {
- data = codec.utf8Encode(data);
- }
- validator.checkIsInstanceOf(
- data, Uint8Array, 'Uint8Array', 'Data to store in digital envelope');
- try {
- // Generate encryption secret key and use it to symmetrically encrypt
- // data.
- var encryptionSecretKey = secretKeyGenerator_.nextEncryptionKey();
- var encryptedData =
- symmetricCipher_.init(encryptionSecretKey).encrypt(data);
- // Generate MAC secret key and use it to generate MAC of symmetrically
- // encrypted data.
- var macSecretKey = secretKeyGenerator_.nextMacKey();
- var mac = macHandler_.init(macSecretKey).generate(encryptedData);
- // Construct bit-wise concatenation of encryption and MAC secret keys.
- var secretKeyPair =
- bitwise.concatenate(encryptionSecretKey, macSecretKey);
- // Generate list of asymmetric encryptions of the secret key
- // concatenation, each encryption created using a different one of the
- // public keys provided as input for the digital envelope generation.
- var encryptedSecretKeyPairs = [];
- for (var i = 0; i < publicKeys_.length; i++) {
- var publicKeyPem = publicKeys_[i];
- var encryptedSecretKeyPair =
- asymmetricEncrypter_.init(publicKeyPem).encrypt(secretKeyPair);
- encryptedSecretKeyPairs.push(
- new EncryptedSecretKeyPair(encryptedSecretKeyPair, publicKeyPem));
- }
- return new DigitalEnvelope(encryptedData, mac, encryptedSecretKeyPairs);
- } catch (error) {
- throw new Error('Digital envelope could not be generated. ' + error);
- }
- };
- }
|