/*
* 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 DigitalEnvelopeGenerator = require('./generator');
var DigitalEnvelopeOpener = require('./opener');
var EncryptedSecretKeyPair = require('./encrypted-secret-keypair');
var validator = require('./input-validator');
var codec = require('scytl-codec');
module.exports = DigitalEnvelopeService;
/**
* @class DigitalEnvelopeService
* @classdesc The digital envelope 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 {SymmetricCryptographyService}
* [options.symmetricCryptographyService=Created internally] The
* symmetric cryptography service to use.
* @param {AsymmetricCryptographyService}
* [options.asymmetricCryptographyService=Created internally] The
* asymmetric cryptography service to use.
*/
function DigitalEnvelopeService(options) {
/**
* Creates a new DigitalEnvelopeGenerator object for generating digital
* envelopes. It must be initialized with one or more public keys.
*
* @function newGenerator
* @memberof DigitalEnvelopeService
* @returns {DigitalEnvelopeGenerator} The new DigitalEnvelopeGenerator
* object.
*/
this.newGenerator = function() {
return new DigitalEnvelopeGenerator(options);
};
/**
* Creates a new DigitalEnvelopeOpener object for opening digital envelopes.
* It must be initialized with a private key.
*
* @function newOpener
* @memberof DigitalEnvelopeService
* @returns {DigitalEnvelopeOpener} The new DigitalEnvelopeOpener object.
*/
this.newOpener = function() {
return new DigitalEnvelopeOpener(options);
};
}
DigitalEnvelopeService.prototype = {
/**
* Creates a new DigitalEnvelope object from a provided digital envelope or
* its components.
*
* @function newEnvelope
* @memberof DigitalEnvelopeService
* @param {Uint8Array}
* encryptedDataOrJson The symmetrically encrypted data OR
* a JSON string representation of a DigitalEnvelope object,
* compatible with its toJson
method. For the
* latter case, any additional input arguments will be ignored.
* @param {Uint8Array}
* mac The MAC of the symmetrically encrypted data.
* @param {EncryptedSecretKeyPair[]}
* encryptedSecretKeyPairs The array of asymmetric encryptions of
* the concatenation of the encryption secret key and MAC secret
* key used to generate and open the digital envelope, each
* asymmetric encryption having been generated using a different
* one of the public keys used to initialize digital envelope
* generator.
* @returns {DigitalEnvelope} The new DigitalEnvelope object.
* @throws {Error}
* If the input data validation fails.
*/
newEnvelope: function(encryptedDataOrJson, mac, encryptedSecretKeyPairs) {
if (typeof encryptedDataOrJson !== 'string') {
validator.checkIsInstanceOf(
encryptedDataOrJson, Uint8Array, 'Uint8Array',
'Symmetrically encrypted data for new DigitalEnvelope object');
validator.checkIsInstanceOf(
mac, Uint8Array, 'Uint8Array', 'MAC for new DigitalEnvelope object');
checkEncryptedSecretKeyPairs(
encryptedSecretKeyPairs,
'Encrypted secret key pairs for new DigitalEnvelope object');
return new DigitalEnvelope(
encryptedDataOrJson, mac, encryptedSecretKeyPairs);
} else {
return jsonToEnvelope(encryptedDataOrJson);
}
}
};
function checkEncryptedSecretKeyPairs(keyPairs, label) {
validator.checkIsNonEmptyArray(keyPairs, label);
for (var i = 0; i < keyPairs.length; i++) {
validator.checkIsObjectWithProperties(
keyPairs[i], 'element ' + i + ' of ' + label);
}
}
function jsonToEnvelope(json) {
validator.checkIsJsonString(
json, 'JSON string to deserialize to DigitalEnvelope object');
var parsed = JSON.parse(json).digitalEnvelope;
var encryptedData = codec.base64Decode(parsed.encryptedDataBase64);
var mac = codec.base64Decode(parsed.macBase64);
var encryptedSecretKeyPairsB64 = parsed.encryptedSecretKeyConcatsBase64;
var publicKeysPem = parsed.publicKeysPem;
var encryptedSecretKeyPairs = [];
for (var i = 0; i < encryptedSecretKeyPairsB64.length; i++) {
encryptedSecretKeyPairs.push(new EncryptedSecretKeyPair(
codec.base64Decode(encryptedSecretKeyPairsB64[i]), publicKeysPem[i]));
}
return new DigitalEnvelope(encryptedData, mac, encryptedSecretKeyPairs);
}