2
0

digester.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. /* jshint node:true */
  9. 'use strict';
  10. var validator = require('./input-validator');
  11. var cryptoPolicy = require('scytl-cryptopolicy');
  12. var codec = require('scytl-codec');
  13. var forge = require('node-forge');
  14. module.exports = MessageDigester;
  15. /**
  16. * @class MessageDigester
  17. * @classdesc The message digester API. To instantiate this object, use the
  18. * method {@link MessageDigestService.newDigester}.
  19. * @hideconstructor
  20. * @param {Policy}
  21. * policy The cryptographic policy to use.
  22. */
  23. function MessageDigester(policy) {
  24. var digester_ = getDigester(policy.primitives.messageDigest.algorithm);
  25. digester_.start();
  26. var updated_ = false;
  27. /**
  28. * Generates a message digest from the provided data. If there were any
  29. * prior calls to the method <code>update</code>, then the provided data
  30. * will be bitwise appended to the data provided to those calls before
  31. * digesting. If no data is provided here the digest will only by generated
  32. * for the data provided to prior calls to the method <code>update</code>.
  33. * The message digester will be automatically reinitialized after this
  34. * method completes.
  35. *
  36. * @function digest
  37. * @memberof MessageDigester
  38. * @param {Uint8Array|string}
  39. * [data] The data from which to generate the message digest.
  40. * <b>NOTE:</b> Data of type <code>string</code> will be UTF-8
  41. * encoded.
  42. * @returns {Uint8Array} The generated message digest.
  43. * @throws {Error}
  44. * If no data was provided as input and the update method was
  45. * not previously called.
  46. */
  47. this.digest = function(data) {
  48. if (typeof data !== 'undefined') {
  49. if (typeof data === 'string') {
  50. data = codec.utf8Encode(data);
  51. }
  52. validator.checkIsInstanceOf(
  53. data, Uint8Array, 'Uint8Array', 'Data to digest');
  54. this.update(data);
  55. } else if (!updated_) {
  56. throw new Error(
  57. 'Attempt to generate message digest without either providing data as input or having made previous call to method \'update\'');
  58. }
  59. var bytesBinaryEncoded = digester_.digest().getBytes();
  60. // Reinitialize digester.
  61. digester_.start();
  62. updated_ = false;
  63. return codec.binaryDecode(bytesBinaryEncoded);
  64. };
  65. /**
  66. * Updates the message digester with the provided data. The data will be
  67. * internally bitwise appended to any data provided to previous calls to
  68. * this method, after the last call to the method <code>digest</code>.
  69. *
  70. * @function update
  71. * @memberof MessageDigester
  72. * @param {Uint8Array|string}
  73. * data The data with which to update the message digester.
  74. * <b>NOTE:</b> Data of type <code>string</code> will be UTF-8
  75. * encoded.
  76. * @returns {MessageDigester} A reference to this object, to facilitate
  77. * method chaining.
  78. * @throws {Error}
  79. * If the input data validation fails.
  80. */
  81. this.update = function(data) {
  82. if (typeof data === 'string') {
  83. data = codec.utf8Encode(data);
  84. }
  85. validator.checkIsInstanceOf(
  86. data, Uint8Array, 'Uint8Array', 'Data to update message digester');
  87. digester_.update(codec.binaryEncode(data));
  88. updated_ = true;
  89. return this;
  90. };
  91. function getDigester(algorithm) {
  92. if (algorithm ===
  93. cryptoPolicy.options.primitives.messageDigest.algorithm.SHA256) {
  94. return forge.md.sha256.create();
  95. } else if (
  96. algorithm ===
  97. cryptoPolicy.options.primitives.messageDigest.algorithm.SHA512_224) {
  98. return forge.md.sha512.sha224.create();
  99. } else {
  100. throw new Error(
  101. 'Could not create new message digester for unrecognized hash algorithm \'' +
  102. algorithm + '\'.');
  103. }
  104. }
  105. }