service.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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 DigitalEnvelope = require('./envelope');
  11. var DigitalEnvelopeGenerator = require('./generator');
  12. var DigitalEnvelopeOpener = require('./opener');
  13. var EncryptedSecretKeyPair = require('./encrypted-secret-keypair');
  14. var validator = require('./input-validator');
  15. var codec = require('scytl-codec');
  16. module.exports = DigitalEnvelopeService;
  17. /**
  18. * @class DigitalEnvelopeService
  19. * @classdesc The digital envelope service API. To instantiate this object, use
  20. * the method {@link newService}.
  21. * @hideconstructor
  22. * @param {Object}
  23. * [options] An object containing optional arguments.
  24. * @param {Policy}
  25. * [options.policy=Default policy] The cryptographic policy to use.
  26. * @param {SymmetricCryptographyService}
  27. * [options.symmetricCryptographyService=Created internally] The
  28. * symmetric cryptography service to use.
  29. * @param {AsymmetricCryptographyService}
  30. * [options.asymmetricCryptographyService=Created internally] The
  31. * asymmetric cryptography service to use.
  32. */
  33. function DigitalEnvelopeService(options) {
  34. /**
  35. * Creates a new DigitalEnvelopeGenerator object for generating digital
  36. * envelopes. It must be initialized with one or more public keys.
  37. *
  38. * @function newGenerator
  39. * @memberof DigitalEnvelopeService
  40. * @returns {DigitalEnvelopeGenerator} The new DigitalEnvelopeGenerator
  41. * object.
  42. */
  43. this.newGenerator = function() {
  44. return new DigitalEnvelopeGenerator(options);
  45. };
  46. /**
  47. * Creates a new DigitalEnvelopeOpener object for opening digital envelopes.
  48. * It must be initialized with a private key.
  49. *
  50. * @function newOpener
  51. * @memberof DigitalEnvelopeService
  52. * @returns {DigitalEnvelopeOpener} The new DigitalEnvelopeOpener object.
  53. */
  54. this.newOpener = function() {
  55. return new DigitalEnvelopeOpener(options);
  56. };
  57. }
  58. DigitalEnvelopeService.prototype = {
  59. /**
  60. * Creates a new DigitalEnvelope object from a provided digital envelope or
  61. * its components.
  62. *
  63. * @function newEnvelope
  64. * @memberof DigitalEnvelopeService
  65. * @param {Uint8Array}
  66. * encryptedDataOrJson The symmetrically encrypted data <b>OR</b>
  67. * a JSON string representation of a DigitalEnvelope object,
  68. * compatible with its <code>toJson</code> method. For the
  69. * latter case, any additional input arguments will be ignored.
  70. * @param {Uint8Array}
  71. * mac The MAC of the symmetrically encrypted data.
  72. * @param {EncryptedSecretKeyPair[]}
  73. * encryptedSecretKeyPairs The array of asymmetric encryptions of
  74. * the concatenation of the encryption secret key and MAC secret
  75. * key used to generate and open the digital envelope, each
  76. * asymmetric encryption having been generated using a different
  77. * one of the public keys used to initialize digital envelope
  78. * generator.
  79. * @returns {DigitalEnvelope} The new DigitalEnvelope object.
  80. * @throws {Error}
  81. * If the input data validation fails.
  82. */
  83. newEnvelope: function(encryptedDataOrJson, mac, encryptedSecretKeyPairs) {
  84. if (typeof encryptedDataOrJson !== 'string') {
  85. validator.checkIsInstanceOf(
  86. encryptedDataOrJson, Uint8Array, 'Uint8Array',
  87. 'Symmetrically encrypted data for new DigitalEnvelope object');
  88. validator.checkIsInstanceOf(
  89. mac, Uint8Array, 'Uint8Array', 'MAC for new DigitalEnvelope object');
  90. checkEncryptedSecretKeyPairs(
  91. encryptedSecretKeyPairs,
  92. 'Encrypted secret key pairs for new DigitalEnvelope object');
  93. return new DigitalEnvelope(
  94. encryptedDataOrJson, mac, encryptedSecretKeyPairs);
  95. } else {
  96. return jsonToEnvelope(encryptedDataOrJson);
  97. }
  98. }
  99. };
  100. function checkEncryptedSecretKeyPairs(keyPairs, label) {
  101. validator.checkIsNonEmptyArray(keyPairs, label);
  102. for (var i = 0; i < keyPairs.length; i++) {
  103. validator.checkIsObjectWithProperties(
  104. keyPairs[i], 'element ' + i + ' of ' + label);
  105. }
  106. }
  107. function jsonToEnvelope(json) {
  108. validator.checkIsJsonString(
  109. json, 'JSON string to deserialize to DigitalEnvelope object');
  110. var parsed = JSON.parse(json).digitalEnvelope;
  111. var encryptedData = codec.base64Decode(parsed.encryptedDataBase64);
  112. var mac = codec.base64Decode(parsed.macBase64);
  113. var encryptedSecretKeyPairsB64 = parsed.encryptedSecretKeyConcatsBase64;
  114. var publicKeysPem = parsed.publicKeysPem;
  115. var encryptedSecretKeyPairs = [];
  116. for (var i = 0; i < encryptedSecretKeyPairsB64.length; i++) {
  117. encryptedSecretKeyPairs.push(new EncryptedSecretKeyPair(
  118. codec.base64Decode(encryptedSecretKeyPairsB64[i]), publicKeysPem[i]));
  119. }
  120. return new DigitalEnvelope(encryptedData, mac, encryptedSecretKeyPairs);
  121. }