/* * 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/messagedigest */ cryptolib.modules.primitives.messagedigest = function(box) { 'use strict'; box.primitives = box.primitives || {}; box.primitives.messagedigest = box.primitives.messagedigest || {}; /** * A module that holds message digest functionalities. * @exports primitives/messagedigest */ box.primitives.messagedigest.factory = box.primitives.messagedigest.factory || {}; var policies = { messagedigest: { algorithm: box.policies.primitives.messagedigest.algorithm, provider: box.policies.primitives.messagedigest.provider } }; var converters, exceptions; cryptolib('commons', function(box) { converters = new box.commons.utils.Converters(); exceptions = box.commons.exceptions; }); /** * A factory class for creating a message digest generator and verifier. * @class */ box.primitives.messagedigest.factory.MessageDigestFactory = function() {}; box.primitives.messagedigest.factory.MessageDigestFactory.prototype = { /** * Gets a message dister object. * @function * @returns {primitives/messagedigest.CryptoForgeMessageDigest} */ getCryptoMessageDigest: function() { try { if (policies.messagedigest.provider === Config.primitives.messagedigest.provider.FORGE) { return this.getCryptoForgeMessageDigest(); } else { throw new exceptions.CryptoLibException( 'No suitable provider was provided.'); } } catch (error) { throw new exceptions.CryptoLibException( 'A CryptoSymmetricCipher could not be obtained.', error); } }, getCryptoForgeMessageDigest: function() { return new CryptoForgeMessageDigest(); } }; /** * Defines a message digest hash function. * @class * @memberof primitives/messagedigest */ function CryptoForgeMessageDigest() { this.digester = null; try { if (policies.messagedigest.algorithm === Config.primitives.messagedigest.algorithm.SHA256) { this.digester = forge.md.sha256.create(); } else if ( policies.messagedigest.algorithm === Config.primitives.messagedigest.algorithm.SHA512_224) { this.digester = forge.md.sha512.sha224.create(); } else { var errorMessage = 'Message digester type \'' + policies.messagedigest.algorithm + '\' not recognized by CryptoForgeMessageDigest.'; throw new exceptions.CryptoLibException(errorMessage); } } catch (error) { throw new exceptions.CryptoLibException( 'CryptoForgeMessageDigest could not be created.', error); } } CryptoForgeMessageDigest.prototype = { /** * Initializes the message digest generator. * @function */ start: function() { try { this.digester.start(); } catch (error) { throw new exceptions.CryptoLibException( 'Message digest could not be initialized.', error); } }, /** * Updates the message digest generator. * @function * @param {Array} arrayDataBase64 * data to compute the hash, as an array of string in Base64 * encoded format. */ update: function(arrayDataBase64) { try { if (!arrayDataBase64 || arrayDataBase64.length < 1) { throw new exceptions.CryptoLibException( 'The array of data in Base64 should contain at least one element.'); } for (var i = 0; i < arrayDataBase64.length; i++) { this.digester.update(converters.base64Decode(arrayDataBase64[i])); } } catch (error) { throw new exceptions.CryptoLibException( 'Message digest could not be updated.', error); } }, /** * Generates the message digest for the updated data. * @function * @returns {string} Message digest, as string in Base64 encoded format. */ digest: function() { try { var messageDigest = this.digester.digest(); var rawOutput = messageDigest.getBytes(); var encodedOutput = converters.base64Encode(rawOutput); return encodedOutput; } catch (error) { throw new exceptions.CryptoLibException( 'Message digest could not be generated.', error); } } }; };