123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /*
- * 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
- */
- cryptolib.modules.primitives = cryptolib.modules.primitives || {};
- /** @namespace primitives/derivation */
- cryptolib.modules.primitives.derivation = function(box) {
- 'use strict';
- box.primitives = box.primitives || {};
- box.primitives.derivation = {};
- /**
- * A module that holds derivation functionalities.
- *
- * @exports primitives/derivation
- */
- box.primitives.derivation.factory = {};
- var policies = {
- pbkdf: {
- provider: box.policies.primitives.derivation.pbkdf.provider,
- hash: box.policies.primitives.derivation.pbkdf.hash,
- saltLengthBytes: box.policies.primitives.derivation.pbkdf.saltLengthBytes,
- keyLengthBytes: box.policies.primitives.derivation.pbkdf.keyLengthBytes,
- iterations: box.policies.primitives.derivation.pbkdf.iterations
- }
- };
- var exceptions, converters;
- cryptolib('rnd', 'commons', function(box) {
- exceptions = box.commons.exceptions;
- converters = new box.commons.utils.Converters();
- });
- /**
- * A factory class for generating {@link CryptoForgePBKDFSecretKeyGenerator}
- * objects.
- *
- * @class
- */
- box.primitives.derivation.factory.SecretKeyGeneratorFactory = function() {
- };
- box.primitives.derivation.factory.SecretKeyGeneratorFactory.prototype = {
- /**
- * Creates a generator for deriving passwords.
- *
- * @function
- * @returns {primitives/derivation.CryptoForgePBKDFSecretKeyGenerator} a
- * {@link primitives/derivation.CryptoForgePBKDFSecretKeyGenerator}
- * object.
- */
- createPBKDF: function() {
- var provider = policies.pbkdf.provider;
- try {
- if (provider === Config.primitives.derivation.pbkdf.provider.FORGE) {
- return new CryptoForgePBKDFSecretKeyGenerator();
- } else {
- throw new exceptions.CryptoLibException(
- 'The specified provider ' + provider + ' is not supported.');
- }
- } catch (error) {
- throw new exceptions.CryptoLibException(
- 'A CryptoPBKDFSecretKeyGenerator object could not be created.',
- error);
- }
- }
- };
- /**
- *
- * @class
- * @memberof primitives/derivation
- */
- function CryptoForgePBKDFSecretKeyGenerator() {
- validateHash(policies.pbkdf.hash);
- validateKeyLengthBytes(policies.pbkdf.keyLengthBytes);
- validateSaltLengthBytes(policies.pbkdf.saltLengthBytes);
- validateIterations(policies.pbkdf.iterations);
- this.keyLengthBytes = policies.pbkdf.keyLengthBytes;
- }
- CryptoForgePBKDFSecretKeyGenerator.prototype = {
- /**
- * @param {string}
- * password the password, as a string of bytes in Base64
- * encoded format.
- * @param {string}
- * salt the salt, as a string of bytes in Base64 encoded
- * format. Note that the salt length should coincide with the
- * one required by the hash algorithm.
- *
- * @return {string} the derived key, as a string of bytes in Base64
- * encoded format.
- */
- generateSecret: function(passwordB64, saltB64) {
- var password = converters.base64Decode(passwordB64);
- var salt = converters.base64Decode(saltB64);
- if (salt.length < policies.pbkdf.saltLengthBytes) {
- throw new exceptions.CryptoLibException(
- 'The salt byte length ' + salt.length +
- ' is less than the minimum allowed salt length ' +
- policies.pbkdf.saltLengthBytes +
- ' set by the cryptographic policy.');
- }
- var derivedKey = sjcl.misc.pbkdf2(
- password, sjcl.codec.base64.toBits(saltB64),
- policies.pbkdf.iterations, this.keyLengthBytes * 8,
- hashCallback(policies.pbkdf.hash));
- return sjcl.codec.base64.fromBits(derivedKey);
- }
- };
- function hashCallback(algorithm) {
- if (algorithm === Config.primitives.derivation.pbkdf.hash.SHA256) {
- return null;
- } else {
- throw new exceptions.CryptoLibException(
- 'Hash algorithm \'' + algorithm + '\' is unsupported');
- }
- }
- function validateHash(hash) {
- var supportedHashAlgorithms =
- [Config.primitives.derivation.pbkdf.hash.SHA256];
- if (supportedHashAlgorithms.indexOf(hash) < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified hash algorithm ' + hash +
- ' is not one of the supported options: ' + supportedHashAlgorithms);
- }
- }
- function validateSaltLengthBytes(saltLengthBytes) {
- var supportedSaltLengthBytes = [
- Config.primitives.derivation.pbkdf.saltLengthBytes.SL_20,
- Config.primitives.derivation.pbkdf.saltLengthBytes.SL_32
- ];
- if (typeof saltLengthBytes !== 'number' || saltLengthBytes % 1 !== 0 ||
- saltLengthBytes < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified salt byte length ' + saltLengthBytes +
- ' is not a positive integer.');
- }
- if (supportedSaltLengthBytes.indexOf(saltLengthBytes) < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified salt byte length ' + saltLengthBytes +
- ' is not one of the supported options: ' + supportedSaltLengthBytes);
- }
- }
- function validateKeyLengthBytes(keyLengthBytes) {
- var supportedKeyLengthBytes = [
- Config.primitives.derivation.pbkdf.keyLengthBytes.KL_16,
- Config.primitives.derivation.pbkdf.keyLengthBytes.KL_32
- ];
- if (typeof keyLengthBytes !== 'number' || keyLengthBytes % 1 !== 0 ||
- keyLengthBytes < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified key byte length ' + keyLengthBytes +
- ' is not a positive number.');
- }
- if (supportedKeyLengthBytes.indexOf(keyLengthBytes) < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified key byte length ' + keyLengthBytes +
- ' is not one of the supported options: ' + supportedKeyLengthBytes);
- }
- }
- function validateIterations(iterations) {
- var supportedIterations = [
- Config.primitives.derivation.pbkdf.iterations.I_1,
- Config.primitives.derivation.pbkdf.iterations.I_8000,
- Config.primitives.derivation.pbkdf.iterations.I_16000,
- Config.primitives.derivation.pbkdf.iterations.I_32000,
- Config.primitives.derivation.pbkdf.iterations.I_64000
- ];
- if (typeof iterations !== 'number' || iterations % 1 !== 0 ||
- iterations < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified number of iterations ' + iterations +
- ' is not a positive integer.');
- }
- if (supportedIterations.indexOf(iterations) < 0) {
- throw new exceptions.CryptoLibException(
- 'The specified number of iterations ' + iterations +
- ' is not one of the supported options: ' + supportedIterations);
- }
- }
- };
|