Source: security/identity/identity-manager.js

  1. /**
  2. * Copyright (C) 2014-2016 Regents of the University of California.
  3. * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  4. * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. * A copy of the GNU Lesser General Public License is in the file COPYING.
  19. */
  20. // Use capitalized Crypto to not clash with the browser's crypto.subtle.
  21. /** @ignore */
  22. var Crypto = require('../../crypto.js'); /** @ignore */
  23. var Name = require('../../name.js').Name; /** @ignore */
  24. var Data = require('../../data.js').Data; /** @ignore */
  25. var Blob = require('../../util/blob.js').Blob; /** @ignore */
  26. var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
  27. var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
  28. var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
  29. var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
  30. var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
  31. var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
  32. var KeyType = require('../security-types.js').KeyType; /** @ignore */
  33. var RsaKeyParams = require('../key-params.js').RsaKeyParams; /** @ignore */
  34. var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
  35. var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
  36. var CertificateSubjectDescription = require('../certificate/certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
  37. var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
  38. var BasicIdentityStorage = require('./basic-identity-storage.js').BasicIdentityStorage; /** @ignore */
  39. var FilePrivateKeyStorage = require('./file-private-key-storage.js').FilePrivateKeyStorage;
  40. /**
  41. * An IdentityManager is the interface of operations related to identity, keys,
  42. * and certificates.
  43. *
  44. * Create a new IdentityManager to use the IdentityStorage and
  45. * PrivateKeyStorage.
  46. * @param {IdentityStorage} identityStorage An object of a subclass of
  47. * IdentityStorage. In Node.js, if this is omitted then use BasicIdentityStorage.
  48. * @param {PrivateKeyStorage} privateKeyStorage An object of a subclass of
  49. * PrivateKeyStorage. In Node.js, if this is omitted then use the default
  50. * PrivateKeyStorage for your system, which is FilePrivateKeyStorage for any
  51. * system other than OS X. (OS X key chain storage is not yet implemented, so
  52. * you must supply a different PrivateKeyStorage.)
  53. * @throws SecurityException if this is not in Node.js and identityStorage or
  54. * privateKeyStorage is omitted.
  55. * @constructor
  56. */
  57. var IdentityManager = function IdentityManager
  58. (identityStorage, privateKeyStorage)
  59. {
  60. if (!identityStorage) {
  61. if (!BasicIdentityStorage)
  62. // Assume we are in the browser.
  63. throw new SecurityException(new Error
  64. ("IdentityManager: If not in Node.js then you must supply an identityStorage."));
  65. identityStorage = new BasicIdentityStorage();
  66. }
  67. if (!privateKeyStorage) {
  68. if (!FilePrivateKeyStorage)
  69. // Assume we are in the browser.
  70. throw new SecurityException(new Error
  71. ("IdentityManager: If not in Node.js then you must supply a privateKeyStorage."));
  72. // Assume we are in Node.js, so check the system.
  73. if (process.platform === "darwin")
  74. throw new SecurityException(new Error
  75. ("IdentityManager: OS X key chain storage is not yet implemented. You must supply a privateKeyStorage."));
  76. else
  77. privateKeyStorage = new FilePrivateKeyStorage();
  78. }
  79. this.identityStorage = identityStorage;
  80. this.privateKeyStorage = privateKeyStorage;
  81. };
  82. exports.IdentityManager = IdentityManager;
  83. /**
  84. * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
  85. * identity and a self-signed certificate of the KSK. If a key pair or
  86. * certificate for the identity already exists, use it.
  87. * @param {Name} identityName The name of the identity.
  88. * @params {KeyParams} params The key parameters if a key needs to be generated
  89. * for the identity.
  90. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  91. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  92. * an async Promise.
  93. * @return {Promise|SyncPromise} A promise which returns the name of the default
  94. * certificate of the identity.
  95. */
  96. IdentityManager.prototype.createIdentityAndCertificatePromise = function
  97. (identityName, params, useSync)
  98. {
  99. var thisManager = this;
  100. var generateKey = true;
  101. var keyName = null;
  102. return this.identityStorage.addIdentityPromise(identityName, useSync)
  103. .then(function() {
  104. return thisManager.identityStorage.getDefaultKeyNameForIdentityPromise
  105. (identityName, useSync)
  106. .then(function(localKeyName) {
  107. keyName = localKeyName;
  108. // Set generateKey.
  109. return thisManager.identityStorage.getKeyPromise(keyName, useSync)
  110. .then(function(publicKeyDer) {
  111. var key = new PublicKey(publicKeyDer);
  112. if (key.getKeyType() == params.getKeyType())
  113. // The key exists and has the same type, so don't need to generate one.
  114. generateKey = false;
  115. return SyncPromise.resolve();
  116. });
  117. }, function(err) {
  118. if (!(err instanceof SecurityException))
  119. throw err;
  120. // The key doesn't exist, so leave generateKey true.
  121. return SyncPromise.resolve();
  122. });
  123. })
  124. .then(function() {
  125. if (generateKey)
  126. return thisManager.generateKeyPairPromise(identityName, true, params, useSync)
  127. .then(function(localKeyName) {
  128. keyName = localKeyName;
  129. return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
  130. (keyName, useSync);
  131. });
  132. else
  133. // Don't generate a key pair. Use the existing keyName.
  134. return SyncPromise.resolve();
  135. })
  136. .then(function() {
  137. return thisManager.identityStorage.getDefaultCertificateNameForKeyPromise
  138. (keyName, useSync)
  139. .then(function(certName) {
  140. // The cert exists, so don't need to make it.
  141. return SyncPromise.resolve(certName);
  142. }, function(err) {
  143. if (!(err instanceof SecurityException))
  144. throw err;
  145. // The cert doesn't exist, so make one.
  146. var certName;
  147. return thisManager.selfSignPromise(keyName, useSync)
  148. .then(function(selfCert) {
  149. certName = selfCert.getName();
  150. return thisManager.addCertificateAsIdentityDefaultPromise(selfCert, useSync);
  151. })
  152. .then(function() {
  153. return SyncPromise.resolve(certName);
  154. });
  155. });
  156. });
  157. };
  158. /**
  159. * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
  160. * identity and a self-signed certificate of the KSK. If a key pair or
  161. * certificate for the identity already exists, use it.
  162. * @param {Name} identityName The name of the identity.
  163. * @params {KeyParams} params The key parameters if a key needs to be generated
  164. * for the identity.
  165. * @param {function} onComplete (optional) This calls onComplete(certificateName)
  166. * with the name of the default certificate of the identity. If omitted, the
  167. * return value is described below. (Some crypto libraries only use a callback,
  168. * so onComplete is required to use these.)
  169. * @param {function} onError (optional) If defined, then onComplete must be
  170. * defined and if there is an exception, then this calls onError(exception)
  171. * with the exception. If onComplete is defined but onError is undefined, then
  172. * this will log any thrown exception. (Some crypto libraries only use a
  173. * callback, so onError is required to be notified of an exception.)
  174. * @return {Name} If onComplete is omitted, return the name of the default
  175. * certificate of the identity. Otherwise, if onComplete is supplied then return
  176. * undefined and use onComplete as described above.
  177. */
  178. IdentityManager.prototype.createIdentityAndCertificate = function
  179. (identityName, params, onComplete, onError)
  180. {
  181. return SyncPromise.complete(onComplete, onError,
  182. this.createIdentityAndCertificatePromise(identityName, params, !onComplete));
  183. };
  184. /**
  185. * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
  186. * identity and a self-signed certificate of the KSK. If a key pair or
  187. * certificate for the identity already exists, use it.
  188. * @deprecated Use createIdentityAndCertificate which returns the
  189. * certificate name instead of the key name. You can use
  190. * IdentityCertificate.certificateNameToPublicKeyName to convert the
  191. * certificate name to the key name.
  192. * @param {Name} identityName The name of the identity.
  193. * @params {KeyParams} params The key parameters if a key needs to be generated
  194. * for the identity.
  195. * @return {Name} The key name of the auto-generated KSK of the identity.
  196. */
  197. IdentityManager.prototype.createIdentity = function(identityName, params)
  198. {
  199. return IdentityCertificate.certificateNameToPublicKeyName
  200. (this.createIdentityAndCertificate(identityName, params));
  201. };
  202. /**
  203. * Delete the identity from the public and private key storage. If the
  204. * identity to be deleted is the current default system default, this will not
  205. * delete the identity and will return immediately.
  206. * @param {Name} identityName The name of the identity.
  207. * @param {function} onComplete (optional) This calls onComplete() when the
  208. * operation is complete. If omitted, do not use it. (Some database libraries
  209. * only use a callback, so onComplete is required to use these.)
  210. * @param {function} onError (optional) If defined, then onComplete must be
  211. * defined and if there is an exception, then this calls onError(exception)
  212. * with the exception. If onComplete is defined but onError is undefined, then
  213. * this will log any thrown exception. (Some database libraries only use a
  214. * callback, so onError is required to be notified of an exception.)
  215. */
  216. IdentityManager.prototype.deleteIdentity = function
  217. (identityName, onComplete, onError)
  218. {
  219. var useSync = !onComplete;
  220. var thisManager = this;
  221. var doDelete = true;
  222. var mainPromise = this.identityStorage.getDefaultIdentityPromise(useSync)
  223. .then(function(defaultIdentityName) {
  224. if (defaultIdentityName.equals(identityName))
  225. // Don't delete the default identity!
  226. doDelete = false;
  227. return SyncPromise.resolve();
  228. }, function(err) {
  229. // There is no default identity to check.
  230. return SyncPromise.resolve();
  231. })
  232. .then(function() {
  233. if (!doDelete)
  234. return SyncPromise.resolve();
  235. var keysToDelete = [];
  236. return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
  237. (identityName, keysToDelete, true)
  238. .then(function() {
  239. return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
  240. (identityName, keysToDelete, false);
  241. })
  242. .then(function() {
  243. return thisManager.identityStorage.deleteIdentityInfoPromise(identityName);
  244. })
  245. .then(function() {
  246. // Recursively loop through keysToDelete, calling deleteKeyPairPromise.
  247. function deleteKeyLoop(i) {
  248. if (i >= keysToDelete.length)
  249. return SyncPromise.resolve();
  250. return thisManager.privateKeyStorage.deleteKeyPairPromise(keysToDelete[i])
  251. .then(function() {
  252. return deleteKeyLoop(i + 1);
  253. });
  254. }
  255. return deleteKeyLoop(0);
  256. });
  257. });
  258. return SyncPromise.complete(onComplete, onError, mainPromise);
  259. };
  260. /**
  261. * Set the default identity. If the identityName does not exist, then clear the
  262. * default identity so that getDefaultIdentity() throws an exception.
  263. * @param {Name} identityName The default identity name.
  264. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  265. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  266. * an async Promise.
  267. * @return {Promise|SyncPromise} A promise which fulfills when the default
  268. * identity is set.
  269. */
  270. IdentityManager.prototype.setDefaultIdentityPromise = function
  271. (identityName, useSync)
  272. {
  273. return this.identityStorage.setDefaultIdentityPromise(identityName, useSync);
  274. };
  275. /**
  276. * Set the default identity. If the identityName does not exist, then clear the
  277. * default identity so that getDefaultIdentity() throws an exception.
  278. * @param {Name} identityName The default identity name.
  279. * @param {function} onComplete (optional) This calls onComplete() when complete.
  280. * (Some database libraries only use a callback, so onComplete is required to
  281. * use these.)
  282. * @param {function} onError (optional) If defined, then onComplete must be
  283. * defined and if there is an exception, then this calls onError(exception)
  284. * with the exception. If onComplete is defined but onError is undefined, then
  285. * this will log any thrown exception. (Some database libraries only use a
  286. * callback, so onError is required to be notified of an exception.)
  287. */
  288. IdentityManager.prototype.setDefaultIdentity = function
  289. (identityName, onComplete, onError)
  290. {
  291. return SyncPromise.complete(onComplete, onError,
  292. this.identityStorage.setDefaultIdentityPromise(identityName, !onComplete));
  293. };
  294. /**
  295. * Get the default identity.
  296. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  297. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  298. * an async Promise.
  299. * @return {Promise|SyncPromise} A promise which returns the Name of default
  300. * identity, or a promise rejected with SecurityException if the default
  301. * identity is not set.
  302. */
  303. IdentityManager.prototype.getDefaultIdentityPromise = function(useSync)
  304. {
  305. return this.identityStorage.getDefaultIdentityPromise(useSync);
  306. };
  307. /**
  308. * Get the default identity.
  309. * @param {function} onComplete (optional) This calls onComplete(identityName)
  310. * with name of the default identity. If omitted, the return value is described
  311. * below. (Some database libraries only use a callback, so onComplete is required
  312. * to use these.)
  313. * @param {function} onError (optional) If defined, then onComplete must be
  314. * defined and if there is an exception, then this calls onError(exception)
  315. * with the exception. If onComplete is defined but onError is undefined, then
  316. * this will log any thrown exception. (Some database libraries only use a
  317. * callback, so onError is required to be notified of an exception.)
  318. * @returns {Name} If onComplete is omitted, return the name of the default
  319. * identity. Otherwise, if onComplete is supplied then return undefined and use
  320. * onComplete as described above.
  321. * @throws SecurityException if the default identity is not set. However, if
  322. * onComplete and onError are defined, then if there is an exception return
  323. * undefined and call onError(exception).
  324. */
  325. IdentityManager.prototype.getDefaultIdentity = function(onComplete, onError)
  326. {
  327. return SyncPromise.complete(onComplete, onError,
  328. this.identityStorage.getDefaultIdentityPromise(!onComplete));
  329. };
  330. /**
  331. * Get the certificate of the default identity.
  332. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  333. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  334. * an async Promise.
  335. * @return {Promise|SyncPromise} A promise which returns the requested
  336. * IdentityCertificate or null if not found.
  337. */
  338. IdentityManager.prototype.getDefaultCertificatePromise = function(useSync)
  339. {
  340. return this.identityStorage.getDefaultCertificatePromise(useSync);
  341. };
  342. /**
  343. * Generate a pair of RSA keys for the specified identity.
  344. * @param {Name} identityName The name of the identity.
  345. * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
  346. * a Data-Signing-Key (DSK).
  347. * @param {number} keySize The size of the key.
  348. * @return {Name} The generated key name.
  349. */
  350. IdentityManager.prototype.generateRSAKeyPair = function
  351. (identityName, isKsk, keySize)
  352. {
  353. // For now, require sync. This method may be removed from the API.
  354. return SyncPromise.getValue
  355. (this.generateKeyPairPromise
  356. (identityName, isKsk, new RsaKeyParams(keySize), true));
  357. };
  358. /**
  359. * Set a key as the default key of an identity. The identity name is inferred
  360. * from keyName.
  361. * @param {Name} keyName The name of the key.
  362. * @param {Name} identityNameCheck (optional) The identity name to check that the
  363. * keyName contains the same identity name. If an empty name, it is ignored.
  364. * @param {function} onComplete (optional) This calls onComplete() when complete.
  365. * (Some database libraries only use a callback, so onComplete is required to
  366. * use these.)
  367. * @param {function} onError (optional) If defined, then onComplete must be
  368. * defined and if there is an exception, then this calls onError(exception)
  369. * with the exception. If onComplete is defined but onError is undefined, then
  370. * this will log any thrown exception. (Some database libraries only use a
  371. * callback, so onError is required to be notified of an exception.)
  372. */
  373. IdentityManager.prototype.setDefaultKeyForIdentity = function
  374. (keyName, identityNameCheck, onComplete, onError)
  375. {
  376. onError = (typeof identityNameCheck === "function") ? onComplete : onError;
  377. onComplete = (typeof identityNameCheck === "function") ?
  378. identityNameCheck : onComplete;
  379. identityNameCheck = (typeof identityNameCheck === "function" || !identityNameCheck) ?
  380. new Name() : identityNameCheck;
  381. return SyncPromise.complete(onComplete, onError,
  382. this.identityStorage.setDefaultKeyNameForIdentityPromise
  383. (keyName, identityNameCheck, !onComplete));
  384. };
  385. /**
  386. * Get the default key for an identity.
  387. * @param {Name} identityName The name of the identity.
  388. * @param {function} onComplete (optional) This calls onComplete(keyName)
  389. * with name of the default key. If omitted, the return value is described
  390. * below. (Some database libraries only use a callback, so onComplete is required
  391. * to use these.)
  392. * @param {function} onError (optional) If defined, then onComplete must be
  393. * defined and if there is an exception, then this calls onError(exception)
  394. * with the exception. If onComplete is defined but onError is undefined, then
  395. * this will log any thrown exception. (Some database libraries only use a
  396. * callback, so onError is required to be notified of an exception.)
  397. * @return {Name} If onComplete is omitted, return the default key name.
  398. * Otherwise, if onComplete is supplied then return undefined and use onComplete
  399. * as described above.
  400. * @throws SecurityException if the default key name for the identity is not set.
  401. * However, if onComplete and onError are defined, then if there is an exception
  402. * return undefined and call onError(exception).
  403. */
  404. IdentityManager.prototype.getDefaultKeyNameForIdentity = function
  405. (identityName, onComplete, onError)
  406. {
  407. return SyncPromise.complete(onComplete, onError,
  408. this.identityStorage.getDefaultKeyNameForIdentityPromise
  409. (identityName, !onComplete));
  410. };
  411. /**
  412. * Generate a pair of RSA keys for the specified identity and set it as default
  413. * key for the identity.
  414. * @param {Name} identityName The name of the identity.
  415. * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
  416. * a Data-Signing-Key (DSK).
  417. * @param {number} keySize The size of the key.
  418. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  419. * is already fulfilled. If false, this may return a SyncPromise or an async
  420. * Promise.
  421. * @return {Promise|SyncPromise} A promise which returns the generated key name.
  422. */
  423. IdentityManager.prototype.generateRSAKeyPairAsDefaultPromise = function
  424. (identityName, isKsk, keySize, useSync)
  425. {
  426. var newKeyName;
  427. var thisManager = this;
  428. return this.generateKeyPairPromise(identityName, isKsk, new RsaKeyParams(keySize))
  429. .then(function(localKeyName) {
  430. newKeyName = localKeyName;
  431. return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
  432. (newKeyName);
  433. })
  434. .then(function() {
  435. return SyncPromise.resolve(newKeyName);
  436. });
  437. };
  438. /**
  439. * Generate a pair of RSA keys for the specified identity and set it as default
  440. * key for the identity.
  441. * @param {Name} identityName The name of the identity.
  442. * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
  443. * a Data-Signing-Key (DSK).
  444. * @param {number} keySize The size of the key.
  445. * @return {Name} The generated key name.
  446. */
  447. IdentityManager.prototype.generateRSAKeyPairAsDefault = function
  448. (identityName, isKsk, keySize)
  449. {
  450. return SyncPromise.getValue
  451. (this.generateRSAKeyPairAsDefaultPromise(identityName, isKsk, keySize, true));
  452. };
  453. /**
  454. * Get the public key with the specified name.
  455. * @param {Name} keyName The name of the key.
  456. * @param {function} onComplete (optional) This calls onComplete(publicKey)
  457. * with PublicKey. If omitted, the return value is described below. (Some database
  458. * libraries only use a callback, so onComplete is required to use these.)
  459. * @param {function} onError (optional) If defined, then onComplete must be
  460. * defined and if there is an exception, then this calls onError(exception)
  461. * with the exception. If onComplete is defined but onError is undefined, then
  462. * this will log any thrown exception. (Some database libraries only use a
  463. * callback, so onError is required to be notified of an exception.)
  464. * @return {PublicKey} If onComplete is omitted, return the public key.
  465. * Otherwise, if onComplete is supplied then return undefined and use onComplete
  466. * as described above.
  467. */
  468. IdentityManager.prototype.getPublicKey = function(keyName, onComplete, onError)
  469. {
  470. return SyncPromise.complete(onComplete, onError,
  471. this.identityStorage.getKeyPromise(keyName, !onComplete)
  472. .then(function(keyDer) {
  473. return SyncPromise.resolve(new PublicKey(keyDer));
  474. }));
  475. };
  476. // TODO: Add two versions of createIdentityCertificate.
  477. /**
  478. * Prepare an unsigned identity certificate.
  479. * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
  480. * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
  481. * use the keyName to get the public key from the identity storage.
  482. * @param {Name} signingIdentity The signing identity.
  483. * @param {number} notBefore See IdentityCertificate.
  484. * @param {number} notAfter See IdentityCertificate.
  485. * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
  486. * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
  487. * this adds a an ATTRIBUTE_NAME based on the keyName.
  488. * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
  489. * null or omitted, this infers the certificate name according to the relation
  490. * between the signingIdentity and the subject identity. If the signingIdentity
  491. * is a prefix of the subject identity, `KEY` will be inserted after the
  492. * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
  493. * before `ksk-...`).
  494. * @param {function} onComplete (optional) This calls onComplete(certificate)
  495. * with the unsigned IdentityCertificate, or null if the inputs are invalid. If
  496. * omitted, the return value is described below. (Some database libraries only
  497. * use a callback, so onComplete is required to use these.)
  498. * @param {function} onError (optional) If defined, then onComplete must be
  499. * defined and if there is an exception, then this calls onError(exception)
  500. * with the exception. If onComplete is defined but onError is undefined, then
  501. * this will log any thrown exception. (Some database libraries only use a
  502. * callback, so onError is required to be notified of an exception.)
  503. * @return {IdentityCertificate} If onComplete is omitted, return the the
  504. * unsigned IdentityCertificate, or null if the inputs are invalid. Otherwise,
  505. * if onComplete is supplied then return undefined and use onComplete as
  506. * described above.
  507. */
  508. IdentityManager.prototype.prepareUnsignedIdentityCertificate = function
  509. (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
  510. certPrefix, onComplete, onError)
  511. {
  512. if (!(publicKey instanceof PublicKey)) {
  513. // The publicKey was omitted. Shift arguments.
  514. onError = onComplete;
  515. onComplete = certPrefix;
  516. certPrefix = subjectDescription;
  517. subjectDescription = notAfter;
  518. notAfter = notBefore;
  519. notBefore = signingIdentity;
  520. signingIdentity = publicKey;
  521. publicKey = null;
  522. }
  523. // certPrefix may be omitted or null, so check for it and the following args.
  524. var arg7 = certPrefix;
  525. var arg8 = onComplete;
  526. var arg9 = onError;
  527. if (arg7 instanceof Name)
  528. certPrefix = arg7;
  529. else
  530. certPrefix = null;
  531. if (typeof arg7 === 'function') {
  532. onComplete = arg7;
  533. onError = arg8;
  534. }
  535. else if (typeof arg8 === 'function') {
  536. onComplete = arg8;
  537. onError = arg9;
  538. }
  539. else {
  540. onComplete = null;
  541. onError = null;
  542. }
  543. var promise;
  544. if (publicKey == null)
  545. promise = this.prepareUnsignedIdentityCertificatePromise
  546. (keyName, signingIdentity, notBefore, notAfter, subjectDescription,
  547. certPrefix, !onComplete);
  548. else
  549. promise = this.prepareUnsignedIdentityCertificatePromise
  550. (keyName, publicKey, signingIdentity, notBefore, notAfter,
  551. subjectDescription, certPrefix, !onComplete);
  552. return SyncPromise.complete(onComplete, onError, promise);
  553. };
  554. /**
  555. * Prepare an unsigned identity certificate.
  556. * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
  557. * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
  558. * use the keyName to get the public key from the identity storage.
  559. * @param {Name} signingIdentity The signing identity.
  560. * @param {number} notBefore See IdentityCertificate.
  561. * @param {number} notAfter See IdentityCertificate.
  562. * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
  563. * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
  564. * this adds a an ATTRIBUTE_NAME based on the keyName.
  565. * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
  566. * null or omitted, this infers the certificate name according to the relation
  567. * between the signingIdentity and the subject identity. If the signingIdentity
  568. * is a prefix of the subject identity, `KEY` will be inserted after the
  569. * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
  570. * before `ksk-...`).
  571. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  572. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  573. * an async Promise.
  574. * @return {Promise|SyncPromise} A promise that returns the unsigned
  575. * IdentityCertificate, or that returns null if the inputs are invalid.
  576. */
  577. IdentityManager.prototype.prepareUnsignedIdentityCertificatePromise = function
  578. (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
  579. certPrefix, useSync)
  580. {
  581. if (!(publicKey instanceof PublicKey)) {
  582. // The publicKey was omitted. Shift arguments.
  583. useSync = certPrefix;
  584. certPrefix = subjectDescription;
  585. subjectDescription = notAfter;
  586. notAfter = notBefore;
  587. notBefore = signingIdentity;
  588. signingIdentity = publicKey;
  589. publicKey = null;
  590. }
  591. // certPrefix may be omitted or null, so check for it and the following arg.
  592. var arg7 = certPrefix;
  593. var arg8 = useSync;
  594. if (arg7 instanceof Name)
  595. certPrefix = arg7;
  596. else
  597. certPrefix = null;
  598. if (typeof arg7 === 'boolean')
  599. useSync = arg7;
  600. else if (typeof arg8 === 'boolean')
  601. useSync = arg8;
  602. else
  603. useSync = false;
  604. var promise;
  605. if (publicKey == null) {
  606. promise = this.identityStorage.getKeyPromise(keyName, useSync)
  607. .then(function(keyDer) {
  608. publicKey = new PublicKey(keyDer);
  609. return SyncPromise.resolve();
  610. });
  611. }
  612. else
  613. promise = SyncPromise.resolve();
  614. return promise
  615. .then(function() {
  616. return SyncPromise.resolve
  617. (IdentityManager.prepareUnsignedIdentityCertificateHelper_
  618. (keyName, publicKey, signingIdentity, notBefore, notAfter,
  619. subjectDescription, certPrefix));
  620. });
  621. };
  622. /**
  623. * A helper for prepareUnsignedIdentityCertificatePromise where the publicKey
  624. * is known.
  625. */
  626. IdentityManager.prepareUnsignedIdentityCertificateHelper_ = function
  627. (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
  628. certPrefix)
  629. {
  630. if (keyName.size() < 1)
  631. return null;
  632. var tempKeyIdPrefix = keyName.get(-1).toEscapedString();
  633. if (tempKeyIdPrefix.length < 4)
  634. return null;
  635. keyIdPrefix = tempKeyIdPrefix.substr(0, 4);
  636. if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
  637. return null;
  638. var certificate = new IdentityCertificate();
  639. var certName = new Name();
  640. if (certPrefix == null) {
  641. // No certificate prefix hint, so infer the prefix.
  642. if (signingIdentity.match(keyName))
  643. certName.append(signingIdentity)
  644. .append("KEY")
  645. .append(keyName.getSubName(signingIdentity.size()))
  646. .append("ID-CERT")
  647. .appendVersion(new Date().getTime());
  648. else
  649. certName.append(keyName.getPrefix(-1))
  650. .append("KEY")
  651. .append(keyName.get(-1))
  652. .append("ID-CERT")
  653. .appendVersion(new Date().getTime());
  654. }
  655. else {
  656. // A cert prefix hint is supplied, so determine the cert name.
  657. if (certPrefix.match(keyName) && !certPrefix.equals(keyName))
  658. certName.append(certPrefix)
  659. .append("KEY")
  660. .append(keyName.getSubName(certPrefix.size()))
  661. .append("ID-CERT")
  662. .appendVersion(new Date().getTime());
  663. else
  664. return null;
  665. }
  666. certificate.setName(certName);
  667. certificate.setNotBefore(notBefore);
  668. certificate.setNotAfter(notAfter);
  669. certificate.setPublicKeyInfo(publicKey);
  670. if (subjectDescription == null || subjectDescription.length === 0)
  671. certificate.addSubjectDescription(new CertificateSubjectDescription
  672. ("2.5.4.41", keyName.getPrefix(-1).toUri()));
  673. else {
  674. for (var i = 0; i < subjectDescription.length; ++i)
  675. certificate.addSubjectDescription(subjectDescription[i]);
  676. }
  677. try {
  678. certificate.encode();
  679. } catch (ex) {
  680. throw SecurityException(new Error("DerEncodingException: " + ex));
  681. }
  682. return certificate;
  683. };
  684. /**
  685. * Add a certificate into the public key identity storage.
  686. * @param {IdentityCertificate} certificate The certificate to to added. This
  687. * makes a copy of the certificate.
  688. * @param {function} onComplete (optional) This calls onComplete() when complete.
  689. * (Some database libraries only use a callback, so onComplete is required to
  690. * use these.)
  691. * @param {function} onError (optional) If defined, then onComplete must be
  692. * defined and if there is an exception, then this calls onError(exception)
  693. * with the exception. If onComplete is defined but onError is undefined, then
  694. * this will log any thrown exception. (Some database libraries only use a
  695. * callback, so onError is required to be notified of an exception.)
  696. */
  697. IdentityManager.prototype.addCertificate = function
  698. (certificate, onComplete, onError)
  699. {
  700. return SyncPromise.complete(onComplete, onError,
  701. this.identityStorage.addCertificatePromise(certificate, !onComplete));
  702. };
  703. /**
  704. * Set the certificate as the default for its corresponding key.
  705. * @param {IdentityCertificate} certificate The certificate.
  706. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  707. * is already fulfilled. If false, this may return a SyncPromise or an async
  708. * Promise.
  709. * @return {Promise|SyncPromise} A promise which fulfills when the default
  710. * certificate is set.
  711. */
  712. IdentityManager.prototype.setDefaultCertificateForKeyPromise = function
  713. (certificate, useSync)
  714. {
  715. var thisManager = this;
  716. var keyName = certificate.getPublicKeyName();
  717. return this.identityStorage.doesKeyExistPromise(keyName, useSync)
  718. .then(function(exists) {
  719. if (!exists)
  720. throw new SecurityException(new Error
  721. ("No corresponding Key record for certificate!"));
  722. return thisManager.identityStorage.setDefaultCertificateNameForKeyPromise
  723. (keyName, certificate.getName(), useSync);
  724. });
  725. };
  726. /**
  727. * Set the certificate as the default for its corresponding key.
  728. * @param {IdentityCertificate} certificate The certificate.
  729. * @param {function} onComplete (optional) This calls onComplete() when complete.
  730. * (Some database libraries only use a callback, so onComplete is required to
  731. * use these.)
  732. * @param {function} onError (optional) If defined, then onComplete must be
  733. * defined and if there is an exception, then this calls onError(exception)
  734. * with the exception. If onComplete is defined but onError is undefined, then
  735. * this will log any thrown exception. (Some database libraries only use a
  736. * callback, so onError is required to be notified of an exception.)
  737. */
  738. IdentityManager.prototype.setDefaultCertificateForKey = function
  739. (certificate, onComplete, onError)
  740. {
  741. return SyncPromise.complete(onComplete, onError,
  742. this.setDefaultCertificateForKeyPromise(certificate, !onComplete));
  743. };
  744. /**
  745. * Add a certificate into the public key identity storage and set the
  746. * certificate as the default for its corresponding identity.
  747. * @param {IdentityCertificate} certificate The certificate to be added. This
  748. * makes a copy of the certificate.
  749. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  750. * is already fulfilled. If false, this may return a SyncPromise or an async
  751. * Promise.
  752. * @return {Promise|SyncPromise} A promise which fulfills when the certificate
  753. * is added.
  754. */
  755. IdentityManager.prototype.addCertificateAsIdentityDefaultPromise = function
  756. (certificate, useSync)
  757. {
  758. var thisManager = this;
  759. return this.identityStorage.addCertificatePromise(certificate, useSync)
  760. .then(function() {
  761. var keyName = certificate.getPublicKeyName();
  762. return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
  763. (keyName, useSync);
  764. })
  765. .then(function() {
  766. return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
  767. });
  768. };
  769. /**
  770. * Add a certificate into the public key identity storage and set the
  771. * certificate as the default of its corresponding key.
  772. * @param {IdentityCertificate} certificate The certificate to be added. This
  773. * makes a copy of the certificate.
  774. * @param {function} onComplete (optional) This calls onComplete() when complete.
  775. * (Some database libraries only use a callback, so onComplete is required to use
  776. * these.)
  777. * @param {function} onError (optional) If defined, then onComplete must be
  778. * defined and if there is an exception, then this calls onError(exception)
  779. * with the exception. If onComplete is defined but onError is undefined, then
  780. * this will log any thrown exception. (Some database libraries only use a
  781. * callback, so onError is required to be notified of an exception.)
  782. */
  783. IdentityManager.prototype.addCertificateAsDefault = function
  784. (certificate, onComplete, onError)
  785. {
  786. var useSync = !onComplete;
  787. var thisManager = this;
  788. return SyncPromise.complete(onComplete, onError,
  789. this.identityStorage.addCertificatePromise(certificate, useSync)
  790. .then(function() {
  791. return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
  792. }));
  793. };
  794. /**
  795. * Get a certificate which is still valid with the specified name.
  796. * @param {Name} certificateName The name of the requested certificate.
  797. * @param {function} onComplete (optional) This calls onComplete(certificate)
  798. * with the requested IdentityCertificate. If omitted, the return value is
  799. * described below. (Some database libraries only use a callback, so onComplete
  800. * is required to use these.)
  801. * @param {function} onError (optional) If defined, then onComplete must be
  802. * defined and if there is an exception, then this calls onError(exception)
  803. * with the exception. If onComplete is defined but onError is undefined, then
  804. * this will log any thrown exception. (Some database libraries only use a
  805. * callback, so onError is required to be notified of an exception.)
  806. * @return {IdentityCertificate} If onComplete is omitted, return the requested
  807. * certificate. Otherwise, if onComplete is supplied then return undefined and
  808. * use onComplete as described above.
  809. */
  810. IdentityManager.prototype.getCertificate = function
  811. (certificateName, onComplete, onError)
  812. {
  813. return SyncPromise.complete(onComplete, onError,
  814. this.identityStorage.getCertificatePromise
  815. (certificateName, false, !onComplete));
  816. };
  817. /**
  818. * Get the default certificate name for the specified identity.
  819. * @param {Name} identityName The identity name.
  820. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  821. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  822. * an async Promise.
  823. * @return {Promise|SyncPromise} A promise which returns the default certificate
  824. * Name, or a promise rejected with SecurityException if the default key name
  825. * for the identity is not set or the default certificate name for the key name
  826. * is not set.
  827. */
  828. IdentityManager.prototype.getDefaultCertificateNameForIdentityPromise = function
  829. (identityName, useSync)
  830. {
  831. return this.identityStorage.getDefaultCertificateNameForIdentityPromise
  832. (identityName, useSync);
  833. }
  834. /**
  835. * Get the default certificate name for the specified identity, which will be
  836. * used when signing is performed based on identity.
  837. * @param {Name} identityName The name of the specified identity.
  838. * @param {function} onComplete (optional) This calls onComplete(certificateName)
  839. * with name of the default certificate. If omitted, the return value is described
  840. * below. (Some database libraries only use a callback, so onComplete is required
  841. * to use these.)
  842. * @param {function} onError (optional) If defined, then onComplete must be
  843. * defined and if there is an exception, then this calls onError(exception)
  844. * with the exception. If onComplete is defined but onError is undefined, then
  845. * this will log any thrown exception. (Some database libraries only use a
  846. * callback, so onError is required to be notified of an exception.)
  847. * @return {Name} If onComplete is omitted, return the default certificate name.
  848. * Otherwise, if onComplete is supplied then return undefined and use
  849. * onComplete as described above.
  850. * @throws SecurityException if the default key name for the identity is not
  851. * set or the default certificate name for the key name is not set. However, if
  852. * onComplete and onError are defined, then if there is an exception return
  853. * undefined and call onError(exception).
  854. */
  855. IdentityManager.prototype.getDefaultCertificateNameForIdentity = function
  856. (identityName, onComplete, onError)
  857. {
  858. return SyncPromise.complete(onComplete, onError,
  859. this.identityStorage.getDefaultCertificateNameForIdentityPromise
  860. (identityName, !onComplete));
  861. };
  862. /**
  863. * Get the default certificate name of the default identity, which will be used
  864. * when signing is based on identity and the identity is not specified.
  865. * @param {function} onComplete (optional) This calls onComplete(certificateName)
  866. * with name of the default certificate. If omitted, the return value is described
  867. * below. (Some database libraries only use a callback, so onComplete is required
  868. * to use these.)
  869. * @param {function} onError (optional) If defined, then onComplete must be
  870. * defined and if there is an exception, then this calls onError(exception)
  871. * with the exception. If onComplete is defined but onError is undefined, then
  872. * this will log any thrown exception. (Some database libraries only use a
  873. * callback, so onError is required to be notified of an exception.)
  874. * @return {Name} If onComplete is omitted, return the default certificate name.
  875. * Otherwise, if onComplete is supplied then return undefined and use
  876. * onComplete as described above.
  877. * @throws SecurityException if the default identity is not set or the default
  878. * key name for the identity is not set or the default certificate name for
  879. * the key name is not set. However, if onComplete and onError are defined, then
  880. * if there is an exception return undefined and call onError(exception).
  881. */
  882. IdentityManager.prototype.getDefaultCertificateName = function
  883. (onComplete, onError)
  884. {
  885. var useSync = !onComplete;
  886. var thisManager = this;
  887. return SyncPromise.complete(onComplete, onError,
  888. this.identityStorage.getDefaultIdentityPromise(useSync)
  889. .then(function(identityName) {
  890. return thisManager.identityStorage.getDefaultCertificateNameForIdentityPromise
  891. (identityName, useSync);
  892. }));
  893. };
  894. /**
  895. * Append all the identity names to the nameList.
  896. * @param {Array<Name>} nameList Append result names to nameList.
  897. * @param {boolean} isDefault If true, add only the default identity name. If
  898. * false, add only the non-default identity names.
  899. * @param {function} onComplete (optional) This calls onComplete() when finished
  900. * adding to nameList. If omitted, this returns when complete. (Some database
  901. * libraries only use a callback, so onComplete is required to use these.)
  902. * @param {function} onError (optional) If defined, then onComplete must be
  903. * defined and if there is an exception, then this calls onError(exception)
  904. * with the exception. If onComplete is defined but onError is undefined, then
  905. * this will log any thrown exception. (Some database libraries only use a
  906. * callback, so onError is required to be notified of an exception.)
  907. * @return {void} If onComplete is omitted, return when complete. Otherwise, if
  908. * onComplete is supplied then return undefined and use onComplete as described
  909. * above.
  910. */
  911. IdentityManager.prototype.getAllIdentities = function
  912. (nameList, isDefault, onComplete, onError)
  913. {
  914. return SyncPromise.complete(onComplete, onError,
  915. this.identityStorage.getAllIdentitiesPromise
  916. (nameList, isDefault, !onComplete));
  917. };
  918. /**
  919. * Append all the key names of a particular identity to the nameList.
  920. * @param {Name} identityName The identity name to search for.
  921. * @param {Array<Name>} nameList Append result names to nameList.
  922. * @param {boolean} isDefault If true, add only the default key name. If false,
  923. * add only the non-default key names.
  924. * @param {function} onComplete (optional) This calls onComplete() when finished
  925. * adding to nameList. If omitted, this returns when complete. (Some database
  926. * libraries only use a callback, so onComplete is required to use these.)
  927. * @param {function} onError (optional) If defined, then onComplete must be
  928. * defined and if there is an exception, then this calls onError(exception)
  929. * with the exception. If onComplete is defined but onError is undefined, then
  930. * this will log any thrown exception. (Some database libraries only use a
  931. * callback, so onError is required to be notified of an exception.)
  932. * @return {void} If onComplete is omitted, return when complete. Otherwise, if
  933. * onComplete is supplied then return undefined and use onComplete as described
  934. * above.
  935. */
  936. IdentityManager.prototype.getAllKeyNamesOfIdentity = function
  937. (identityName, nameList, isDefault, onComplete, onError)
  938. {
  939. return SyncPromise.complete(onComplete, onError,
  940. this.identityStorage.getAllKeyNamesOfIdentityPromise
  941. (identityName, nameList, isDefault, !onComplete));
  942. };
  943. /**
  944. * Append all the certificate names of a particular key name to the nameList.
  945. * @param {Name} keyName The key name to search for.
  946. * @param {Array<Name>} nameList Append result names to nameList.
  947. * @param {boolean} isDefault If true, add only the default certificate name. If
  948. * false, add only the non-default certificate names.
  949. * @param {function} onComplete (optional) This calls onComplete() when finished
  950. * adding to nameList. If omitted, this returns when complete. (Some database
  951. * libraries only use a callback, so onComplete is required to use these.)
  952. * @param {function} onError (optional) If defined, then onComplete must be
  953. * defined and if there is an exception, then this calls onError(exception)
  954. * with the exception. If onComplete is defined but onError is undefined, then
  955. * this will log any thrown exception. (Some database libraries only use a
  956. * callback, so onError is required to be notified of an exception.)
  957. * @return {void} If onComplete is omitted, return when complete. Otherwise, if
  958. * onComplete is supplied then return undefined and use onComplete as described
  959. * above.
  960. */
  961. IdentityManager.prototype.getAllCertificateNamesOfKey = function
  962. (keyName, nameList, isDefault, onComplete, onError)
  963. {
  964. return SyncPromise.complete(onComplete, onError,
  965. this.identityStorage.getAllCertificateNamesOfKeyPromise
  966. (keyName, nameList, isDefault, !onComplete));
  967. };
  968. /**
  969. * Sign the Data packet or byte array data based on the certificate name.
  970. * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
  971. * update its signature and key locator field and wireEncoding. If it is a
  972. * Buffer, sign it to produce a Signature object.
  973. * @param {Name} certificateName The Name identifying the certificate which
  974. * identifies the signing key.
  975. * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
  976. * WireFormat.getDefaultWireFormat() if omitted.
  977. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  978. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  979. * an async Promise.
  980. * @return {Promise|SyncPromise} A promise that returns the generated Signature
  981. * object (if target is a Buffer) or the target (if target is Data).
  982. */
  983. IdentityManager.prototype.signByCertificatePromise = function
  984. (target, certificateName, wireFormat, useSync)
  985. {
  986. useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
  987. wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
  988. var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
  989. var thisManager = this;
  990. if (target instanceof Data) {
  991. var data = target;
  992. var digestAlgorithm = [0];
  993. return this.makeSignatureByCertificatePromise
  994. (certificateName, digestAlgorithm, useSync)
  995. .then(function(signature) {
  996. data.setSignature(signature);
  997. // Encode once to get the signed portion.
  998. var encoding = data.wireEncode(wireFormat);
  999. return thisManager.privateKeyStorage.signPromise
  1000. (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
  1001. })
  1002. .then(function(signatureValue) {
  1003. data.getSignature().setSignature(signatureValue);
  1004. // Encode again to include the signature.
  1005. data.wireEncode(wireFormat);
  1006. return SyncPromise.resolve(data);
  1007. });
  1008. }
  1009. else {
  1010. var digestAlgorithm = [0];
  1011. return this.makeSignatureByCertificatePromise
  1012. (certificateName, digestAlgorithm, useSync)
  1013. .then(function(signature) {
  1014. return thisManager.privateKeyStorage.signPromise
  1015. (target, keyName, digestAlgorithm[0], useSync);
  1016. })
  1017. .then(function (signatureValue) {
  1018. signature.setSignature(signatureValue);
  1019. return SyncPromise.resolve(signature);
  1020. });
  1021. }
  1022. };
  1023. /**
  1024. * Sign the Data packet or byte array data based on the certificate name.
  1025. * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
  1026. * update its signature and key locator field and wireEncoding. If it is a
  1027. * Buffer, sign it to produce a Signature object.
  1028. * @param {Name} certificateName The Name identifying the certificate which
  1029. * identifies the signing key.
  1030. * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
  1031. * WireFormat.getDefaultWireFormat() if omitted.
  1032. * @param {function} onComplete (optional) If target is a Data object, this calls
  1033. * onComplete(data) with the supplied Data object which has been modified to set
  1034. * its signature. If target is a Buffer, this calls onComplete(signature) where
  1035. * signature is the produced Signature object. If omitted, the return value is
  1036. * described below. (Some crypto libraries only use a callback, so onComplete is
  1037. * required to use these.)
  1038. * @param {function} onError (optional) If defined, then onComplete must be
  1039. * defined and if there is an exception, then this calls onError(exception)
  1040. * with the exception. If onComplete is defined but onError is undefined, then
  1041. * this will log any thrown exception. (Some crypto libraries only use a
  1042. * callback, so onError is required to be notified of an exception.)
  1043. * @return {Signature} If onComplete is omitted, return the generated Signature
  1044. * object (if target is a Buffer) or the target (if target is Data). Otherwise,
  1045. * if onComplete is supplied then return undefined and use onComplete as described
  1046. * above.
  1047. */
  1048. IdentityManager.prototype.signByCertificate = function
  1049. (target, certificateName, wireFormat, onComplete, onError)
  1050. {
  1051. onError = (typeof wireFormat === "function") ? onComplete : onError;
  1052. onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  1053. wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
  1054. return SyncPromise.complete(onComplete, onError,
  1055. this.signByCertificatePromise
  1056. (target, certificateName, wireFormat, !onComplete));
  1057. };
  1058. /**
  1059. * Append a SignatureInfo to the Interest name, sign the name components and
  1060. * append a final name component with the signature bits.
  1061. * @param {Interest} interest The Interest object to be signed. This appends
  1062. * name components of SignatureInfo and the signature bits.
  1063. * @param {Name} certificateName The certificate name of the key to use for
  1064. * signing.
  1065. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1066. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1067. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  1068. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  1069. * an async Promise.
  1070. * @return {Promise|SyncPromise} A promise that returns the supplied Interest.
  1071. */
  1072. IdentityManager.prototype.signInterestByCertificatePromise = function
  1073. (interest, certificateName, wireFormat, useSync)
  1074. {
  1075. useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
  1076. wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
  1077. var thisManager = this;
  1078. var signature;
  1079. var digestAlgorithm = [0];
  1080. return this.makeSignatureByCertificatePromise
  1081. (certificateName, digestAlgorithm, useSync)
  1082. .then(function(localSignature) {
  1083. signature = localSignature;
  1084. // Append the encoded SignatureInfo.
  1085. interest.getName().append(wireFormat.encodeSignatureInfo(signature));
  1086. // Append an empty signature so that the "signedPortion" is correct.
  1087. interest.getName().append(new Name.Component());
  1088. // Encode once to get the signed portion.
  1089. var encoding = interest.wireEncode(wireFormat);
  1090. var keyName = IdentityManager.certificateNameToPublicKeyName
  1091. (certificateName);
  1092. return thisManager.privateKeyStorage.signPromise
  1093. (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
  1094. })
  1095. .then(function(signatureValue) {
  1096. signature.setSignature(signatureValue);
  1097. // Remove the empty signature and append the real one.
  1098. interest.setName(interest.getName().getPrefix(-1).append
  1099. (wireFormat.encodeSignatureValue(signature)));
  1100. return SyncPromise.resolve(interest);
  1101. });
  1102. };
  1103. /**
  1104. * Append a SignatureInfo to the Interest name, sign the name components and
  1105. * append a final name component with the signature bits.
  1106. * @param {Interest} interest The Interest object to be signed. This appends
  1107. * name components of SignatureInfo and the signature bits.
  1108. * @param {Name} certificateName The certificate name of the key to use for
  1109. * signing.
  1110. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1111. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1112. * @param {function} onComplete (optional) This calls onComplete(interest) with
  1113. * the supplied Interest object which has been modified to set its signature. If
  1114. * omitted, then return when the interest has been signed. (Some crypto
  1115. * libraries only use a callback, so onComplete is required to use these.)
  1116. * @param {function} onError (optional) If defined, then onComplete must be
  1117. * defined and if there is an exception, then this calls onError(exception)
  1118. * with the exception. If onComplete is defined but onError is undefined, then
  1119. * this will log any thrown exception. (Some crypto libraries only use a
  1120. * callback, so onError is required to be notified of an exception.)
  1121. * @return {Signature} If onComplete is omitted, return the interest. Otherwise,
  1122. * if onComplete is supplied then return undefined and use onComplete as
  1123. * described above.
  1124. */
  1125. IdentityManager.prototype.signInterestByCertificate = function
  1126. (interest, certificateName, wireFormat, onComplete, onError)
  1127. {
  1128. onError = (typeof wireFormat === "function") ? onComplete : onError;
  1129. onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  1130. wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
  1131. return SyncPromise.complete(onComplete, onError,
  1132. this.signInterestByCertificatePromise
  1133. (interest, certificateName, wireFormat, !onComplete));
  1134. };
  1135. /**
  1136. * Wire encode the Data object, digest it and set its SignatureInfo to a
  1137. * DigestSha256.
  1138. * @param {Data} data The Data object to be signed. This updates its signature
  1139. * and wireEncoding.
  1140. * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
  1141. * WireFormat.getDefaultWireFormat() if omitted.
  1142. */
  1143. IdentityManager.prototype.signWithSha256 = function(data, wireFormat)
  1144. {
  1145. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  1146. data.setSignature(new DigestSha256Signature());
  1147. // Encode once to get the signed portion.
  1148. var encoding = data.wireEncode(wireFormat);
  1149. // Digest and set the signature.
  1150. var hash = Crypto.createHash('sha256');
  1151. hash.update(encoding.signedBuf());
  1152. data.getSignature().setSignature(new Blob(hash.digest(), false));
  1153. // Encode again to include the signature.
  1154. data.wireEncode(wireFormat);
  1155. };
  1156. /**
  1157. * Append a SignatureInfo for DigestSha256 to the Interest name, digest the
  1158. * name components and append a final name component with the signature bits
  1159. * (which is the digest).
  1160. * @param {Interest} interest The Interest object to be signed. This appends
  1161. * name components of SignatureInfo and the signature bits.
  1162. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1163. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1164. */
  1165. IdentityManager.prototype.signInterestWithSha256 = function(interest, wireFormat)
  1166. {
  1167. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  1168. var signature = new DigestSha256Signature();
  1169. // Append the encoded SignatureInfo.
  1170. interest.getName().append(wireFormat.encodeSignatureInfo(signature));
  1171. // Append an empty signature so that the "signedPortion" is correct.
  1172. interest.getName().append(new Name.Component());
  1173. // Encode once to get the signed portion.
  1174. var encoding = interest.wireEncode(wireFormat);
  1175. // Digest and set the signature.
  1176. var hash = Crypto.createHash('sha256');
  1177. hash.update(encoding.signedBuf());
  1178. signature.setSignature(new Blob(hash.digest(), false));
  1179. // Remove the empty signature and append the real one.
  1180. interest.setName(interest.getName().getPrefix(-1).append
  1181. (wireFormat.encodeSignatureValue(signature)));
  1182. };
  1183. /**
  1184. * Generate a self-signed certificate for a public key.
  1185. * @param {Name} keyName The name of the public key.
  1186. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  1187. * is already fulfilled. If false, this may return a SyncPromise or an async
  1188. * Promise.
  1189. * @return {Promise|SyncPromise} A promise which returns the generated
  1190. * IdentityCertificate.
  1191. */
  1192. IdentityManager.prototype.selfSignPromise = function(keyName, useSync)
  1193. {
  1194. var certificate = new IdentityCertificate();
  1195. var thisManager = this;
  1196. return this.identityStorage.getKeyPromise(keyName, useSync)
  1197. .then(function(keyBlob) {
  1198. var publicKey = new PublicKey(keyBlob);
  1199. var notBefore = new Date().getTime();
  1200. var notAfter = notBefore + 2 * 365 * 24 * 3600 * 1000; // about 2 years
  1201. certificate.setNotBefore(notBefore);
  1202. certificate.setNotAfter(notAfter);
  1203. var certificateName = keyName.getPrefix(-1).append("KEY").append
  1204. (keyName.get(-1)).append("ID-CERT").appendVersion(certificate.getNotBefore());
  1205. certificate.setName(certificateName);
  1206. certificate.setPublicKeyInfo(publicKey);
  1207. certificate.addSubjectDescription(new CertificateSubjectDescription
  1208. ("2.5.4.41", keyName.toUri()));
  1209. certificate.encode();
  1210. return thisManager.signByCertificatePromise
  1211. (certificate, certificate.getName(), useSync);
  1212. })
  1213. };
  1214. /**
  1215. * Generate a self-signed certificate for a public key.
  1216. * @param {Name} keyName The name of the public key.
  1217. * @param {function} onComplete (optional) This calls onComplete(certificate)
  1218. * with the the generated IdentityCertificate. If omitted, the return value is
  1219. * described below. (Some crypto libraries only use a callback, so onComplete is
  1220. * required to use these.)
  1221. * @return {IdentityCertificate} If onComplete is omitted, return the
  1222. * generated certificate. Otherwise, if onComplete is supplied then return
  1223. * undefined and use onComplete as described above.
  1224. * @param {function} onError (optional) If defined, then onComplete must be
  1225. * defined and if there is an exception, then this calls onError(exception)
  1226. * with the exception. If onComplete is defined but onError is undefined, then
  1227. * this will log any thrown exception. (Some crypto libraries only use a
  1228. * callback, so onError is required to be notified of an exception.)
  1229. */
  1230. IdentityManager.prototype.selfSign = function(keyName, onComplete, onError)
  1231. {
  1232. return SyncPromise.complete(onComplete, onError,
  1233. this.selfSignPromise(keyName, !onComplete));
  1234. };
  1235. /**
  1236. * Get the public key name from the full certificate name.
  1237. *
  1238. * @param {Name} certificateName The full certificate name.
  1239. * @return {Name} The related public key name.
  1240. * TODO: Move this to IdentityCertificate
  1241. */
  1242. IdentityManager.certificateNameToPublicKeyName = function(certificateName)
  1243. {
  1244. var i = certificateName.size() - 1;
  1245. var idString = "ID-CERT";
  1246. while (i >= 0) {
  1247. if (certificateName.get(i).toEscapedString() == idString)
  1248. break;
  1249. --i;
  1250. }
  1251. var tmpName = certificateName.getSubName(0, i);
  1252. var keyString = "KEY";
  1253. i = 0;
  1254. while (i < tmpName.size()) {
  1255. if (tmpName.get(i).toEscapedString() == keyString)
  1256. break;
  1257. ++i;
  1258. }
  1259. return tmpName.getSubName(0, i).append(tmpName.getSubName
  1260. (i + 1, tmpName.size() - i - 1));
  1261. };
  1262. /**
  1263. * Return a new Signature object based on the signature algorithm of the public
  1264. * key with keyName (derived from certificateName).
  1265. * @param {Name} certificateName The certificate name.
  1266. * @param {Array} digestAlgorithm Set digestAlgorithm[0] to the signature
  1267. * algorithm's digest algorithm, e.g. DigestAlgorithm.SHA256.
  1268. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  1269. * is already fulfilled. If false, this may return a SyncPromise or an async
  1270. * Promise.
  1271. * @return {Promise|SyncPromise} A promise which returns a new object of the
  1272. * correct subclass of Signature.
  1273. */
  1274. IdentityManager.prototype.makeSignatureByCertificatePromise = function
  1275. (certificateName, digestAlgorithm, useSync)
  1276. {
  1277. var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
  1278. return this.privateKeyStorage.getPublicKeyPromise(keyName, useSync)
  1279. .then(function(publicKey) {
  1280. var keyType = publicKey.getKeyType();
  1281. var signature = null;
  1282. if (keyType == KeyType.RSA) {
  1283. signature = new Sha256WithRsaSignature();
  1284. digestAlgorithm[0] = DigestAlgorithm.SHA256;
  1285. signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
  1286. signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
  1287. }
  1288. else
  1289. throw new SecurityException(new Error("Key type is not recognized"));
  1290. return SyncPromise.resolve(signature);
  1291. });
  1292. };
  1293. /**
  1294. * A private method to generate a pair of keys for the specified identity.
  1295. * @param {Name} identityName The name of the identity.
  1296. * @param {boolean} isKsk true for generating a Key-Signing-Key (KSK), false for
  1297. * a Data-Signing-Key (DSK).
  1298. * @param {KeyParams} params The parameters of the key.
  1299. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  1300. * is already fulfilled. If false, this may return a SyncPromise or an async
  1301. * Promise.
  1302. * @return {Promise|SyncPromise} A promise which returns the generated key name.
  1303. */
  1304. IdentityManager.prototype.generateKeyPairPromise = function
  1305. (identityName, isKsk, params, useSync)
  1306. {
  1307. var keyName;
  1308. var thisManager = this;
  1309. return this.identityStorage.getNewKeyNamePromise(identityName, isKsk, useSync)
  1310. .then(function(localKeyName) {
  1311. keyName = localKeyName;
  1312. return thisManager.privateKeyStorage.generateKeyPairPromise
  1313. (keyName, params, useSync);
  1314. })
  1315. .then(function() {
  1316. return thisManager.privateKeyStorage.getPublicKeyPromise
  1317. (keyName, useSync);
  1318. })
  1319. .then(function(publicKey) {
  1320. return thisManager.identityStorage.addKeyPromise
  1321. (keyName, params.getKeyType(), publicKey.getKeyDer());
  1322. })
  1323. .then(function() {
  1324. return SyncPromise.resolve(keyName);
  1325. });
  1326. };