/* * 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 */ /** * @global * @description This object describes the configuration scheme for this * cryptographic library. The following modules are considered: * * @readonly * @property {object} asymmetric.keypair - Policies for generating keypairs. * @property {object} asymmetric.keypair.encryption - Policies for generating * encryption keypairs. * @property {object} asymmetric.keypair.encryption.algorithm - Algorithm. * @property {string} asymmetric.keypair.encryption.algorithm.RSA - RSA * algorithm. * @property {object} asymmetric.keypair.encryption.provider - Provider. * @property {string} asymmetric.keypair.encryption.provider.FORGE - Forge * provider. * @property {object} asymmetric.keypair.encryption.keyLength - Key length. * @property {number} asymmetric.keypair.encryption.keyLength.KL_2048 - 2048 * bits. * @property {number} asymmetric.keypair.encryption.keyLength.KL_3072 - 3072 * bits. * @property {number} asymmetric.keypair.encryption.keyLength.KL_4096 - 4096 * bits. * @property {object} asymmetric.keypair.encryption.publicExponent - Public * exponent for generating encryption keypairs. * @property {number} asymmetric.keypair.encryption.publicExponent.F4 - 65537. * * @property {object} asymmetric.signer - Policies for signing and verifying * data. * @property {object} asymmetric.signer.algorithm - Algorithm. * @property {string} asymmetric.signer.algorithm.RSA - RSA algorithm. * @property {object} asymmetric.signer.provider - Provider. * @property {string} asymmetric.signer.provider.FORGE - Forge provider. * @property {object} asymmetric.signer.hash - Hash algorithm. * @property {string} asymmetric.signer.hash.SHA256 - SHA-256 algorithm. * @property {object} asymmetric.signer.padding - Padding scheme. * @property {object} asymmetric.signer.padding.PSS - PSS padding scheme. * @property {string} asymmetric.signer.padding.PSS.name - PSS. * @property {object} asymmetric.signer.padding.PSS.hash - Hash for the PSS * padding scheme. * @property {string} asymmetric.signer.padding.PSS.hash.SHA256 - SHA-256 * algorithm. * @property {object} asymmetric.signer.padding.PSS.mask - Mask generating * function for the PSS padding scheme. * @property {object} asymmetric.signer.padding.PSS.mask.MGF1 - MGF1 for the PSS * padding scheme. * @property {string} asymmetric.signer.padding.PSS.mask.MGF1.name - MGF1. * @property {object} asymmetric.signer.padding.PSS.mask.MGF1.hash - Hash * algorithm for the MGF1 for the PSS padding scheme. * @property {string} asymmetric.signer.padding.PSS.mask.MGF1.hash.SHA256 - * SHA-256 algorithm. * @property {object} asymmetric.signer.padding.PSS.saltLengthBytes - Salt * length for the PSS padding scheme. * @property {number} asymmetric.signer.padding.PSS.saltLengthBytes.SL_32 - 32 * bytes. * @property {object} asymmetric.signer.publicExponent - Public exponent. * @property {number} asymmetric.signer.publicExponent.F4 - 65537. * @property {object} primitives.securerandom - Policies for generating * securerandom. * @property {object} primitives.securerandom.provider - Provider. * @property {string} primitives.securerandom.provider.SCYTL - Scytl provider. * @property {object} primitives.messagedigest - Policies for generating message * digests. * @property {object} primitives.messagedigest.algorithm - Algorithm. * @property {string} primitives.messagedigest.algorithm.SHA256 - SHA-256 * algorithm. * @property {object} primitives.messagedigest.provider - Provider. * @property {string} primitives.messagedigest.provider.FORGE - Forge provider. * @property {object} symmetric.secretkey - Policies to generate secret keys. * @property {number} symmetric.secretkey.length - 128 bits. * @property {object} symmetric.cipher - Policies to encrypt and decrypt * symmetrically. * @property {object} symmetric.cipher.algorithm - Algorithm. * @property {object} symmetric.cipher.algorithm.AES128_GCM - AES128-GCM * algorithm. * @property {string} symmetric.cipher.algorithm.AES128_GCM.name - AES128-GCM. * @property {number} symmetric.cipher.algorithm.AES128_GCM.keyLengthBytes - 16 * bytes. * @property {number} symmetric.cipher.algorithm.AES128_GCM.tagLengthBytes - 16 * bytes. * @property {object} symmetric.cipher.provider - Provider. * @property {object} symmetric.cipher.provider.FORGE - Forge provider. * @property {object} symmetric.cipher.initializationVectorLengthBytes - * Initialization vector length. * @property {number} symmetric.cipher.initializationVectorLengthBytes.IV_12 - * 12 bytes. */ var Config = { homomorphic: {cipher: {secureRandom: {provider: {SCYTL: 'Scytl'}}}}, asymmetric: { keypair: { encryption: { algorithm: {RSA: 'RSA'}, provider: {FORGE: 'Forge'}, keyLength: {KL_2048: 2048, KL_3072: 3072, KL_4096: 4096}, publicExponent: {F4: 65537} }, secureRandom: {provider: {SCYTL: 'Scytl'}} }, signer: { algorithm: {RSA: 'RSA'}, provider: {FORGE: 'Forge'}, hash: {SHA256: 'SHA256'}, padding: { PSS: { name: 'PSS', hash: {SHA256: 'SHA256'}, mask: {MGF1: {name: 'MGF1', hash: {SHA256: 'SHA256'}}}, saltLengthBytes: {SL_32: 32} } }, publicExponent: {F4: 65537}, secureRandom: {provider: {SCYTL: 'Scytl'}} }, cipher: { algorithm: { RSA_OAEP: { name: 'RSA-OAEP', hash: 'SHA256', mask: {MGF1: {name: 'MGF1', hash: 'SHA1'}} }, RSA_KEM: { name: 'RSA-KEM', secretKeyLengthBytes: {KL_16: 16, KL_24: 24, KL_32: 32}, ivLengthBytes: {IVL_12: 12, IVL_16: 16, IVL_32: 32, IVL_64: 64}, tagLengthBytes: {TL_12: 12, TL_16: 16, TL_32: 32, TL_64: 64}, deriver: { name: {KDF1: 'kdf1', KDF2: 'kdf2', MGF1: 'mgf1'}, messagedigest: {algorithm: {SHA256: 'SHA256'}} }, cipher: {AESGCM: 'AES-GCM'} } }, provider: {FORGE: 'Forge'}, secureRandom: {provider: {SCYTL: 'Scytl'}} } }, primitives: { secureRandom: {provider: {SCYTL: 'Scytl'}}, messagedigest: { algorithm: {SHA256: 'SHA256', SHA512_224: 'SHA512/224'}, provider: {FORGE: 'Forge'} }, derivation: { pbkdf: { provider: {FORGE: 'Forge'}, hash: {SHA256: 'SHA256'}, saltLengthBytes: {SL_20: 20, SL_32: 32}, keyLengthBytes: {KL_16: 16, KL_32: 32}, iterations: { I_1: 1, I_8000: 8000, I_16000: 16000, I_32000: 32000, I_64000: 64000 } } } }, stores: {}, symmetric: { secretkey: { encryption: {lengthBytes: {SK_16: 16}}, mac: {lengthBytes: {SK_32: 32}}, secureRandom: {provider: {SCYTL: 'Scytl'}} }, cipher: { provider: {FORGE: 'Forge'}, algorithm: { AES128_GCM: {name: 'AES-GCM', keyLengthBytes: 16, tagLengthBytes: 16} }, initializationVectorLengthBytes: {IV_12: 12}, secureRandom: {provider: {SCYTL: 'Scytl'}} }, mac: {hash: {SHA256: 'SHA256'}, provider: {FORGE: 'Forge'}} }, proofs: { secureRandom: {provider: {SCYTL: 'Scytl'}}, messagedigest: { algorithm: {SHA256: 'SHA256', SHA512_224: 'SHA512/224'}, provider: {FORGE: 'Forge'} }, charset: {UTF8: 'UTF-8'} }, digitalenvelope: { symmetric: { secretkey: { encryption: {lengthBytes: {SK_16: 16}}, mac: {lengthBytes: {SK_32: 32}}, secureRandom: {provider: {SCYTL: 'Scytl'}} }, cipher: { provider: {FORGE: 'Forge'}, algorithm: { AES128_GCM: {name: 'AES-GCM', keyLengthBytes: 16, tagLengthBytes: 16} }, initializationVectorLengthBytes: {IV_12: 12}, secureRandom: {provider: {SCYTL: 'Scytl'}} }, mac: {hash: {SHA256: 'SHA256'}, provider: {FORGE: 'Forge'}} }, asymmetric: { cipher: { algorithm: { RSA_OAEP: { name: 'RSA-OAEP', hash: 'SHA256', mask: {MGF1: {name: 'MGF1', hash: 'SHA1'}} }, RSA_KEM: { name: 'RSA-KEM', secretKeyLengthBytes: {KL_16: 16, KL_24: 24, KL_32: 32}, ivLengthBytes: {IVL_12: 12, IVL_16: 16, IVL_32: 32, IVL_64: 64}, tagLengthBytes: {TL_12: 12, TL_16: 16, TL_32: 32, TL_64: 64}, deriver: { name: {KDF1: 'kdf1', KDF2: 'kdf2', MGF1: 'mgf1'}, messagedigest: {algorithm: {SHA256: 'SHA256'}} }, cipher: {AESGCM: 'AES-GCM'} } }, provider: {FORGE: 'Forge'}, secureRandom: {provider: {SCYTL: 'Scytl'}} } } } }; if (Object.freeze) { /** * Freezes an object and all its contents. * @param {Object} target the object to freeze. */ var recursiveFreeze = function(target) { 'use strict'; // Get all property names var propNames = Object.getOwnPropertyNames(target); // Freeze the object's properties. propNames.forEach(function(name) { var property = target[name]; // Freeze the properties' properties. if (typeof property === 'object' && property !== null) { recursiveFreeze(property); } }); // Freeze the object itself. return Object.freeze(target); }; // Lock down the configuration recursiveFreeze(Config); } var cryptolibPolicies; /** * @global * @function cryptolib * * @description Core of the library, this module is used to sandbox the * requested modules. * * @example // how to load all modules cryptolib('*', function(box) { // any * module can be used from here. // * box.examplemodule.service.getExample(); }); * * * @param modules * {...modules} modules to be loaded. '*' or none to load all the * modules. * @param function * {cryptolibSandbox} a closure for the cryptolib object. * @tutorial workers */ function cryptolib() { 'use strict'; /* Class to keep the references to polices and prng. */ function Cryptolib(modules, callback) { function getAllModules(parent) { var modules = []; for (var module in parent) { if (parent.hasOwnProperty(module)) { modules.push(module); } } return modules; } function loadModules(box, modules, parentModule) { if (!modules || modules.toString() === '*'.toString()) { modules = getAllModules(parentModule); } for (var i = 0; i < modules.length; i += 1) { var firstDotIndex = modules[i].indexOf('.'); if (firstDotIndex > -1) { var subModule = modules[i].substr(firstDotIndex + 1); var root = modules[i].substr(0, firstDotIndex); loadModules(box, [subModule], parentModule[root]); } else if (typeof parentModule[modules[i]] === 'function') { parentModule[modules[i]](box); } else if (typeof parentModule[modules[i]] === 'object') { loadModules(box, '*', parentModule[modules[i]]); } } } this.policies = callback.policies || cryptolibPolicies; cryptolibPolicies = cryptolibPolicies || this.policies; this.prng = callback.prng || cryptoPRNG.getPRNG(); loadModules(this, modules, cryptolib.modules); callback(this); } Cryptolib.prototype = { getKeys: function(obj) { var keys = []; for (var key in obj) { if (typeof key !== 'undefined') { keys.push(key); } } return keys; }, getModuleNames: function() { var moduleNames = ''; for (var module in cryptolib.modules) { if (typeof module !== 'undefined') { if (moduleNames.length > 0) { moduleNames += ', '; } moduleNames += module; } } return '[' + moduleNames + ']'; }, forge: forge, // redefines forge global variable sjcl: sjcl, // redefines sjcl global variable // Constants. /** @constant */ NUMBER_OF_BITS_PER_BYTE: 8, /** @constant */ MAXIMUM_LENGTH_TO_GENERATE_DATA: 512, /** @constant */ BASE_2_RADIX: 2, /** @constant */ BASE_10_RADIX: 10, /** @constant */ BASE_16_RADIX: 16, /** @constant */ EPOCH_TIME_LENGTH: 10, /** @constant */ RSA_LINE_LENGTH: 64, /** @constant */ SHA_256_LENGTH: 32, /** @constant */ HMAC_SHA256_KEY_LENGTH: 32, /** @constant */ AES_KEY_LENGTH: 16, /** @constant */ AES_CBC_IV_LENGTH: 16, /** @constant */ DES3_KEY_LENGTH: 24, /** @constant */ DES3_CBC_IV_LENGTH: 8, EQUALS: ' = ', NEWLINE: '\n', CRYPTO_SPEC_DELIM: '/', /** @constant */ SHA_256: 'SHA256', /** @constant */ RSA_ECB_PKCS1PADDING: 'RSA/ECB/PKCS1PADDING', /** @constant */ RSA_ECB_OAEP_WITH_SHA256_AND_MGF1PADDING: 'RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING', /** @constant */ FORGE_RSA_OAEP: 'RSA-OAEP', /** @constant */ FORGE_RSAES_PKCS1_V1_5: 'RSAES-PKCS1-V1_5', /** @constant */ MINIMUM_PRIME_CERTAINTY_LEVEL: 80, /** @constant */ SHORT_EXPONENT_BIT_LENGTH: 256, /** @constant */ EXPONENTIATION_PROOF_AUXILIARY_DATA: 'ExponentiationProof', /** @constant */ PLAINTEXT_PROOF_AUXILIARY_DATA: 'PlaintextProof', /** @constant */ SIMPLE_PLAINTEXT_EQUALITY_PROOF_AUXILIARY_DATA: 'SimplePlaintextEqualityProof', /** @constant */ PLAINTEXT_EQUALITY_PROOF_AUXILIARY_DATA: 'PlaintextEqualityProof', /** @constant */ PLAINTEXT_EXPONENT_EQUALITY_PROOF_AUXILIARY_DATA: 'PlaintextExponentEqualityProof' }; var args = Array.prototype.slice.call(arguments); var callback = args.pop(); var modules = (args[0] && typeof args[0] === 'string') ? args : args[0]; return new Cryptolib(modules, callback); } cryptolib.modules = {};