primitives.messagedigest.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright 2018 Scytl Secure Electronic Voting SA
  3. *
  4. * All rights reserved
  5. *
  6. * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
  7. */
  8. cryptolib.modules.primitives = cryptolib.modules.primitives || {};
  9. /**
  10. * @namespace primitives/messagedigest
  11. */
  12. cryptolib.modules.primitives.messagedigest = function(box) {
  13. 'use strict';
  14. box.primitives = box.primitives || {};
  15. box.primitives.messagedigest = box.primitives.messagedigest || {};
  16. /**
  17. * A module that holds message digest functionalities.
  18. * @exports primitives/messagedigest
  19. */
  20. box.primitives.messagedigest.factory =
  21. box.primitives.messagedigest.factory || {};
  22. var policies = {
  23. messagedigest: {
  24. algorithm: box.policies.primitives.messagedigest.algorithm,
  25. provider: box.policies.primitives.messagedigest.provider
  26. }
  27. };
  28. var converters, exceptions;
  29. cryptolib('commons', function(box) {
  30. converters = new box.commons.utils.Converters();
  31. exceptions = box.commons.exceptions;
  32. });
  33. /**
  34. * A factory class for creating a message digest generator and verifier.
  35. * @class
  36. */
  37. box.primitives.messagedigest.factory.MessageDigestFactory = function() {};
  38. box.primitives.messagedigest.factory.MessageDigestFactory.prototype = {
  39. /**
  40. * Gets a message dister object.
  41. * @function
  42. * @returns {primitives/messagedigest.CryptoForgeMessageDigest}
  43. */
  44. getCryptoMessageDigest: function() {
  45. try {
  46. if (policies.messagedigest.provider ===
  47. Config.primitives.messagedigest.provider.FORGE) {
  48. return this.getCryptoForgeMessageDigest();
  49. } else {
  50. throw new exceptions.CryptoLibException(
  51. 'No suitable provider was provided.');
  52. }
  53. } catch (error) {
  54. throw new exceptions.CryptoLibException(
  55. 'A CryptoSymmetricCipher could not be obtained.', error);
  56. }
  57. },
  58. getCryptoForgeMessageDigest: function() {
  59. return new CryptoForgeMessageDigest();
  60. }
  61. };
  62. /**
  63. * Defines a message digest hash function.
  64. * @class
  65. * @memberof primitives/messagedigest
  66. */
  67. function CryptoForgeMessageDigest() {
  68. this.digester = null;
  69. try {
  70. if (policies.messagedigest.algorithm ===
  71. Config.primitives.messagedigest.algorithm.SHA256) {
  72. this.digester = forge.md.sha256.create();
  73. } else if (
  74. policies.messagedigest.algorithm ===
  75. Config.primitives.messagedigest.algorithm.SHA512_224) {
  76. this.digester = forge.md.sha512.sha224.create();
  77. } else {
  78. var errorMessage = 'Message digester type \'' +
  79. policies.messagedigest.algorithm +
  80. '\' not recognized by CryptoForgeMessageDigest.';
  81. throw new exceptions.CryptoLibException(errorMessage);
  82. }
  83. } catch (error) {
  84. throw new exceptions.CryptoLibException(
  85. 'CryptoForgeMessageDigest could not be created.', error);
  86. }
  87. }
  88. CryptoForgeMessageDigest.prototype = {
  89. /**
  90. * Initializes the message digest generator.
  91. * @function
  92. */
  93. start: function() {
  94. try {
  95. this.digester.start();
  96. } catch (error) {
  97. throw new exceptions.CryptoLibException(
  98. 'Message digest could not be initialized.', error);
  99. }
  100. },
  101. /**
  102. * Updates the message digest generator.
  103. * @function
  104. * @param {Array} arrayDataBase64
  105. * data to compute the hash, as an array of string in Base64
  106. * encoded format.
  107. */
  108. update: function(arrayDataBase64) {
  109. try {
  110. if (!arrayDataBase64 || arrayDataBase64.length < 1) {
  111. throw new exceptions.CryptoLibException(
  112. 'The array of data in Base64 should contain at least one element.');
  113. }
  114. for (var i = 0; i < arrayDataBase64.length; i++) {
  115. this.digester.update(converters.base64Decode(arrayDataBase64[i]));
  116. }
  117. } catch (error) {
  118. throw new exceptions.CryptoLibException(
  119. 'Message digest could not be updated.', error);
  120. }
  121. },
  122. /**
  123. * Generates the message digest for the updated data.
  124. * @function
  125. * @returns {string} Message digest, as string in Base64 encoded format.
  126. */
  127. digest: function() {
  128. try {
  129. var messageDigest = this.digester.digest();
  130. var rawOutput = messageDigest.getBytes();
  131. var encodedOutput = converters.base64Encode(rawOutput);
  132. return encodedOutput;
  133. } catch (error) {
  134. throw new exceptions.CryptoLibException(
  135. 'Message digest could not be generated.', error);
  136. }
  137. }
  138. };
  139. };