2
0

service.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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 RsaPublicKey = require('./rsa-public-key');
  11. var RsaPrivateKey = require('./rsa-private-key');
  12. var KeyPair = require('./keypair');
  13. var KeyPairGenerator = require('./keypair-generator');
  14. var Signer = require('./signer');
  15. var SignatureVerifier = require('./signature-verifier');
  16. var AsymmetricEncrypter = require('./encrypter');
  17. var AsymmetricDecrypter = require('./decrypter');
  18. var validator = require('./input-validator');
  19. var cryptoPolicy = require('scytl-cryptopolicy');
  20. var secureRandom = require('scytl-securerandom');
  21. var forge = require('node-forge');
  22. module.exports = AsymmetricCryptographyService;
  23. /**
  24. * @class AsymmetricCryptographyService
  25. * @classdesc The asymmetric cryptography service API. To instantiate this
  26. * object, use the method {@link newService}.
  27. * @hideconstructor
  28. * @param {Object}
  29. * [options] An object containing optional arguments.
  30. * @param {Policy}
  31. * [options.policy=Default policy] The cryptographic policy to use.
  32. * @param {SecureRandomService}
  33. * [options.secureRandomService=Created internally] The secure random
  34. * service to use.
  35. */
  36. function AsymmetricCryptographyService(options) {
  37. options = options || {};
  38. var policy_;
  39. if (options.policy) {
  40. policy_ = options.policy;
  41. } else {
  42. policy_ = cryptoPolicy.newInstance();
  43. }
  44. var secureRandomService_;
  45. if (options.secureRandomService) {
  46. secureRandomService_ = options.secureRandomService;
  47. } else {
  48. secureRandomService_ = secureRandom.newService();
  49. }
  50. /**
  51. * Creates a new RsaPublicKey object from a provided RSA public key or its
  52. * components.
  53. *
  54. * @function newRsaPublicKey
  55. * @memberof AsymmetricCryptographyService
  56. * @param {Object}
  57. * params An object containing the input parameters for the
  58. * RsaPublicKey object creation.
  59. * @param {string}
  60. * params.pem a PEM string representation of the key. Any
  61. * additional parameters will be ignored.
  62. * @param {number}
  63. * params.n The modulus of the key. Required if
  64. * <code>params.pem</code> is undefined.
  65. * @param {number}
  66. * params.e The public exponent of the key. Required if
  67. * <code>params.pem</code> is undefined.
  68. * @returns {RsaPublicKey} The new RsaPublicKey object.
  69. */
  70. this.newRsaPublicKey = function(params) {
  71. validator.checkIsObjectWithProperties(
  72. params, 'Parameters object for creation of RsaPublicKey object');
  73. if (!params.pem) {
  74. checkPublicKeyData(params);
  75. return new RsaPublicKey(params);
  76. } else {
  77. validator.checkIsNonEmptyString(
  78. params.pem, 'RSA public key, PEM encoded');
  79. var forgePublicKey = forge.pki.publicKeyFromPem(params.pem);
  80. if (typeof forgePublicKey.encrypt === 'undefined') {
  81. throw new Error(
  82. 'PEM encoding of public key for creation of RsaPublicKey object is corrupt');
  83. }
  84. return new RsaPublicKey({n: forgePublicKey.n, e: forgePublicKey.e});
  85. }
  86. };
  87. /**
  88. * Creates a new RsaPrivateKey object from a provided RSA private key or its
  89. * components.
  90. *
  91. * @function newRsaPrivateKey
  92. * @memberof AsymmetricCryptographyService
  93. * @param {Object}
  94. * params An object containing the input parameters for the
  95. * RsaPrivateKey object creation.
  96. * @param {Object}
  97. * params An object containing the required input parameters.
  98. * @param {string}
  99. * params.pem a PEM string representation of the key. Any
  100. * additional parameters will be ignored.
  101. * @param {number}
  102. * params.n The modulus of the key. Required if
  103. * <code>params.pem</code> is undefined.
  104. * @param {number}
  105. * params.e The public exponent of the key. Required if
  106. * <code>params.pem</code> is undefined.
  107. * @param {number}
  108. * params.d The private exponent of the key. Required if
  109. * <code>params.pem</code> is undefined.
  110. * @param {number}
  111. * params.p The first prime of the key. Required if
  112. * <code>params.pem</code> is undefined.
  113. * @param {number}
  114. * params.q The second prime of the key Required if
  115. * <code>params.pem</code> is undefined.
  116. * @param {number}
  117. * params.dP The first exponent of the key. Required if
  118. * <code>params.pem</code> is undefined.
  119. * @param {number}
  120. * params.dQ The second exponent of the key. Required if
  121. * <code>params.pem</code> is undefined.
  122. * @param {number}
  123. * params.qInv The coefficient of the key. Required if
  124. * <code>params.pem</code> is undefined.
  125. * @returns {RsaPrivateKey} The new RsaPrivateKey object.
  126. */
  127. this.newRsaPrivateKey = function(params) {
  128. validator.checkIsObjectWithProperties(
  129. params, 'Parameters object for creation of RsaPrivateKey object');
  130. if (!params.pem) {
  131. checkPrivateKeyData(params);
  132. return new RsaPrivateKey(params);
  133. } else {
  134. validator.checkIsNonEmptyString(
  135. params.pem, 'RSA public key, PEM encoded');
  136. var forgePrivateKey = forge.pki.privateKeyFromPem(params.pem);
  137. if (typeof forgePrivateKey.decrypt === 'undefined') {
  138. throw new Error(
  139. 'PEM encoding of private key for creation of RsaPrivateKey object is corrupt');
  140. }
  141. return new RsaPrivateKey({
  142. n: forgePrivateKey.n,
  143. e: forgePrivateKey.e,
  144. d: forgePrivateKey.d,
  145. p: forgePrivateKey.p,
  146. q: forgePrivateKey.q,
  147. dP: forgePrivateKey.dP,
  148. dQ: forgePrivateKey.dQ,
  149. qInv: forgePrivateKey.qInv
  150. });
  151. }
  152. };
  153. /**
  154. * Creates a new KeyPair object from a provided key pair.
  155. *
  156. * @function newKeyPair
  157. * @memberof AsymmetricCryptographyService
  158. * @param {string}
  159. * publicKey The public key comprising the key pair, in PEM
  160. * format.
  161. * @param {string}
  162. * privateKey The private key comprising the key pair, in PEM
  163. * format.
  164. * @returns {KeyPair} The new KeyPair object.
  165. */
  166. this.newKeyPair = function(publicKey, privateKey) {
  167. validator.checkIsNonEmptyString(publicKey, 'Public key, PEM encoded');
  168. validator.checkIsNonEmptyString(privateKey, 'Private key, PEM encoded');
  169. return new KeyPair(publicKey, privateKey);
  170. };
  171. /**
  172. * Creates a new KeyPairGenerator object for generating key pairs.
  173. *
  174. * @function newKeyPairGenerator
  175. * @memberof AsymmetricCryptographyService
  176. * @returns {RsaKeyPairGenerator} The new RsaKeyPairGenerator object.
  177. */
  178. this.newKeyPairGenerator = function() {
  179. return new KeyPairGenerator(policy_, secureRandomService_);
  180. };
  181. /**
  182. * Creates a new Signer object for digitally signing data. It must be
  183. * initialized with a private key.
  184. *
  185. * @function newSigner
  186. * @memberof AsymmetricCryptographyService
  187. * @returns {Signer} The new Signer object.
  188. */
  189. this.newSigner = function() {
  190. return new Signer(policy_, secureRandomService_);
  191. };
  192. /**
  193. * Creates a new SignatureVerifier object for verifying a digital
  194. * signatures. It must be initialized with a public key.
  195. *
  196. * @function newSignatureVerifier
  197. * @memberof AsymmetricCryptographyService
  198. * @returns {SignatureVerifier} The new SignatureVerifier object.
  199. */
  200. this.newSignatureVerifier = function() {
  201. return new SignatureVerifier(policy_, secureRandomService_);
  202. };
  203. /**
  204. * Creates a new AsymmetricEncrypter object for encrypting data. It must be
  205. * initialized with a public key.
  206. *
  207. * @function newEncrypter
  208. * @memberof AsymmetricCryptographyService
  209. * @returns {AsymmetricEncrypter} The new AsymmetricEncrypter object.
  210. */
  211. this.newEncrypter = function() {
  212. return new AsymmetricEncrypter(policy_, secureRandomService_);
  213. };
  214. /**
  215. * Creates a new AsymmetricDecrypter object for decrypting data. It must be
  216. * initialized with a private key.
  217. *
  218. * @function newDecrypter
  219. * @memberof AsymmetricCryptographyService
  220. * @returns {AsymmetricDecrypter} The new AsymmetricDecrypter object.
  221. */
  222. this.newDecrypter = function() {
  223. return new AsymmetricDecrypter(policy_);
  224. };
  225. function checkPublicKeyData(params) {
  226. validator.checkIsPositiveBigInteger(params.n, 'RSA public key modulus');
  227. validator.checkIsPositiveBigInteger(
  228. params.e, 'RSA public key public exponent');
  229. }
  230. function checkPrivateKeyData(params) {
  231. validator.checkIsPositiveBigInteger(params.n, 'RSA private key modulus');
  232. validator.checkIsPositiveBigInteger(
  233. params.e, 'RSA private key public exponent');
  234. validator.checkIsPositiveBigInteger(
  235. params.d, 'RSA private key private exponent');
  236. validator.checkIsPositiveBigInteger(
  237. params.p, 'RSA private key first prime');
  238. validator.checkIsPositiveBigInteger(
  239. params.q, 'RSA private key second prime');
  240. validator.checkIsPositiveBigInteger(
  241. params.dP, 'RSA private key first exponent');
  242. validator.checkIsPositiveBigInteger(
  243. params.dQ, 'RSA private key second exponent');
  244. validator.checkIsPositiveBigInteger(
  245. params.qInv, 'RSA private key coefficient');
  246. }
  247. }