Source: security/key-chain.js

  1. /**
  2. * Copyright (C) 2014-2018 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. /** @ignore */
  21. var path = require('path'); /** @ignore */
  22. var fs = require('fs'); /** @ignore */
  23. var Crypto = require('../crypto.js'); /** @ignore */
  24. var LOG = require('../log.js').Log.LOG; /** @ignore */
  25. var Name = require('../name.js').Name; /** @ignore */
  26. var Interest = require('../interest.js').Interest; /** @ignore */
  27. var Data = require('../data.js').Data; /** @ignore */
  28. var ContentType = require('../meta-info.js').ContentType; /** @ignore */
  29. var Blob = require('../util/blob.js').Blob; /** @ignore */
  30. var ConfigFile = require('../util/config-file.js').ConfigFile; /** @ignore */
  31. var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
  32. var SecurityException = require('./security-exception.js').SecurityException; /** @ignore */
  33. var RsaKeyParams = require('./key-params.js').RsaKeyParams; /** @ignore */
  34. var BasicIdentityStorage = require('./identity/basic-identity-storage.js').BasicIdentityStorage; /** @ignore */
  35. var IdentityCertificate = require('./certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
  36. var Tpm = require('./tpm/tpm.js').Tpm; /** @ignore */
  37. var TpmBackEndFile = require('./tpm/tpm-back-end-file.js').TpmBackEndFile; /** @ignore */
  38. var TpmBackEndMemory = require('./tpm/tpm-back-end-memory.js').TpmBackEndMemory; /** @ignore */
  39. var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
  40. var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
  41. var IdentityManager = require('./identity/identity-manager.js').IdentityManager; /** @ignore */
  42. var CertificateV2 = require('./v2/certificate-v2.js').CertificateV2; /** @ignore */
  43. var SigningInfo = require('./signing-info.js').SigningInfo; /** @ignore */
  44. var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
  45. var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
  46. var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
  47. var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
  48. var KeyLocator = require('../key-locator.js').KeyLocator; /** @ignore */
  49. var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
  50. var DigestAlgorithm = require('./security-types.js').DigestAlgorithm; /** @ignore */
  51. var KeyType = require('./security-types.js').KeyType; /** @ignore */
  52. var ValidityPeriod = require('./validity-period.js').ValidityPeriod; /** @ignore */
  53. var VerificationHelpers = require('./verification-helpers.js').VerificationHelpers; /** @ignore */
  54. var PublicKey = require('./certificate/public-key.js').PublicKey; /** @ignore */
  55. var NoVerifyPolicyManager = require('./policy/no-verify-policy-manager.js').NoVerifyPolicyManager;
  56. /**
  57. * A KeyChain provides a set of interfaces to the security library such as
  58. * identity management, policy configuration and packet signing and verification.
  59. * Note: This class is an experimental feature. See the API docs for more detail at
  60. * http://named-data.net/doc/ndn-ccl-api/key-chain.html .
  61. *
  62. * There are four forms to create a KeyChain:
  63. * KeyChain(pibLocator, tpmLocator, allowReset = false) - Create a KeyChain to
  64. * use the PIB and TPM defined by the given locators, which creates a security
  65. * v2 KeyChain that uses CertificateV2, Pib, Tpm and Validator (instead of v1
  66. * Certificate, IdentityStorage, PrivateKeyStorage and PolicyManager).
  67. * KeyChain(identityManager = null, policyManager = null) - Create a security v1
  68. * KeyChain to use the optional identityManager and policyManager.
  69. * KeyChain(pibImpl, tpmBackEnd, policyManager) - Create a KeyChain using this
  70. * temporary constructor for the transition to security v2, which creates a
  71. * security v2 KeyChain but still uses the v1 PolicyManager.
  72. * Finally, the default constructor KeyChain() creates a KeyChain with the
  73. * default PIB and TPM, which are platform-dependent and can be overridden
  74. * system-wide or individually by the user. The default constructor creates a
  75. * security v2 KeyChain that uses CertificateV2, Pib, Tpm and Validator.
  76. * However, if the default security v1 database file still exists, and the
  77. * default security v2 database file does not yet exists, then assume that the
  78. * system is running an older NFD and create a security v1 KeyChain with the
  79. * default IdentityManager and a NoVerifyPolicyManager.
  80. * @param {string} pibLocator The PIB locator, e.g., "pib-sqlite3:/example/dir".
  81. * @param {string} tpmLocator The TPM locator, e.g., "tpm-memory:".
  82. * @param {boolean} allowReset (optional) If True, the PIB will be reset when
  83. * the supplied tpmLocator mismatches the one in the PIB. If omitted, don't
  84. * allow reset.
  85. * @param {IdentityManager} identityManager (optional) The identity manager as a
  86. * subclass of IdentityManager. If omitted, use the default IdentityManager
  87. * constructor.
  88. * @param {PolicyManager} policyManager: (optional) The policy manager as a
  89. * subclass of PolicyManager. If omitted, use NoVerifyPolicyManager.
  90. * @param {PibImpl} pibImpl The PibImpl when using the constructor form
  91. * KeyChain(pibImpl, tpmBackEnd, policyManager).
  92. * @param {TpmBackEnd} tpmBackEnd: The TpmBackEnd when using the constructor
  93. * form KeyChain(pibImpl, tpmBackEnd, policyManager).
  94. * @throws SecurityException if this is not in Node.js and this uses the default
  95. * IdentityManager constructor. (See IdentityManager for details.)
  96. * @constructor
  97. */
  98. var KeyChain = function KeyChain(arg1, arg2, arg3)
  99. {
  100. this.identityManager_ = null; // for security v1
  101. this.policyManager_ = null; // for security v1
  102. this.face_ = null; // for security v1
  103. this.pib_ = null;
  104. this.tpm_ = null;
  105. if (arg1 == undefined) {
  106. // The default constructor.
  107. if (!ConfigFile)
  108. // Assume we are in the browser.
  109. throw new SecurityException(new Error
  110. ("KeyChain: The default KeyChain constructor is not supported in the browser"));
  111. if (fs.existsSync(BasicIdentityStorage.getDefaultDatabaseFilePath()) &&
  112. !fs.existsSync(PibSqlite3.getDefaultDatabaseFilePath())) {
  113. // The security v1 SQLite file still exists and the security v2
  114. // does not yet.
  115. arg1 = new IdentityManager();
  116. arg2 = new NoVerifyPolicyManager();
  117. }
  118. else {
  119. // Set the security v2 locators to default empty strings.
  120. arg1 = "";
  121. arg2 = "";
  122. }
  123. }
  124. if (typeof arg1 === 'string') {
  125. var pibLocator = arg1;
  126. var tpmLocator = arg2;
  127. var allowReset = arg3;
  128. if (allowReset == undefined)
  129. allowReset = false;
  130. this.isSecurityV1_ = false;
  131. // PIB locator.
  132. var pibScheme = [null];
  133. var pibLocation = [null];
  134. KeyChain.parseAndCheckPibLocator_(pibLocator, pibScheme, pibLocation);
  135. var canonicalPibLocator = pibScheme[0] + ":" + pibLocation[0];
  136. // Create the PIB and TPM, where Pib.initializePromise_ will complete the
  137. // initialization the first time it is called in an asynchronous context. We
  138. // can't do it here because this constructor cannot perform async operations.
  139. this.pib_ = KeyChain.createPib_(canonicalPibLocator);
  140. this.tpm_ = new Tpm("", "", null);
  141. this.pib_.initializeTpm_ = this.tpm_;
  142. this.pib_.initializePibLocator_ = pibLocator;
  143. this.pib_.initializeTpmLocator_ = tpmLocator;
  144. this.pib_.initializeAllowReset_ = allowReset;
  145. this.tpm_.initializePib_ = this.pib_;
  146. }
  147. else if (arg1 instanceof PibImpl) {
  148. var pibImpl = arg1;
  149. var tpmBackEnd = arg2;
  150. var policyManager = arg3;
  151. this.isSecurityV1_ = false;
  152. this.policyManager_ = policyManager;
  153. this.pib_ = new Pib("", "", pibImpl);
  154. this.tpm_ = new Tpm("", "", tpmBackEnd);
  155. }
  156. else {
  157. var identityManager = arg1;
  158. var policyManager = arg2;
  159. this.isSecurityV1_ = true;
  160. if (identityManager == undefined)
  161. identityManager = new IdentityManager();
  162. if (policyManager == undefined)
  163. policyManager = new NoVerifyPolicyManager();
  164. this.identityManager_ = identityManager;
  165. this.policyManager_ = policyManager;
  166. }
  167. };
  168. exports.KeyChain = KeyChain;
  169. /**
  170. * Create a KeyChain.Error which represents an error in KeyChain processing.
  171. * Call with: throw new KeyChain.Error(new Error("message")).
  172. * @constructor
  173. * @param {Error} error The exception created with new Error.
  174. */
  175. KeyChain.Error = function KeyChainError(error)
  176. {
  177. if (error) {
  178. error.__proto__ = KeyChain.Error.prototype;
  179. return error;
  180. }
  181. };
  182. KeyChain.Error.prototype = new Error();
  183. KeyChain.Error.prototype.name = "KeyChainError";
  184. /**
  185. * @return {Pib}
  186. */
  187. KeyChain.prototype.getPib = function()
  188. {
  189. if (this.isSecurityV1_)
  190. throw new SecurityException(new Error
  191. ("getPib is not supported for security v1"));
  192. return this.pib_;
  193. };
  194. /**
  195. * @return {Tpm}
  196. */
  197. KeyChain.prototype.getTpm = function()
  198. {
  199. if (this.isSecurityV1_)
  200. throw new SecurityException(new Error
  201. ("getTpm is not supported for security v1"));
  202. return this.tpm_;
  203. };
  204. /**
  205. * Get the flag set by the constructor if this is a security v1 or v2 KeyChain.
  206. * @return (boolean} True if this is a security v1 KeyChain, false if this is a
  207. * security v2 KeyChain.
  208. */
  209. KeyChain.prototype.getIsSecurityV1 = function() { return this.isSecurityV1_; };
  210. // Identity management
  211. /**
  212. * Create a security V2 identity for identityName. This method will check if the
  213. * identity exists in PIB and whether the identity has a default key and default
  214. * certificate. If the identity does not exist, this method will create the
  215. * identity in PIB. If the identity's default key does not exist, this method
  216. * will create a key pair and set it as the identity's default key. If the key's
  217. * default certificate is missing, this method will create a self-signed
  218. * certificate for the key. If identityName did not exist and no default
  219. * identity was selected before, the created identity will be set as the default
  220. * identity.
  221. * @param {Name} identityName The name of the identity.
  222. * @param {KeyParams} params (optional) The key parameters if a key needs to be
  223. * generated for the identity. If omitted, use getDefaultKeyParams().
  224. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  225. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  226. * an async Promise.
  227. * @return {Promise|SyncPromise} A promise that returns the created PibIdentity
  228. * instance.
  229. */
  230. KeyChain.prototype.createIdentityV2Promise = function
  231. (identityName, params, useSync)
  232. {
  233. useSync = (typeof params === "boolean") ? params : useSync;
  234. params = (typeof params === "boolean" || !params) ? undefined : params;
  235. if (params == undefined)
  236. params = KeyChain.getDefaultKeyParams();
  237. var thisKeyChain = this;
  238. var id;
  239. return this.pib_.addIdentityPromise_(identityName, useSync)
  240. .then(function(localId) {
  241. id = localId;
  242. return id.getDefaultKeyPromise(useSync)
  243. .catch(function(err) {
  244. if (err instanceof Pib.Error)
  245. return thisKeyChain.createKeyPromise(id, params, useSync);
  246. else
  247. return SyncPromise.reject(err);
  248. });
  249. })
  250. .then(function(key) {
  251. return key.getDefaultCertificatePromise(useSync)
  252. .catch(function(err) {
  253. if (err instanceof Pib.Error) {
  254. if (LOG > 2)
  255. console.log("No default cert for " + key.getName() +
  256. ", requesting self-signing")
  257. return thisKeyChain.selfSignPromise(key, useSync);
  258. }
  259. else
  260. return SyncPromise.reject(err);
  261. });
  262. })
  263. .then(function() {
  264. return SyncPromise.resolve(id);
  265. });
  266. };
  267. /**
  268. * Create a security V2 identity for identityName. This method will check if the
  269. * identity exists in PIB and whether the identity has a default key and default
  270. * certificate. If the identity does not exist, this method will create the
  271. * identity in PIB. If the identity's default key does not exist, this method
  272. * will create a key pair and set it as the identity's default key. If the key's
  273. * default certificate is missing, this method will create a self-signed
  274. * certificate for the key. If identityName did not exist and no default
  275. * identity was selected before, the created identity will be set as the default
  276. * identity.
  277. * @param {Name} identityName The name of the identity.
  278. * @param {KeyParams} params (optional) The key parameters if a key needs to be
  279. * generated for the identity. If omitted, use getDefaultKeyParams().
  280. * @param {function} onComplete (optional) This calls
  281. * onComplete(identity) with the created PibIdentity instance. If omitted, the
  282. * return value is described below. (Some database libraries only use a callback,
  283. * so onComplete is required to use these.)
  284. * NOTE: The library will log any exceptions thrown by this callback, but for
  285. * better error handling the callback should catch and properly handle any
  286. * exceptions.
  287. * @param {function} onError (optional) If defined, then onComplete must be
  288. * defined and if there is an exception, then this calls onError(exception)
  289. * with the exception. If onComplete is defined but onError is undefined, then
  290. * this will log any thrown exception. (Some database libraries only use a
  291. * callback, so onError is required to be notified of an exception.)
  292. * NOTE: The library will log any exceptions thrown by this callback, but for
  293. * better error handling the callback should catch and properly handle any
  294. * exceptions.
  295. * @return {PibIdentity} If onComplete is omitted, return the created
  296. * PibIdentity instance. Otherwise, if onComplete is supplied then return
  297. * undefined and use onComplete as described above.
  298. */
  299. KeyChain.prototype.createIdentityV2 = function
  300. (identityName, params, onComplete, onError)
  301. {
  302. onError = (typeof params === "function") ? onComplete : onError;
  303. onComplete = (typeof params === "function") ? params : onComplete;
  304. params = (typeof params === "function" || !params) ? undefined : params;
  305. return SyncPromise.complete(onComplete, onError,
  306. this.createIdentityV2Promise(identityName, params, !onComplete));
  307. };
  308. /**
  309. * This method has two forms:
  310. * deleteIdentity(identity, useSync) - Delete the PibIdentity identity. After this
  311. * operation, the identity is invalid.
  312. * deleteIdentity(identityName, useSync) - Delete the identity from the public and
  313. * private key storage. If the identity to be deleted is the current default s
  314. * system default, the method will not delete the identity and will return
  315. * immediately.
  316. * @param {PibIdentity} identity The identity to delete.
  317. * @param {Name} identityName The name of the identity to delete.
  318. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  319. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  320. * an async Promise.
  321. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  322. * complete.
  323. */
  324. KeyChain.prototype.deleteIdentityPromise = function(identity, useSync)
  325. {
  326. var thisKeyChain = this;
  327. if (identity instanceof Name) {
  328. if (!this.isSecurityV1_) {
  329. return this.pib_.getIdentityPromise(identity, useSync)
  330. .then(function(pibIdentity) {
  331. return thisKeyChain.deleteIdentityPromise(pibIdentity, useSync);
  332. })
  333. .catch(function(err) {
  334. // Ignore errors.
  335. return SyncPromise.resolve();
  336. });
  337. return;
  338. }
  339. else
  340. return SyncPromise.reject(new KeyChain.Error(new Error
  341. ("deleteIdentityPromise is not supported for security v1. Use deleteIdentity.")));
  342. }
  343. var identityName = identity.getName();
  344. var keyNames = identity.getKeys_().getKeyNames();
  345. // Make a recursive function to do the loop.
  346. function deleteKeys(i) {
  347. if (i >= keyNames.length)
  348. // Done.
  349. return SyncPromise.resolve();
  350. return thisKeyChain.tpm_.deleteKeyPromise_(keyNames[i], useSync)
  351. .then(function() {
  352. // Recurse to the next iteration.
  353. return deleteKeys(i + 1);
  354. });
  355. }
  356. return deleteKeys(0)
  357. .then(function() {
  358. return thisKeyChain.pib_.removeIdentityPromise_(identityName, useSync);
  359. // TODO: Mark identity as invalid.
  360. });
  361. };
  362. /**
  363. * This method has two forms:
  364. * deleteIdentity(identity, onComplete, onError) - Delete the PibIdentity
  365. * identity (optionally using onComplete and onError callbacks). After this
  366. * operation, the identity is invalid.
  367. * deleteIdentity(identityName, onComplete, onError) - Delete the identity from
  368. * the public and private key storage (optionally using onComplete and onError
  369. * callbacks). If the identity to be deleted is the current default system
  370. * default, the method will not delete the identity and will return immediately.
  371. * @param {PibIdentity} identity The identity to delete.
  372. * @param {Name} identityName The name of the identity to delete.
  373. * @param {function} onComplete (optional) This calls onComplete() when the
  374. * operation is complete. If omitted, do not use it. (Some database libraries
  375. * only use a callback, so onComplete is required to use these.)
  376. * NOTE: The library will log any exceptions thrown by this callback, but for
  377. * better error handling the callback should catch and properly handle any
  378. * exceptions.
  379. * @param {function} onError (optional) If defined, then onComplete must be
  380. * defined and if there is an exception, then this calls onError(exception)
  381. * with the exception. If onComplete is defined but onError is undefined, then
  382. * this will log any thrown exception. (Some database libraries only use a
  383. * callback, so onError is required to be notified of an exception.)
  384. * NOTE: The library will log any exceptions thrown by this callback, but for
  385. * better error handling the callback should catch and properly handle any
  386. * exceptions.
  387. */
  388. KeyChain.prototype.deleteIdentity = function(identity, onComplete, onError)
  389. {
  390. if (identity instanceof Name && this.isSecurityV1_) {
  391. this.identityManager_.deleteIdentity(identity, onComplete, onError);
  392. return;
  393. }
  394. return SyncPromise.complete(onComplete, onError,
  395. this.deleteIdentityPromise(identity, !onComplete));
  396. };
  397. /**
  398. * Set the identity as the default identity.
  399. * @param {PibIdentity} identity The identity to make the default.
  400. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  401. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  402. * an async Promise.
  403. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  404. * complete.
  405. */
  406. KeyChain.prototype.setDefaultIdentityPromise = function(identity, useSync)
  407. {
  408. return this.pib_.setDefaultIdentityPromise_(identity.getName(), useSync);
  409. };
  410. /**
  411. * Set the identity as the default identity.
  412. * @param {PibIdentity} identity The identity to make the default.
  413. * @param {function} onComplete (optional) This calls onComplete() when the
  414. * operation is complete. If omitted, do not use it. (Some database libraries
  415. * only use a callback, so onComplete is required to use these.)
  416. * NOTE: The library will log any exceptions thrown by this callback, but for
  417. * better error handling the callback should catch and properly handle any
  418. * exceptions.
  419. * @param {function} onError (optional) If defined, then onComplete must be
  420. * defined and if there is an exception, then this calls onError(exception)
  421. * with the exception. If onComplete is defined but onError is undefined, then
  422. * this will log any thrown exception. (Some database libraries only use a
  423. * callback, so onError is required to be notified of an exception.)
  424. * NOTE: The library will log any exceptions thrown by this callback, but for
  425. * better error handling the callback should catch and properly handle any
  426. * exceptions.
  427. */
  428. KeyChain.prototype.setDefaultIdentity = function(identity, onComplete, onError)
  429. {
  430. return SyncPromise.complete(onComplete, onError,
  431. this.setDefaultIdentityPromise(identity, !onComplete));
  432. };
  433. // Key management
  434. /**
  435. * Create a key for the identity according to params. If the identity had no
  436. * default key selected, the created key will be set as the default for this
  437. * identity. This method will also create a self-signed certificate for the
  438. * created key.
  439. * @param {PibIdentity} identity A valid PibIdentity object.
  440. * @param {KeyParams} params (optional) The key parameters if a key needs to be
  441. * generated for the identity. If omitted, use getDefaultKeyParams().
  442. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  443. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  444. * an async Promise.
  445. * @return {Promise|SyncPromise} A promise that returns the new PibKey.
  446. */
  447. KeyChain.prototype.createKeyPromise = function(identity, params, useSync)
  448. {
  449. useSync = (typeof params === "boolean") ? params : useSync;
  450. params = (typeof params === "boolean" || !params) ? undefined : params;
  451. if (params == undefined)
  452. params = KeyChain.getDefaultKeyParams();
  453. var thisKeyChain = this;
  454. var key, keyName;
  455. // Create the key in the TPM.
  456. return this.tpm_.createKeyPromise_(identity.getName(), params, useSync)
  457. .then(function(localKeyName) {
  458. keyName = localKeyName;
  459. // Set up the key info in the PIB.
  460. return thisKeyChain.tpm_.getPublicKeyPromise(keyName, useSync);
  461. })
  462. .then(function(publicKey) {
  463. return identity.addKeyPromise_(publicKey.buf(), keyName, useSync);
  464. })
  465. .then(function(localKey) {
  466. key = localKey;
  467. if (LOG > 2)
  468. console.log
  469. ("Requesting self-signing for newly created key " + key.getName().toUri());
  470. return thisKeyChain.selfSignPromise(key, useSync);
  471. })
  472. .then(function() {
  473. return SyncPromise.resolve(key);
  474. });
  475. };
  476. /**
  477. * Create a key for the identity according to params. If the identity had no
  478. * default key selected, the created key will be set as the default for this
  479. * identity. This method will also create a self-signed certificate for the
  480. * created key.
  481. * @param {PibIdentity} identity A valid PibIdentity object.
  482. * @param {KeyParams} params (optional) The key parameters if a key needs to be
  483. * generated for the identity. If omitted, use getDefaultKeyParams().
  484. * @param {function} onComplete (optional) This calls onComplete(key) with the
  485. * new PibKey. If omitted, the return value is described below. (Some database
  486. * libraries only use a callback, so onComplete is required to use these.)
  487. * NOTE: The library will log any exceptions thrown by this callback, but for
  488. * better error handling the callback should catch and properly handle any
  489. * exceptions.
  490. * @param {function} onError (optional) If defined, then onComplete must be
  491. * defined and if there is an exception, then this calls onError(exception)
  492. * with the exception. If onComplete is defined but onError is undefined, then
  493. * this will log any thrown exception. (Some database libraries only use a
  494. * callback, so onError is required to be notified of an exception.)
  495. * NOTE: The library will log any exceptions thrown by this callback, but for
  496. * better error handling the callback should catch and properly handle any
  497. * exceptions.
  498. * @return {PibKey} If onComplete is omitted, return the new PibKey. Otherwise,
  499. * if onComplete is supplied then return undefined and use onComplete as
  500. * described above.
  501. */
  502. KeyChain.prototype.createKey = function(identity, params, onComplete, onError)
  503. {
  504. onError = (typeof params === "function") ? onComplete : onError;
  505. onComplete = (typeof params === "function") ? params : onComplete;
  506. params = (typeof params === "function" || !params) ? undefined : params;
  507. return SyncPromise.complete(onComplete, onError,
  508. this.createKeyPromise(identity, params, !onComplete));
  509. };
  510. /**
  511. * Delete the given key of the given identity. The key becomes invalid.
  512. * @param {PibIdentity} identity A valid PibIdentity object.
  513. * @param {PibKey} key The key to delete.
  514. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  515. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  516. * an async Promise.
  517. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  518. * complete, or a promise rejected with Error if the key does not belong to the
  519. * identity.
  520. */
  521. KeyChain.prototype.deleteKeyPromise = function(identity, key, useSync)
  522. {
  523. var keyName = key.getName();
  524. if (!identity.getName().equals(key.getIdentityName()))
  525. return SyncPromise.reject(new Error
  526. ("Identity `" + identity.getName().toUri() + "` does not match key `" +
  527. keyName.toUri() + "`"));
  528. var thisKeyChain = this;
  529. return identity.removeKeyPromise_(keyName, useSync)
  530. .then(function() {
  531. return thisKeyChain.tpm_.deleteKeyPromise_(keyName, useSync);
  532. });
  533. };
  534. /**
  535. * Delete the given key of the given identity. The key becomes invalid.
  536. * @param {PibIdentity} identity A valid PibIdentity object.
  537. * @param {PibKey} key The key to delete.
  538. * @param {function} onComplete (optional) This calls onComplete() when the
  539. * operation is complete. If omitted, do not use it. (Some database libraries
  540. * only use a callback, so onComplete is required to use these.)
  541. * NOTE: The library will log any exceptions thrown by this callback, but for
  542. * better error handling the callback should catch and properly handle any
  543. * exceptions.
  544. * @param {function} onError (optional) If defined, then onComplete must be
  545. * defined and if there is an exception, then this calls onError(exception)
  546. * with the exception. If onComplete is defined but onError is undefined, then
  547. * this will log any thrown exception. (Some database libraries only use a
  548. * callback, so onError is required to be notified of an exception.)
  549. * NOTE: The library will log any exceptions thrown by this callback, but for
  550. * better error handling the callback should catch and properly handle any
  551. * exceptions.
  552. * @throws Error if the key does not belong to the identity. However, if
  553. * onComplete and onError are defined, then if there is an exception return
  554. * undefined and call onError(exception).
  555. */
  556. KeyChain.prototype.deleteKey = function(identity, key, onComplete, onError)
  557. {
  558. return SyncPromise.complete(onComplete, onError,
  559. this.deleteKeyPromise(identity, key, !onComplete));
  560. };
  561. /**
  562. * Set the key as the default key of identity.
  563. * @param {type} identity A valid PibIdentity object.
  564. * @param {type} key The key to become the default.
  565. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  566. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  567. * an async Promise.
  568. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  569. * complete, or a promise rejected with Error if the key does not belong to the
  570. * identity.
  571. */
  572. KeyChain.prototype.setDefaultKeyPromise = function(identity, key, useSync)
  573. {
  574. if (!identity.getName().equals(key.getIdentityName()))
  575. return SyncPromise.reject(new Error
  576. ("Identity `" + identity.getName().toUri() + "` does not match key `" +
  577. key.getName().toUri() + "`"));
  578. return identity.setDefaultKeyPromise_(key.getName(), useSync);
  579. };
  580. /**
  581. * Set the key as the default key of identity.
  582. * @param {type} identity A valid PibIdentity object.
  583. * @param {type} key The key to become the default.
  584. * @param {function} onComplete (optional) This calls onComplete() when the
  585. * operation is complete. If omitted, do not use it. (Some database libraries
  586. * only use a callback, so onComplete is required to use these.)
  587. * NOTE: The library will log any exceptions thrown by this callback, but for
  588. * better error handling the callback should catch and properly handle any
  589. * exceptions.
  590. * @param {function} onError (optional) If defined, then onComplete must be
  591. * defined and if there is an exception, then this calls onError(exception)
  592. * with the exception. If onComplete is defined but onError is undefined, then
  593. * this will log any thrown exception. (Some database libraries only use a
  594. * callback, so onError is required to be notified of an exception.)
  595. * NOTE: The library will log any exceptions thrown by this callback, but for
  596. * better error handling the callback should catch and properly handle any
  597. * exceptions.
  598. * @throws Error if the key does not belong to the identity. However, if
  599. * onComplete and onError are defined, then if there is an exception return
  600. * undefined and call onError(exception).
  601. */
  602. KeyChain.prototype.setDefaultKey = function(identity, key, onComplete, onError)
  603. {
  604. return SyncPromise.complete(onComplete, onError,
  605. this.setDefaultKeyPromise(identity, key, !onComplete));
  606. };
  607. // Certificate management
  608. /**
  609. * Add a certificate for the key. If the key had no default certificate
  610. * selected, the added certificate will be set as the default certificate for
  611. * this key.
  612. * @param {PibKey} key A valid PibKey object.
  613. * @param {CertificateV2} certificate The certificate to add. This copies the
  614. * object.
  615. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  616. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  617. * an async Promise.
  618. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  619. * complete, or a promise rejected with Error if the key does not match the
  620. * certificate.
  621. */
  622. KeyChain.prototype.addCertificatePromise = function(key, certificate, useSync)
  623. {
  624. if (!key.getName().equals(certificate.getKeyName()) ||
  625. !certificate.getContent().equals(key.getPublicKey()))
  626. return SyncPromise.reject(new Error
  627. ("Key `" + key.getName().toUri() + "` does not match certificate `" +
  628. certificate.getKeyName().toUri() + "`"));
  629. return key.addCertificatePromise_(certificate, useSync);
  630. };
  631. /**
  632. * Add a certificate for the key. If the key had no default certificate
  633. * selected, the added certificate will be set as the default certificate for
  634. * this key.
  635. * @param {PibKey} key A valid PibKey object.
  636. * @param {CertificateV2} certificate The certificate to add. This copies the
  637. * object.
  638. * @param {function} onComplete (optional) This calls onComplete() when the
  639. * operation is complete. If omitted, do not use it. (Some database libraries
  640. * only use a callback, so onComplete is required to use these.)
  641. * NOTE: The library will log any exceptions thrown by this callback, but for
  642. * better error handling the callback should catch and properly handle any
  643. * exceptions.
  644. * @param {function} onError (optional) If defined, then onComplete must be
  645. * defined and if there is an exception, then this calls onError(exception)
  646. * with the exception. If onComplete is defined but onError is undefined, then
  647. * this will log any thrown exception. (Some database libraries only use a
  648. * callback, so onError is required to be notified of an exception.)
  649. * NOTE: The library will log any exceptions thrown by this callback, but for
  650. * better error handling the callback should catch and properly handle any
  651. * exceptions.
  652. * @throws Error if the key does not match the certificate. However, if
  653. * onComplete and onError are defined, then if there is an exception return
  654. * undefined and call onError(exception).
  655. */
  656. KeyChain.prototype.addCertificate = function
  657. (key, certificate, onComplete, onError)
  658. {
  659. return SyncPromise.complete(onComplete, onError,
  660. this.addCertificatePromise(key, certificate, !onComplete));
  661. };
  662. /**
  663. * Delete the certificate with the given name from the given key. If the
  664. * certificate does not exist, this does nothing.
  665. * @param {PibKey} key A valid PibKey object.
  666. * @param {Name} certificateName The name of the certificate to delete.
  667. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  668. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  669. * an async Promise.
  670. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  671. * complete, or a promise rejected with Error if certificateName does not follow
  672. * certificate naming conventions.
  673. */
  674. KeyChain.prototype.deleteCertificatePromise = function
  675. (key, certificateName, useSync)
  676. {
  677. if (!CertificateV2.isValidName(certificateName))
  678. return SyncPromise.reject(new Error
  679. ("Wrong certificate name `" + certificateName.toUri() + "`"));
  680. return key.removeCertificatePromise_(certificateName, useSync);
  681. };
  682. /**
  683. * Delete the certificate with the given name from the given key. If the
  684. * certificate does not exist, this does nothing.
  685. * @param {PibKey} key A valid PibKey object.
  686. * @param {Name} certificateName The name of the certificate to delete.
  687. * @param {function} onComplete (optional) This calls onComplete() when the
  688. * operation is complete. If omitted, do not use it. (Some database libraries
  689. * only use a callback, so onComplete is required to use these.)
  690. * NOTE: The library will log any exceptions thrown by this callback, but for
  691. * better error handling the callback should catch and properly handle any
  692. * exceptions.
  693. * @param {function} onError (optional) If defined, then onComplete must be
  694. * defined and if there is an exception, then this calls onError(exception)
  695. * with the exception. If onComplete is defined but onError is undefined, then
  696. * this will log any thrown exception. (Some database libraries only use a
  697. * callback, so onError is required to be notified of an exception.)
  698. * NOTE: The library will log any exceptions thrown by this callback, but for
  699. * better error handling the callback should catch and properly handle any
  700. * exceptions.
  701. * @throws Error if certificateName does not follow certificate naming
  702. * conventions. However, if onComplete and onError are defined, then if there is
  703. * an exception return undefined and call onError(exception).
  704. */
  705. KeyChain.prototype.deleteCertificate = function
  706. (key, certificateName, onComplete, onError)
  707. {
  708. return SyncPromise.complete(onComplete, onError,
  709. this.deleteCertificatePromise(key, certificateName, !onComplete));
  710. };
  711. /**
  712. * Set the certificate as the default certificate of the key. The certificate
  713. * will be added to the key, potentially overriding an existing certificate if
  714. * it has the same name (without considering implicit digest).
  715. * @param {PibKey} key A valid PibKey object.
  716. * @param {CertificateV2} certificate The certificate to become the default.
  717. * This copies the object.
  718. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  719. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  720. * an async Promise.
  721. * @return {Promise|SyncPromise} A promise that fulfills when the operation is
  722. * complete.
  723. */
  724. KeyChain.prototype.setDefaultCertificatePromise = function
  725. (key, certificate, useSync)
  726. {
  727. // This replaces the certificate it it exists.
  728. return this.addCertificatePromise(key, certificate, useSync)
  729. .then(function() {
  730. return key.setDefaultCertificatePromise_(certificate.getName(), useSync);
  731. });
  732. };
  733. /**
  734. * Set the certificate as the default certificate of the key. The certificate
  735. * will be added to the key, potentially overriding an existing certificate if
  736. * it has the same name (without considering implicit digest).
  737. * @param {PibKey} key A valid PibKey object.
  738. * @param {CertificateV2} certificate The certificate to become the default.
  739. * This copies the object.
  740. * @param {function} onComplete (optional) This calls onComplete() when the
  741. * operation is complete. If omitted, do not use it. (Some database libraries
  742. * only use a callback, so onComplete is required to use these.)
  743. * NOTE: The library will log any exceptions thrown by this callback, but for
  744. * better error handling the callback should catch and properly handle any
  745. * exceptions.
  746. * @param {function} onError (optional) If defined, then onComplete must be
  747. * defined and if there is an exception, then this calls onError(exception)
  748. * with the exception. If onComplete is defined but onError is undefined, then
  749. * this will log any thrown exception. (Some database libraries only use a
  750. * callback, so onError is required to be notified of an exception.)
  751. * NOTE: The library will log any exceptions thrown by this callback, but for
  752. * better error handling the callback should catch and properly handle any
  753. * exceptions.
  754. */
  755. KeyChain.prototype.setDefaultCertificate = function
  756. (key, certificate, onComplete, onError)
  757. {
  758. return SyncPromise.complete(onComplete, onError,
  759. this.setDefaultCertificatePromise(key, certificate, !onComplete));
  760. };
  761. // Signing
  762. /**
  763. * Sign the target. If it is a Data or Interest object, set its signature. If it
  764. * is a Buffer, produce a Signature object.
  765. * @param {Data|Interest|Buffer} target If this is a Data object, wire encode
  766. * for signing, replace its Signature object based on the type of key and other
  767. * info in the SigningInfo params or default identity, and update the
  768. * wireEncoding. If this is an Interest object, wire encode for signing, append
  769. * a SignatureInfo to the Interest name, sign the name components and append a
  770. * final name component with the signature bits. If it is a buffer, sign it and
  771. * return a Signature object.
  772. * @param {SigningInfo|Name} paramsOrCertificateName (optional) If a SigningInfo,
  773. * it is the signing parameters. If a Name, it is the certificate name of the
  774. * key to use for signing. If omitted and this is a security v1 KeyChain then
  775. * use the IdentityManager to get the default identity. Otherwise, use the PIB
  776. * to get the default key of the default identity.
  777. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  778. * the input. If omitted, use WireFormat getDefaultWireFormat().
  779. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  780. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  781. * an async Promise.
  782. * @return {Promise|SyncPromise} A promise that returns the target (if target is
  783. * Data or Interest), or returns the generated Signature object (if target is a
  784. * Buffer).
  785. */
  786. KeyChain.prototype.signPromise = function
  787. (target, paramsOrCertificateName, wireFormat, useSync)
  788. {
  789. var arg2 = paramsOrCertificateName;
  790. var arg3 = wireFormat;
  791. var arg4 = useSync;
  792. // arg2, arg3, arg4
  793. // paramsOrCertificateName, wireFormat, useSync
  794. // paramsOrCertificateName, wireFormat, null
  795. // paramsOrCertificateName, useSync, null
  796. // paramsOrCertificateName, null, null
  797. // wireFormat, useSync, null
  798. // wireFormat, null, null
  799. // useSync, null, null
  800. // null, null, null
  801. if (arg2 instanceof SigningInfo || arg2 instanceof Name)
  802. paramsOrCertificateName = arg2;
  803. else
  804. paramsOrCertificateName = undefined;
  805. if (arg2 instanceof WireFormat)
  806. wireFormat = arg2;
  807. else if (arg3 instanceof WireFormat)
  808. wireFormat = arg3;
  809. else
  810. wireFormat = undefined;
  811. if (typeof arg2 === "boolean")
  812. useSync = arg2;
  813. else if (typeof arg3 === "boolean")
  814. useSync = arg3;
  815. else if (typeof arg4 === "boolean")
  816. useSync = arg4;
  817. else
  818. useSync = false;
  819. if (wireFormat == undefined)
  820. wireFormat = WireFormat.getDefaultWireFormat();
  821. var thisKeyChain = this;
  822. return SyncPromise.resolve()
  823. .then(function() {
  824. if (paramsOrCertificateName == undefined) {
  825. // Convert sign(target) into sign(target, paramsOrCertificateName)
  826. if (thisKeyChain.isSecurityV1_) {
  827. return thisKeyChain.prepareDefaultCertificateNamePromise_(useSync)
  828. .then(function(name) {
  829. paramsOrCertificateName = name;
  830. return SyncPromise.resolve();
  831. });
  832. }
  833. else {
  834. paramsOrCertificateName = KeyChain.defaultSigningInfo_;
  835. return SyncPromise.resolve();
  836. }
  837. }
  838. else
  839. return SyncPromise.resolve();
  840. })
  841. .then(function() {
  842. if (paramsOrCertificateName instanceof Name) {
  843. var certificateName = paramsOrCertificateName;
  844. if (!thisKeyChain.isSecurityV1_) {
  845. // Make and use a SigningInfo for backwards compatibility.
  846. if (!((target instanceof Interest) || (target instanceof Data)))
  847. return SyncPromise.reject(new SecurityException(new Error
  848. ("sign(buffer, certificateName) is not supported for security v2. Use sign with SigningInfo.")));
  849. var signingInfo = new SigningInfo();
  850. signingInfo.setSigningCertificateName(certificateName);
  851. return thisKeyChain.signPromise(target, signingInfo, wireFormat, useSync)
  852. .catch(function(err) {
  853. return SyncPromise.reject(new SecurityException(new Error
  854. ("Error in sign: " + err)));
  855. });
  856. }
  857. else {
  858. if (target instanceof Interest)
  859. return thisKeyChain.identityManager_.signInterestByCertificatePromise
  860. (target, certificateName, wireFormat, useSync);
  861. else if (target instanceof Data)
  862. return thisKeyChain.identityManager_.signByCertificatePromise
  863. (target, certificateName, wireFormat, useSync);
  864. else
  865. return thisKeyChain.identityManager_.signByCertificatePromise
  866. (target, certificateName, useSync);
  867. }
  868. }
  869. var params = paramsOrCertificateName;
  870. if (target instanceof Data) {
  871. var data = target;
  872. var keyName = [null];
  873. return thisKeyChain.prepareSignatureInfoPromise_(params, keyName, useSync)
  874. .then(function(signatureInfo) {
  875. data.setSignature(signatureInfo);
  876. // Encode once to get the signed portion.
  877. var encoding = data.wireEncode(wireFormat);
  878. return thisKeyChain.signBufferPromise_
  879. (encoding.signedBuf(), keyName[0], params.getDigestAlgorithm(), useSync);
  880. })
  881. .then(function(signatureBytes) {
  882. data.getSignature().setSignature(signatureBytes);
  883. // Encode again to include the signature.
  884. data.wireEncode(wireFormat);
  885. return SyncPromise.resolve(data);
  886. });
  887. }
  888. else if (target instanceof Interest) {
  889. var interest = target;
  890. var signatureInfo;
  891. var keyName = [null];
  892. return thisKeyChain.prepareSignatureInfoPromise_(params, keyName, useSync)
  893. .then(function(localSignatureInfo) {
  894. signatureInfo = localSignatureInfo;
  895. // Append the encoded SignatureInfo.
  896. interest.getName().append(wireFormat.encodeSignatureInfo(signatureInfo));
  897. // Append an empty signature so that the "signedPortion" is correct.
  898. interest.getName().append(new Name.Component());
  899. // Encode once to get the signed portion, and sign.
  900. var encoding = interest.wireEncode(wireFormat);
  901. return thisKeyChain.signBufferPromise_
  902. (encoding.signedBuf(), keyName[0], params.getDigestAlgorithm(), useSync);
  903. })
  904. .then(function(signatureBytes) {
  905. signatureInfo.setSignature(signatureBytes);
  906. // Remove the empty signature and append the real one.
  907. interest.setName(interest.getName().getPrefix(-1).append
  908. (wireFormat.encodeSignatureValue(signatureInfo)));
  909. return SyncPromise.resolve(interest);
  910. });
  911. }
  912. else {
  913. var buffer = target;
  914. var keyName = [null];
  915. return thisKeyChain.prepareSignatureInfoPromise_(params, keyName, useSync)
  916. .then(function(signatureInfo) {
  917. return thisKeyChain.signBufferPromise_
  918. (buffer, keyName[0], params.getDigestAlgorithm(), useSync);
  919. });
  920. }
  921. });
  922. };
  923. /**
  924. * Sign the target. If it is a Data or Interest object, set its signature. If it
  925. * is a Buffer, produce a Signature object.
  926. * @param {Data|Interest|Buffer} target If this is a Data object, wire encode
  927. * for signing, replace its Signature object based on the type of key and other
  928. * info in the SigningInfo params or default identity, and update the
  929. * wireEncoding. If this is an Interest object, wire encode for signing, append
  930. * a SignatureInfo to the Interest name, sign the name components and append a
  931. * final name component with the signature bits. If it is a buffer, sign it and
  932. * return a Signature object.
  933. * @param {SigningInfo|Name} paramsOrCertificateName (optional) If a SigningInfo,
  934. * it is the signing parameters. If a Name, it is the certificate name of the
  935. * key to use for signing. If omitted and this is a security v1 KeyChain then
  936. * use the IdentityManager to get the default identity. Otherwise, use the PIB
  937. * to get the default key of the default identity.
  938. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  939. * the input. If omitted, use WireFormat getDefaultWireFormat().
  940. * @param {function} onComplete (optional) If target is a Data object, this calls
  941. * onComplete(data) with the supplied Data object which has been modified to set
  942. * its signature. If target is an Interest object, this calls
  943. * onComplete(interest) with the supplied Interest object which has been
  944. * modified to set its signature. If target is a Buffer, this calls
  945. * onComplete(signature) where signature is the produced Signature object. If
  946. * omitted, the return value is described below. (Some crypto libraries only use
  947. * a callback, so onComplete is required to use these.)
  948. * NOTE: The library will log any exceptions thrown by this callback, but for
  949. * better error handling the callback should catch and properly handle any
  950. * exceptions.
  951. * @param {function} onError (optional) If defined, then onComplete must be
  952. * defined and if there is an exception, then this calls onError(exception)
  953. * with the exception. If onComplete is defined but onError is undefined, then
  954. * this will log any thrown exception. (Some database libraries only use a
  955. * callback, so onError is required to be notified of an exception.)
  956. * NOTE: The library will log any exceptions thrown by this callback, but for
  957. * better error handling the callback should catch and properly handle any
  958. * exceptions.
  959. * @return {Signature} If onComplete is omitted, return the generated Signature
  960. * object (if target is a Buffer) or the target (if target is Data or Interest).
  961. * Otherwise, if onComplete is supplied then return undefined and use onComplete as
  962. * described above.
  963. */
  964. KeyChain.prototype.sign = function
  965. (target, paramsOrCertificateName, wireFormat, onComplete, onError)
  966. {
  967. var arg2 = paramsOrCertificateName;
  968. var arg3 = wireFormat;
  969. var arg4 = onComplete;
  970. var arg5 = onError;
  971. // arg2, arg3, arg4, arg5
  972. // paramsOrCertificateName, wireFormat, onComplete, onError
  973. // paramsOrCertificateName, wireFormat, null, null
  974. // paramsOrCertificateName, onComplete, onError, null
  975. // paramsOrCertificateName, null, null, null
  976. // wireFormat, onComplete, onError, null
  977. // wireFormat, null, null, null
  978. // onComplete, onError, null, null
  979. // null, null, null, null
  980. if (arg2 instanceof SigningInfo || arg2 instanceof Name)
  981. paramsOrCertificateName = arg2;
  982. else
  983. paramsOrCertificateName = null;
  984. if (arg2 instanceof WireFormat)
  985. wireFormat = arg2;
  986. else if (arg3 instanceof WireFormat)
  987. wireFormat = arg3;
  988. else
  989. wireFormat = null;
  990. if (typeof arg2 === "function") {
  991. onComplete = arg2;
  992. onError = arg3;
  993. }
  994. else if (typeof arg3 === "function") {
  995. onComplete = arg3;
  996. onError = arg4;
  997. }
  998. else if (typeof arg4 === "function") {
  999. onComplete = arg4;
  1000. onError = arg5;
  1001. }
  1002. else {
  1003. onComplete = null;
  1004. onError = null;
  1005. }
  1006. return SyncPromise.complete(onComplete, onError,
  1007. this.signPromise(target, paramsOrCertificateName, wireFormat, !onComplete));
  1008. };
  1009. /**
  1010. * Generate a self-signed certificate for the public key and add it to the PIB.
  1011. * This creates the certificate name from the key name by appending "self" and a
  1012. * version based on the current time. If no default certificate for the key has
  1013. * been set, then set the certificate as the default for the key.
  1014. * @param {PibKey} key The PibKey with the key name and public key.
  1015. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1016. * the certificate. If omitted, use WireFormat getDefaultWireFormat().
  1017. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  1018. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  1019. * an async Promise.
  1020. * @return {Promise|SyncPromise} A promise that returns the new CertificateV2.
  1021. */
  1022. KeyChain.prototype.selfSignPromise = function(key, wireFormat, useSync)
  1023. {
  1024. var arg2 = wireFormat;
  1025. var arg3 = useSync;
  1026. // arg2, arg3
  1027. // wireFormat, useSync
  1028. // wireFormat, null
  1029. // useSync, null
  1030. if (arg2 instanceof WireFormat)
  1031. wireFormat = arg2;
  1032. else
  1033. wireFormat = undefined;
  1034. if (typeof arg2 === "boolean")
  1035. useSync = arg2;
  1036. else if (typeof arg3 === "boolean")
  1037. useSync = arg3;
  1038. else
  1039. useSync = false;
  1040. if (wireFormat == undefined)
  1041. wireFormat = WireFormat.getDefaultWireFormat();
  1042. var certificate = new CertificateV2();
  1043. // Set the name.
  1044. var now = new Date().getTime();
  1045. var certificateName = new Name(key.getName());
  1046. certificateName.append("self").appendVersion(now);
  1047. certificate.setName(certificateName);
  1048. // Set the MetaInfo.
  1049. certificate.getMetaInfo().setType(ContentType.KEY);
  1050. // Set a one-hour freshness period.
  1051. certificate.getMetaInfo().setFreshnessPeriod(3600 * 1000.0);
  1052. // Set the content.
  1053. certificate.setContent(key.getPublicKey());
  1054. // Set the signature-info.
  1055. signingInfo = new SigningInfo(key);
  1056. // Set a 20-year validity period.
  1057. signingInfo.setValidityPeriod
  1058. (new ValidityPeriod(now, now + 20 * 365 * 24 * 3600 * 1000.0));
  1059. return this.signPromise(certificate, signingInfo, wireFormat, useSync)
  1060. .then(function() {
  1061. return key.addCertificatePromise_(certificate, useSync)
  1062. .catch(function(ex) {
  1063. // We don't expect this since we just created the certificate.
  1064. return SyncPromise.reject(new KeyChain.Error(new Error
  1065. ("Error encoding certificate: " + ex)));
  1066. });
  1067. })
  1068. .then(function() {
  1069. return SyncPromise.resolve(certificate);
  1070. });
  1071. };
  1072. /**
  1073. * Generate a self-signed certificate for the public key and add it to the PIB.
  1074. * This creates the certificate name from the key name by appending "self" and a
  1075. * version based on the current time. If no default certificate for the key has
  1076. * been set, then set the certificate as the default for the key.
  1077. * @param {PibKey} key The PibKey with the key name and public key.
  1078. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1079. * the certificate. If omitted, use WireFormat getDefaultWireFormat().
  1080. * @param {function} onComplete (optional) This calls
  1081. * onComplete(certificate) with the new CertificateV2. If omitted, the return
  1082. * value is described below. (Some crypto libraries only use a callback, so
  1083. * onComplete is required to use these.)
  1084. * NOTE: The library will log any exceptions thrown by this callback, but for
  1085. * better error handling the callback should catch and properly handle any
  1086. * exceptions.
  1087. * @param {function} onError (optional) If defined, then onComplete must be
  1088. * defined and if there is an exception, then this calls onError(exception)
  1089. * with the exception. If onComplete is defined but onError is undefined, then
  1090. * this will log any thrown exception. (Some database libraries only use a
  1091. * callback, so onError is required to be notified of an exception.)
  1092. * NOTE: The library will log any exceptions thrown by this callback, but for
  1093. * better error handling the callback should catch and properly handle any
  1094. * exceptions.
  1095. * @return {CertificateV2} If onComplete is omitted, return the new certificate.
  1096. * Otherwise, if onComplete is supplied then return undefined and use onComplete
  1097. * as described above.
  1098. */
  1099. KeyChain.prototype.selfSign = function(key, wireFormat, onComplete, onError)
  1100. {
  1101. if (typeof wireFormat === 'function') {
  1102. // wireFormat is omitted, so shift.
  1103. onError = onComplete;
  1104. onComplete = wireFormat;
  1105. wireFormat = undefined;
  1106. }
  1107. if (wireFormat == undefined)
  1108. wireFormat = WireFormat.getDefaultWireFormat();
  1109. return SyncPromise.complete(onComplete, onError,
  1110. this.selfSignPromise(key, wireFormat, !onComplete));
  1111. };
  1112. // Import and export
  1113. /**
  1114. * Import a certificate and its corresponding private key encapsulated in a
  1115. * SafeBag. If the certificate and key are imported properly, the default
  1116. * setting will be updated as if a new key and certificate is added into this
  1117. * KeyChain.
  1118. * @param {SafeBag} safeBag The SafeBag containing the certificate and private
  1119. * key. This copies the values from the SafeBag.
  1120. * @param {Buffer} password (optional) The password for decrypting the private
  1121. * key. If the password is supplied, use it to decrypt the PKCS #8
  1122. * EncryptedPrivateKeyInfo. If the password is omitted or null, import an
  1123. * unencrypted PKCS #8 PrivateKeyInfo.
  1124. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  1125. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  1126. * an async Promise.
  1127. * @return {Promise|SyncPromise} A promise which fulfills when finished.
  1128. */
  1129. KeyChain.prototype.importSafeBagPromise = function(safeBag, password, useSync)
  1130. {
  1131. if (typeof password === 'boolean') {
  1132. // password is omitted, so shift.
  1133. useSync = password;
  1134. password = undefined;
  1135. }
  1136. var certificate;
  1137. try {
  1138. certificate = new CertificateV2(safeBag.getCertificate());
  1139. } catch (ex) {
  1140. return SyncPromise.reject(new Error("Error reading CertificateV2: " + ex));
  1141. }
  1142. var identity = certificate.getIdentity();
  1143. var keyName = certificate.getKeyName();
  1144. var publicKeyBits = certificate.getPublicKey();
  1145. var content = new Blob([0x01, 0x02, 0x03, 0x04]);
  1146. var signatureBits;
  1147. var thisKeyChain = this;
  1148. return SyncPromise.resolve()
  1149. .then(function() {
  1150. return thisKeyChain.tpm_.hasKeyPromise(keyName, useSync);
  1151. })
  1152. .then(function(hasKey) {
  1153. if (hasKey)
  1154. return SyncPromise.reject(new KeyChain.Error(new Error
  1155. ("Private key `" + keyName.toUri() + "` already exists")));
  1156. return thisKeyChain.pib_.getIdentityPromise(identity, useSync)
  1157. .then(function(existingId) {
  1158. return existingId.getKeyPromise(keyName, useSync);
  1159. })
  1160. .then(function() {
  1161. return SyncPromise.reject(new KeyChain.Error(new Error
  1162. ("Public key `" + keyName.toUri() + "` already exists")));
  1163. }, function(err) {
  1164. // Either the identity or the key doesn't exist, so OK to import.
  1165. return SyncPromise.resolve();
  1166. });
  1167. })
  1168. .then(function() {
  1169. return thisKeyChain.tpm_.importPrivateKeyPromise_
  1170. (keyName, safeBag.getPrivateKeyBag().buf(), password, useSync)
  1171. .catch(function(err) {
  1172. return SyncPromise.reject(new KeyChain.Error(new Error
  1173. ("Failed to import private key `" + keyName.toUri() + "`: " + err)));
  1174. });
  1175. })
  1176. .then(function() {
  1177. // Check the consistency of the private key and certificate.
  1178. return thisKeyChain.tpm_.signPromise
  1179. (content.buf(), keyName, DigestAlgorithm.SHA256, useSync)
  1180. .then(function(localSignatureBits) {
  1181. signatureBits = localSignatureBits;
  1182. return SyncPromise.resolve();
  1183. }, function(err) {
  1184. return thisKeyChain.tpm_.deleteKeyPromise_(keyName, useSync)
  1185. .then(function() {
  1186. return SyncPromise.reject(new KeyChain.Error(new Error
  1187. ("Invalid private key `" + keyName.toUri() + "`")));
  1188. });
  1189. });
  1190. })
  1191. .then(function() {
  1192. var publicKey;
  1193. try {
  1194. publicKey = new PublicKey(publicKeyBits);
  1195. } catch (ex) {
  1196. // Promote to KeyChain.Error.
  1197. return thisKeyChain.tpm_.deleteKeyPromise_(keyName, useSync)
  1198. .then(function() {
  1199. return SyncPromise.reject(new KeyChain.Error(new Error
  1200. ("Error decoding public key " + ex)));
  1201. });
  1202. }
  1203. return VerificationHelpers.verifySignaturePromise
  1204. (content, signatureBits, publicKey, useSync);
  1205. })
  1206. .then(function(isVerified) {
  1207. if (!isVerified) {
  1208. return thisKeyChain.tpm_.deleteKeyPromise_(keyName, useSync)
  1209. .then(function() {
  1210. return SyncPromise.reject(new KeyChain.Error(new Error
  1211. ("Certificate `" + certificate.getName().toUri() +
  1212. "` and private key `" + keyName.toUri() + "` do not match")));
  1213. });
  1214. }
  1215. // The consistency is verified. Add to the PIB.
  1216. return thisKeyChain.pib_.addIdentityPromise_(identity, useSync);
  1217. })
  1218. .then(function(id) {
  1219. return id.addKeyPromise_(certificate.getPublicKey().buf(), keyName, useSync);
  1220. })
  1221. .then(function(key) {
  1222. return key.addCertificatePromise_(certificate, useSync);
  1223. });
  1224. };
  1225. /**
  1226. * Import a certificate and its corresponding private key encapsulated in a
  1227. * SafeBag. If the certificate and key are imported properly, the default
  1228. * setting will be updated as if a new key and certificate is added into this
  1229. * KeyChain.
  1230. * @param {SafeBag} safeBag The SafeBag containing the certificate and private
  1231. * key. This copies the values from the SafeBag.
  1232. * @param {Buffer} password (optional) The password for decrypting the private
  1233. * key. If the password is supplied, use it to decrypt the PKCS #8
  1234. * EncryptedPrivateKeyInfo. If the password is omitted or null, import an
  1235. * unencrypted PKCS #8 PrivateKeyInfo.
  1236. * @param {function} onComplete (optional) This calls onComplete() when finished.
  1237. * If omitted, just return when finished. (Some crypto libraries only use a
  1238. * callback, so onComplete is required to use these.)
  1239. * NOTE: The library will log any exceptions thrown by this callback, but for
  1240. * better error handling the callback should catch and properly handle any
  1241. * exceptions.
  1242. * @param {function} onError (optional) If defined, then onComplete must be
  1243. * defined and if there is an exception, then this calls onError(exception)
  1244. * with the exception. If onComplete is defined but onError is undefined, then
  1245. * this will log any thrown exception. (Some crypto libraries only use a
  1246. * callback, so onError is required to be notified of an exception.)
  1247. * NOTE: The library will log any exceptions thrown by this callback, but for
  1248. * better error handling the callback should catch and properly handle any
  1249. * exceptions.
  1250. */
  1251. KeyChain.prototype.importSafeBag = function
  1252. (safeBag, password, onComplete, onError)
  1253. {
  1254. onError = (typeof password === "function") ? onComplete : onError;
  1255. onComplete = (typeof password === "function") ? password : onComplete;
  1256. password = (typeof password === "function") ? null : password;
  1257. return SyncPromise.complete(onComplete, onError,
  1258. this.importSafeBagPromise(safeBag, password, !onComplete));
  1259. };
  1260. // PIB & TPM backend registry
  1261. /**
  1262. * Add to the PIB factories map where scheme is the key and makePibImpl is the
  1263. * value. If your application has its own PIB implementations, this must be
  1264. * called before creating a KeyChain instance which uses your PIB scheme.
  1265. * @param {string} scheme The PIB scheme.
  1266. * @param {function} makePibImpl A callback which takes the PIB location and
  1267. * returns a new PibImpl instance.
  1268. */
  1269. KeyChain.registerPibBackend = function(scheme, makePibImpl)
  1270. {
  1271. KeyChain.getPibFactories_()[scheme] = makePibImpl;
  1272. };
  1273. /**
  1274. * Add to the TPM factories map where scheme is the key and makeTpmBackEnd is
  1275. * the value. If your application has its own TPM implementations, this must be
  1276. * called before creating a KeyChain instance which uses your TPM scheme.
  1277. * @param {string} scheme The TPM scheme.
  1278. * @param {function} makeTpmBackEnd A callback which takes the TPM location and
  1279. * returns a new TpmBackEnd instance.
  1280. */
  1281. KeyChain.registerTpmBackend = function(scheme, makeTpmBackEnd)
  1282. {
  1283. KeyChain.getTpmFactories_()[scheme] = makeTpmBackEnd;
  1284. };
  1285. // Security v1 methods
  1286. /*****************************************
  1287. * Identity Management *
  1288. *****************************************/
  1289. /**
  1290. * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
  1291. * identity and a self-signed certificate of the KSK. If a key pair or
  1292. * certificate for the identity already exists, use it.
  1293. * @param {Name} identityName The name of the identity.
  1294. * @param {KeyParams} params (optional) The key parameters if a key needs to be
  1295. * generated for the identity. If omitted, use KeyChain.getDefaultKeyParams().
  1296. * @param {function} onComplete (optional) This calls onComplete(certificateName)
  1297. * with name of the default certificate of the identity. If omitted, the return
  1298. * value is described below. (Some crypto libraries only use a callback, so
  1299. * onComplete is required to use these.)
  1300. * NOTE: The library will log any exceptions thrown by this callback, but for
  1301. * better error handling the callback should catch and properly handle any
  1302. * exceptions.
  1303. * @param {function} onError (optional) If defined, then onComplete must be
  1304. * defined and if there is an exception, then this calls onError(exception)
  1305. * with the exception. If onComplete is defined but onError is undefined, then
  1306. * this will log any thrown exception. (Some database libraries only use a
  1307. * callback, so onError is required to be notified of an exception.)
  1308. * NOTE: The library will log any exceptions thrown by this callback, but for
  1309. * better error handling the callback should catch and properly handle any
  1310. * exceptions.
  1311. * @return {Name} If onComplete is omitted, return the name of the default
  1312. * certificate of the identity. Otherwise, if onComplete is supplied then return
  1313. * undefined and use onComplete as described above.
  1314. */
  1315. KeyChain.prototype.createIdentityAndCertificate = function
  1316. (identityName, params, onComplete, onError)
  1317. {
  1318. onError = (typeof params === "function") ? onComplete : onError;
  1319. onComplete = (typeof params === "function") ? params : onComplete;
  1320. params = (typeof params === "function" || !params) ?
  1321. KeyChain.getDefaultKeyParams() : params;
  1322. return this.identityManager_.createIdentityAndCertificate
  1323. (identityName, params, onComplete, onError);
  1324. };
  1325. /**
  1326. * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
  1327. * identity and a self-signed certificate of the KSK. If a key pair or
  1328. * certificate for the identity already exists, use it.
  1329. * @deprecated Use createIdentityAndCertificate which returns the
  1330. * certificate name instead of the key name. You can use
  1331. * IdentityCertificate.certificateNameToPublicKeyName to convert the
  1332. * certificate name to the key name.
  1333. * @param {Name} identityName The name of the identity.
  1334. * @param {KeyParams} params (optional) The key parameters if a key needs to be
  1335. * generated for the identity. If omitted, use KeyChain.getDefaultKeyParams().
  1336. * @return {Name} The key name of the auto-generated KSK of the identity.
  1337. */
  1338. KeyChain.prototype.createIdentity = function(identityName, params)
  1339. {
  1340. return IdentityCertificate.certificateNameToPublicKeyName
  1341. (this.createIdentityAndCertificate(identityName, params));
  1342. };
  1343. /**
  1344. * Get the default identity.
  1345. * @param {function} onComplete (optional) This calls onComplete(identityName)
  1346. * with name of the default identity. If omitted, the return value is described
  1347. * below. (Some crypto libraries only use a callback, so onComplete is required
  1348. * to use these.)
  1349. * NOTE: The library will log any exceptions thrown by this callback, but for
  1350. * better error handling the callback should catch and properly handle any
  1351. * exceptions.
  1352. * @param {function} onError (optional) If defined, then onComplete must be
  1353. * defined and if there is an exception, then this calls onError(exception)
  1354. * with the exception. If onComplete is defined but onError is undefined, then
  1355. * this will log any thrown exception. (Some database libraries only use a
  1356. * callback, so onError is required to be notified of an exception.)
  1357. * @return {Name} If onComplete is omitted, return the name of the default
  1358. * identity. Otherwise, if onComplete is supplied then return undefined and use
  1359. * onComplete as described above.
  1360. * NOTE: The library will log any exceptions thrown by this callback, but for
  1361. * better error handling the callback should catch and properly handle any
  1362. * exceptions.
  1363. * @throws SecurityException if the default identity is not set. However, if
  1364. * onComplete and onError are defined, then if there is an exception return
  1365. * undefined and call onError(exception).
  1366. */
  1367. KeyChain.prototype.getDefaultIdentity = function(onComplete, onError)
  1368. {
  1369. if (!this.isSecurityV1_) {
  1370. return SyncPromise.complete(onComplete, onError,
  1371. this.pib_.getDefaultIdentityPromise(!onComplete)
  1372. .then(function(pibIdentity) {
  1373. return SyncPromise.resolve(pibIdentity.getName());
  1374. }));
  1375. }
  1376. return this.identityManager_.getDefaultIdentity(onComplete, onError);
  1377. };
  1378. /**
  1379. * Get the default certificate name of the default identity, which will be used
  1380. * when signing is based on identity and the identity is not specified.
  1381. * @param {function} onComplete (optional) This calls onComplete(certificateName)
  1382. * with name of the default certificate. If omitted, the return value is described
  1383. * below. (Some crypto libraries only use a callback, so onComplete is required
  1384. * to use these.)
  1385. * NOTE: The library will log any exceptions thrown by this callback, but for
  1386. * better error handling the callback should catch and properly handle any
  1387. * exceptions.
  1388. * @param {function} onError (optional) If defined, then onComplete must be
  1389. * defined and if there is an exception, then this calls onError(exception)
  1390. * with the exception. If onComplete is defined but onError is undefined, then
  1391. * this will log any thrown exception. (Some database libraries only use a
  1392. * callback, so onError is required to be notified of an exception.)
  1393. * NOTE: The library will log any exceptions thrown by this callback, but for
  1394. * better error handling the callback should catch and properly handle any
  1395. * exceptions.
  1396. * @return {Name} If onComplete is omitted, return the default certificate name.
  1397. * Otherwise, if onComplete is supplied then return undefined and use onComplete
  1398. * as described above.
  1399. * @throws SecurityException if the default identity is not set or the default
  1400. * key name for the identity is not set or the default certificate name for
  1401. * the key name is not set. However, if onComplete and onError are defined, then
  1402. * if there is an exception return undefined and call onError(exception).
  1403. */
  1404. KeyChain.prototype.getDefaultCertificateName = function(onComplete, onError)
  1405. {
  1406. if (!this.isSecurityV1_) {
  1407. return SyncPromise.complete(onComplete, onError,
  1408. this.pib_.getDefaultIdentityPromise(!onComplete)
  1409. .then(function(identity) {
  1410. return identity.getDefaultKeyPromise(!onComplete);
  1411. })
  1412. .then(function(key) {
  1413. return key.getDefaultCertificatePromise(!onComplete);
  1414. })
  1415. .then(function(certificate) {
  1416. return SyncPromise.resolve(certificate.getName());
  1417. }));
  1418. }
  1419. return this.identityManager_.getDefaultCertificateName(onComplete, onError);
  1420. };
  1421. /**
  1422. * Generate a pair of RSA keys for the specified identity.
  1423. * @param {Name} identityName The name of the identity.
  1424. * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
  1425. * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
  1426. * @param {number} keySize (optional) The size of the key. If omitted, use a
  1427. * default secure key size.
  1428. * @return {Name} The generated key name.
  1429. */
  1430. KeyChain.prototype.generateRSAKeyPair = function(identityName, isKsk, keySize)
  1431. {
  1432. if (!this.isSecurityV1_)
  1433. throw new SecurityException(new Error
  1434. ("generateRSAKeyPair is not supported for security v2. Use createIdentityV2."));
  1435. keySize = (typeof isKsk === "boolean") ? isKsk : keySize;
  1436. isKsk = (typeof isKsk === "boolean") ? isKsk : false;
  1437. if (!keySize)
  1438. keySize = 2048;
  1439. return this.identityManager_.generateRSAKeyPair(identityName, isKsk, keySize);
  1440. };
  1441. /**
  1442. * Set a key as the default key of an identity. The identity name is inferred
  1443. * from keyName.
  1444. * @param {Name} keyName The name of the key.
  1445. * @param {Name} identityNameCheck (optional) The identity name to check that the
  1446. * keyName contains the same identity name. If an empty name, it is ignored.
  1447. * @param {function} onComplete (optional) This calls onComplete() when complete.
  1448. * (Some database libraries only use a callback, so onComplete is required to
  1449. * use these.)
  1450. * NOTE: The library will log any exceptions thrown by this callback, but for
  1451. * better error handling the callback should catch and properly handle any
  1452. * exceptions.
  1453. * @param {function} onError (optional) If defined, then onComplete must be
  1454. * defined and if there is an exception, then this calls onError(exception)
  1455. * with the exception. If onComplete is defined but onError is undefined, then
  1456. * this will log any thrown exception. (Some database libraries only use a
  1457. * callback, so onError is required to be notified of an exception.)
  1458. * NOTE: The library will log any exceptions thrown by this callback, but for
  1459. * better error handling the callback should catch and properly handle any
  1460. * exceptions.
  1461. */
  1462. KeyChain.prototype.setDefaultKeyForIdentity = function
  1463. (keyName, identityNameCheck, onComplete, onError)
  1464. {
  1465. if (!this.isSecurityV1_)
  1466. return SyncPromise.complete(onComplete, onError,
  1467. SyncPromise.reject(new SecurityException(new Error
  1468. ("setDefaultKeyForIdentity is not supported for security v2. Use getPib() methods."))));
  1469. return this.identityManager_.setDefaultKeyForIdentity
  1470. (keyName, identityNameCheck, onComplete, onError);
  1471. };
  1472. /**
  1473. * Generate a pair of RSA keys for the specified identity and set it as the
  1474. * default key for the identity.
  1475. * @param {Name} identityName The name of the identity.
  1476. * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
  1477. * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
  1478. * @param {number} keySize (optional) The size of the key. If omitted, use a
  1479. * default secure key size.
  1480. * @return {Name} The generated key name.
  1481. */
  1482. KeyChain.prototype.generateRSAKeyPairAsDefault = function
  1483. (identityName, isKsk, keySize)
  1484. {
  1485. if (!this.isSecurityV1_)
  1486. throw new SecurityException(new Error
  1487. ("generateRSAKeyPairAsDefault is not supported for security v2. Use createIdentityV2."));
  1488. return this.identityManager_.generateRSAKeyPairAsDefault
  1489. (identityName, isKsk, keySize);
  1490. };
  1491. /**
  1492. * Create a public key signing request.
  1493. * @param {Name} keyName The name of the key.
  1494. * @return {Blob} The signing request data.
  1495. */
  1496. KeyChain.prototype.createSigningRequest = function(keyName)
  1497. {
  1498. if (!this.isSecurityV1_) {
  1499. var useSync = true;
  1500. return SyncPromise.complete(null, null,
  1501. this.pib_.getIdentityPromise
  1502. (PibKey.extractIdentityFromKeyName(keyName, useSync))
  1503. .then(function(identity) {
  1504. return identity.getKeyPromise(keyName, useSync);
  1505. })
  1506. .then(function(key) {
  1507. return SyncPromise.resolve(key.getPublicKey());
  1508. }));
  1509. }
  1510. return this.identityManager_.getPublicKey(keyName).getKeyDer();
  1511. };
  1512. /**
  1513. * Install an identity certificate into the public key identity storage.
  1514. * @param {IdentityCertificate} certificate The certificate to to added.
  1515. * @param {function} onComplete (optional) This calls onComplete() when complete.
  1516. * (Some database libraries only use a callback, so onComplete is required to
  1517. * use these.)
  1518. * NOTE: The library will log any exceptions thrown by this callback, but for
  1519. * better error handling the callback should catch and properly handle any
  1520. * exceptions.
  1521. * @param {function} onError (optional) If defined, then onComplete must be
  1522. * defined and if there is an exception, then this calls onError(exception)
  1523. * with the exception. If onComplete is defined but onError is undefined, then
  1524. * this will log any thrown exception. (Some database libraries only use a
  1525. * callback, so onError is required to be notified of an exception.)
  1526. * NOTE: The library will log any exceptions thrown by this callback, but for
  1527. * better error handling the callback should catch and properly handle any
  1528. * exceptions.
  1529. */
  1530. KeyChain.prototype.installIdentityCertificate = function
  1531. (certificate, onComplete, onError)
  1532. {
  1533. if (!this.isSecurityV1_)
  1534. return SyncPromise.complete(onComplete, onError,
  1535. SyncPromise.reject(new SecurityException(new Error
  1536. ("installIdentityCertificate is not supported for security v2. Use getPib() methods."))));
  1537. this.identityManager_.addCertificate(certificate, onComplete, onError);
  1538. };
  1539. /**
  1540. * Set the certificate as the default for its corresponding key.
  1541. * @param {IdentityCertificate} certificate The certificate.
  1542. * @param {function} onComplete (optional) This calls onComplete() when complete.
  1543. * (Some database libraries only use a callback, so onComplete is required to
  1544. * use these.)
  1545. * NOTE: The library will log any exceptions thrown by this callback, but for
  1546. * better error handling the callback should catch and properly handle any
  1547. * exceptions.
  1548. * @param {function} onError (optional) If defined, then onComplete must be
  1549. * defined and if there is an exception, then this calls onError(exception)
  1550. * with the exception. If onComplete is defined but onError is undefined, then
  1551. * this will log any thrown exception. (Some database libraries only use a
  1552. * callback, so onError is required to be notified of an exception.)
  1553. * NOTE: The library will log any exceptions thrown by this callback, but for
  1554. * better error handling the callback should catch and properly handle any
  1555. * exceptions.
  1556. */
  1557. KeyChain.prototype.setDefaultCertificateForKey = function
  1558. (certificate, onComplete, onError)
  1559. {
  1560. if (!this.isSecurityV1_)
  1561. return SyncPromise.complete(onComplete, onError,
  1562. SyncPromise.reject(new SecurityException(new Error
  1563. ("setDefaultCertificateForKey is not supported for security v2. Use getPib() methods."))));
  1564. this.identityManager_.setDefaultCertificateForKey
  1565. (certificate, onComplete, onError);
  1566. };
  1567. /**
  1568. * Get a certificate which is still valid with the specified name.
  1569. * @param {Name} certificateName The name of the requested certificate.
  1570. * @param {function} onComplete (optional) This calls onComplete(certificate)
  1571. * with the requested IdentityCertificate. If omitted, the return value is
  1572. * described below. (Some crypto libraries only use a callback, so onComplete is
  1573. * required to use these.)
  1574. * NOTE: The library will log any exceptions thrown by this callback, but for
  1575. * better error handling the callback should catch and properly handle any
  1576. * exceptions.
  1577. * @param {function} onError (optional) If defined, then onComplete must be
  1578. * defined and if there is an exception, then this calls onError(exception)
  1579. * with the exception. If onComplete is defined but onError is undefined, then
  1580. * this will log any thrown exception. (Some database libraries only use a
  1581. * callback, so onError is required to be notified of an exception.)
  1582. * NOTE: The library will log any exceptions thrown by this callback, but for
  1583. * better error handling the callback should catch and properly handle any
  1584. * exceptions.
  1585. * @return {IdentityCertificate} If onComplete is omitted, return the requested
  1586. * certificate. Otherwise, if onComplete is supplied then return undefined and
  1587. * use onComplete as described above.
  1588. */
  1589. KeyChain.prototype.getCertificate = function
  1590. (certificateName, onComplete, onError)
  1591. {
  1592. if (!this.isSecurityV1_)
  1593. return SyncPromise.complete(onComplete, onError,
  1594. SyncPromise.reject(new SecurityException(new Error
  1595. ("getCertificate is not supported for security v2. Use getPib() methods."))));
  1596. return this.identityManager_.getCertificate
  1597. (certificateName, onComplete, onError);
  1598. };
  1599. /**
  1600. * @deprecated Use getCertificate.
  1601. */
  1602. KeyChain.prototype.getIdentityCertificate = function
  1603. (certificateName, onComplete, onError)
  1604. {
  1605. if (!this.isSecurityV1_)
  1606. return SyncPromise.complete(onComplete, onError,
  1607. SyncPromise.reject(new SecurityException(new Error
  1608. ("getIdentityCertificate is not supported for security v2. Use getPib() methods."))));
  1609. return this.identityManager_.getCertificate
  1610. (certificateName, onComplete, onError);
  1611. };
  1612. /**
  1613. * Revoke a key.
  1614. * @param {Name} keyName The name of the key that will be revoked.
  1615. */
  1616. KeyChain.prototype.revokeKey = function(keyName)
  1617. {
  1618. //TODO: Implement
  1619. };
  1620. /**
  1621. * Revoke a certificate.
  1622. * @param {Name} certificateName The name of the certificate that will be
  1623. * revoked.
  1624. */
  1625. KeyChain.prototype.revokeCertificate = function(certificateName)
  1626. {
  1627. //TODO: Implement
  1628. };
  1629. /**
  1630. * Get the identity manager given to or created by the constructor.
  1631. * @return {IdentityManager} The identity manager.
  1632. */
  1633. KeyChain.prototype.getIdentityManager = function()
  1634. {
  1635. if (!this.isSecurityV1_)
  1636. throw new SecurityException(new Error
  1637. ("getIdentityManager is not supported for security v2"));
  1638. return this.identityManager_;
  1639. };
  1640. /*****************************************
  1641. * Policy Management *
  1642. *****************************************/
  1643. /**
  1644. * Get the policy manager given to or created by the constructor.
  1645. * @return {PolicyManager} The policy manager.
  1646. */
  1647. KeyChain.prototype.getPolicyManager = function()
  1648. {
  1649. return this.policyManager_;
  1650. };
  1651. /*****************************************
  1652. * Sign/Verify *
  1653. *****************************************/
  1654. /**
  1655. * Sign the target. If it is a Data object, set its signature. If it is an
  1656. * array, produce a signature object.
  1657. * @param {Data|Buffer} target If this is a Data object, wire encode for
  1658. * signing, update its signature and key locator field and wireEncoding. If it
  1659. * is an array, sign it and return a Signature object.
  1660. * @param {Name} identityName (optional) The identity name for the key to use for
  1661. * signing. If omitted, infer the signing identity from the data packet name.
  1662. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1663. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1664. * @param {function} onComplete (optional) If target is a Data object, this calls
  1665. * onComplete(data) with the supplied Data object which has been modified to set
  1666. * its signature. If target is a Buffer, this calls
  1667. * onComplete(signature) where signature is the produced Signature object. If
  1668. * omitted, the return value is described below. (Some crypto libraries only use
  1669. * a callback, so onComplete is required to use these.)
  1670. * NOTE: The library will log any exceptions thrown by this callback, but for
  1671. * better error handling the callback should catch and properly handle any
  1672. * exceptions.
  1673. * @param {function} onError (optional) If defined, then onComplete must be
  1674. * defined and if there is an exception, then this calls onError(exception)
  1675. * with the exception. If onComplete is defined but onError is undefined, then
  1676. * this will log any thrown exception. (Some database libraries only use a
  1677. * callback, so onError is required to be notified of an exception.)
  1678. * NOTE: The library will log any exceptions thrown by this callback, but for
  1679. * better error handling the callback should catch and properly handle any
  1680. * exceptions.
  1681. * @return {Signature} If onComplete is omitted, return the generated Signature
  1682. * object (if target is a Buffer) or undefined (if target is Data).
  1683. * Otherwise, if onComplete is supplied then return undefined and use onComplete
  1684. * as described above.
  1685. */
  1686. KeyChain.prototype.signByIdentity = function
  1687. (target, identityName, wireFormat, onComplete, onError)
  1688. {
  1689. onError = (typeof wireFormat === "function") ? onComplete : onError;
  1690. onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  1691. wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;
  1692. if (!this.isSecurityV1_)
  1693. return SyncPromise.complete(onComplete, onError,
  1694. SyncPromise.reject(new SecurityException(new Error
  1695. ("signByIdentity(buffer, identityName) is not supported for security v2. Use sign with SigningInfo."))));
  1696. var useSync = !onComplete;
  1697. var thisKeyChain = this;
  1698. if (identityName == null)
  1699. identityName = new Name();
  1700. if (target instanceof Data) {
  1701. var data = target;
  1702. var mainPromise = SyncPromise.resolve()
  1703. .then(function() {
  1704. if (identityName.size() == 0) {
  1705. var inferredIdentity = thisKeyChain.policyManager_.inferSigningIdentity
  1706. (data.getName());
  1707. if (inferredIdentity.size() == 0)
  1708. return thisKeyChain.identityManager_.getDefaultCertificateNamePromise
  1709. (useSync);
  1710. else
  1711. return thisKeyChain.identityManager_.getDefaultCertificateNameForIdentityPromise
  1712. (inferredIdentity, useSync);
  1713. }
  1714. else
  1715. return thisKeyChain.identityManager_.getDefaultCertificateNameForIdentityPromise
  1716. (identityName, useSync);
  1717. })
  1718. .then(function(signingCertificateName) {
  1719. if (signingCertificateName.size() == 0)
  1720. throw new SecurityException(new Error
  1721. ("No qualified certificate name found!"));
  1722. if (!thisKeyChain.policyManager_.checkSigningPolicy
  1723. (data.getName(), signingCertificateName))
  1724. throw new SecurityException(new Error
  1725. ("Signing Cert name does not comply with signing policy"));
  1726. return thisKeyChain.identityManager_.signByCertificatePromise
  1727. (data, signingCertificateName, wireFormat, useSync);
  1728. });
  1729. return SyncPromise.complete(onComplete, onError, mainPromise);
  1730. }
  1731. else {
  1732. var array = target;
  1733. return SyncPromise.complete(onComplete, onError,
  1734. this.identityManager_.getDefaultCertificateNameForIdentityPromise
  1735. (identityName, useSync)
  1736. .then(function(signingCertificateName) {
  1737. if (signingCertificateName.size() == 0)
  1738. throw new SecurityException(new Error
  1739. ("No qualified certificate name found!"));
  1740. return thisKeyChain.identityManager_.signByCertificatePromise
  1741. (array, signingCertificateName, wireFormat, useSync);
  1742. }));
  1743. }
  1744. };
  1745. /**
  1746. * Sign the target using DigestSha256.
  1747. * @param {Data|Interest} target If this is a Data object, wire encode for
  1748. * signing, digest it and set its SignatureInfo to a DigestSha256, updating its
  1749. * signature and wireEncoding. If this is an Interest object, wire encode for
  1750. * signing, append a SignatureInfo for DigestSha256 to the Interest name, digest
  1751. * the name components and append a final name component with the signature bits.
  1752. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1753. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1754. */
  1755. KeyChain.prototype.signWithSha256 = function(target, wireFormat)
  1756. {
  1757. if (!this.isSecurityV1_) {
  1758. var signingInfo = SigningInfo();
  1759. signingInfo.setSha256Signing();
  1760. this.sign(target, signingInfo, wireFormat);
  1761. return;
  1762. }
  1763. if (target instanceof Interest)
  1764. this.identityManager_.signInterestWithSha256(target, wireFormat);
  1765. else
  1766. this.identityManager_.signWithSha256(target, wireFormat);
  1767. };
  1768. /**
  1769. * Check the signature on the Data object and call either onVerify or
  1770. * onValidationFailed. We use callback functions because verify may fetch
  1771. * information to check the signature.
  1772. * @param {Data} data The Data object with the signature to check.
  1773. * @param {function} onVerified If the signature is verified, this calls
  1774. * onVerified(data).
  1775. * NOTE: The library will log any exceptions thrown by this callback, but for
  1776. * better error handling the callback should catch and properly handle any
  1777. * exceptions.
  1778. * @param {function} onValidationFailed If the signature check fails, this calls
  1779. * onValidationFailed(data, reason) with the Data object and reason string.
  1780. * NOTE: The library will log any exceptions thrown by this callback, but for
  1781. * better error handling the callback should catch and properly handle any
  1782. * exceptions.
  1783. * @param {number} stepCount
  1784. */
  1785. KeyChain.prototype.verifyData = function
  1786. (data, onVerified, onValidationFailed, stepCount)
  1787. {
  1788. if (stepCount == null)
  1789. stepCount = 0;
  1790. if (this.policyManager_.requireVerify(data)) {
  1791. var nextStep = this.policyManager_.checkVerificationPolicy
  1792. (data, stepCount, onVerified, onValidationFailed);
  1793. if (nextStep != null) {
  1794. var thisKeyChain = this;
  1795. this.face_.expressInterest
  1796. (nextStep.interest,
  1797. function(callbackInterest, callbackData) {
  1798. thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
  1799. },
  1800. function(callbackInterest) {
  1801. thisKeyChain.onCertificateInterestTimeout
  1802. (callbackInterest, nextStep.retry, onValidationFailed, data, nextStep);
  1803. });
  1804. }
  1805. }
  1806. else if (this.policyManager_.skipVerifyAndTrust(data)) {
  1807. try {
  1808. onVerified(data);
  1809. } catch (ex) {
  1810. console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
  1811. }
  1812. }
  1813. else {
  1814. try {
  1815. onValidationFailed
  1816. (data, "The packet has no verify rule but skipVerifyAndTrust is false");
  1817. } catch (ex) {
  1818. console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
  1819. }
  1820. }
  1821. };
  1822. /**
  1823. * Check the signature on the signed interest and call either onVerify or
  1824. * onValidationFailed. We use callback functions because verify may fetch
  1825. * information to check the signature.
  1826. * @param {Interest} interest The interest with the signature to check.
  1827. * @param {function} onVerified If the signature is verified, this calls
  1828. * onVerified(interest).
  1829. * NOTE: The library will log any exceptions thrown by this callback, but for
  1830. * better error handling the callback should catch and properly handle any
  1831. * exceptions.
  1832. * @param {function} onValidationFailed If the signature check fails, this calls
  1833. * onValidationFailed(interest, reason) with the Interest object and reason
  1834. * string.
  1835. * NOTE: The library will log any exceptions thrown by this callback, but for
  1836. * better error handling the callback should catch and properly handle any
  1837. * exceptions.
  1838. */
  1839. KeyChain.prototype.verifyInterest = function
  1840. (interest, onVerified, onValidationFailed, stepCount, wireFormat)
  1841. {
  1842. if (stepCount == null)
  1843. stepCount = 0;
  1844. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  1845. if (this.policyManager_.requireVerify(interest)) {
  1846. var nextStep = this.policyManager_.checkVerificationPolicy
  1847. (interest, stepCount, onVerified, onValidationFailed, wireFormat);
  1848. if (nextStep != null) {
  1849. var thisKeyChain = this;
  1850. this.face_.expressInterest
  1851. (nextStep.interest,
  1852. function(callbackInterest, callbackData) {
  1853. thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
  1854. },
  1855. function(callbackInterest) {
  1856. thisKeyChain.onCertificateInterestTimeout
  1857. (callbackInterest, nextStep.retry, onValidationFailed, interest,
  1858. nextStep);
  1859. });
  1860. }
  1861. }
  1862. else if (this.policyManager_.skipVerifyAndTrust(interest)) {
  1863. try {
  1864. onVerified(interest);
  1865. } catch (ex) {
  1866. console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
  1867. }
  1868. }
  1869. else {
  1870. try {
  1871. onValidationFailed
  1872. (interest,
  1873. "The packet has no verify rule but skipVerifyAndTrust is false");
  1874. } catch (ex) {
  1875. console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
  1876. }
  1877. }
  1878. };
  1879. /**
  1880. * Set the Face which will be used to fetch required certificates.
  1881. * @param {Face} face A pointer to the Face object.
  1882. */
  1883. KeyChain.prototype.setFace = function(face)
  1884. {
  1885. this.face_ = face;
  1886. };
  1887. /**
  1888. * Wire encode the target, compute an HmacWithSha256 and update the object.
  1889. * Note: This method is an experimental feature. The API may change.
  1890. * @param {Data|Interest} target If the target is a Data object (which should
  1891. * already have an HmacWithSha256Signature with a KeyLocator for the key name),
  1892. * then update its signature and wire encoding. If the target is an Interest,
  1893. * then append a SignatureInfo to the Interest name, compute an HmacWithSha256
  1894. * signature for the name components and append a final name component with the
  1895. * signature bits.
  1896. * @param {Blob} key The key for the HmacWithSha256.
  1897. * param {Name} keyName (needed if target is an Interest) The name of the key
  1898. * for the KeyLocator in the SignatureInfo which is added to the Interest name.
  1899. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1900. * the target. If omitted, use WireFormat getDefaultWireFormat().
  1901. */
  1902. KeyChain.signWithHmacWithSha256 = function(target, key, keyName, wireFormat)
  1903. {
  1904. if (keyName instanceof WireFormat) {
  1905. // The keyName is omitted, so shift arguments.
  1906. wireFormat = keyName;
  1907. keyName = undefined;
  1908. }
  1909. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  1910. if (target instanceof Data) {
  1911. var data = target;
  1912. // Encode once to get the signed portion.
  1913. var encoding = data.wireEncode(wireFormat);
  1914. var signer = Crypto.createHmac('sha256', key.buf());
  1915. signer.update(encoding.signedBuf());
  1916. data.getSignature().setSignature(
  1917. new Blob(signer.digest(), false));
  1918. }
  1919. else if (target instanceof Interest) {
  1920. var interest = target;
  1921. if (keyName == null)
  1922. throw new SecurityException(new Error
  1923. ("signWithHmacWithSha256: keyName is required to sign an Interest"));
  1924. var signature = new HmacWithSha256Signature();
  1925. signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
  1926. signature.getKeyLocator().setKeyName(keyName);
  1927. // Append the encoded SignatureInfo.
  1928. interest.getName().append(wireFormat.encodeSignatureInfo(signature));
  1929. // Append an empty signature so that the "signedPortion" is correct.
  1930. interest.getName().append(new Name.Component());
  1931. // Encode once to get the signed portion.
  1932. var encoding = interest.wireEncode(wireFormat);
  1933. var signer = Crypto.createHmac('sha256', key.buf());
  1934. signer.update(encoding.signedBuf());
  1935. signature.setSignature(new Blob(signer.digest(), false));
  1936. // Remove the empty signature and append the real one.
  1937. interest.setName(interest.getName().getPrefix(-1).append
  1938. (wireFormat.encodeSignatureValue(signature)));
  1939. }
  1940. else
  1941. throw new SecurityException(new Error
  1942. ("signWithHmacWithSha256: Unrecognized target type"));
  1943. };
  1944. /**
  1945. * Compute a new HmacWithSha256 for the target and verify it against the
  1946. * signature value.
  1947. * Note: This method is an experimental feature. The API may change.
  1948. * @param {Data} data The Data object to verify.
  1949. * @param {Blob} key The key for the HmacWithSha256.
  1950. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1951. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1952. * @return {boolean} True if the signature verifies, otherwise false.
  1953. */
  1954. KeyChain.verifyDataWithHmacWithSha256 = function(data, key, wireFormat)
  1955. {
  1956. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  1957. // wireEncode returns the cached encoding if available.
  1958. var encoding = data.wireEncode(wireFormat);
  1959. var signer = Crypto.createHmac('sha256', key.buf());
  1960. signer.update(encoding.signedBuf());
  1961. var newSignatureBits = new Blob(signer.digest(), false);
  1962. // Use the flexible Blob.equals operator.
  1963. return newSignatureBits.equals(data.getSignature().getSignature());
  1964. };
  1965. /**
  1966. * Compute a new HmacWithSha256 for all but the final name component and verify
  1967. * it against the signature value in the final name component.
  1968. * Note: This method is an experimental feature. The API may change.
  1969. * @param {Interest} interest The Interest object to verify.
  1970. * @param {Blob} key The key for the HmacWithSha256.
  1971. * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
  1972. * the input. If omitted, use WireFormat getDefaultWireFormat().
  1973. * @return {boolean} True if the signature verifies, otherwise false.
  1974. */
  1975. KeyChain.verifyInterestWithHmacWithSha256 = function(interest, key, wireFormat)
  1976. {
  1977. wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  1978. // Decode the last two name components of the signed interest.
  1979. var signature = wireFormat.decodeSignatureInfoAndValue
  1980. (interest.getName().get(-2).getValue().buf(),
  1981. interest.getName().get(-1).getValue().buf());
  1982. // wireEncode returns the cached encoding if available.
  1983. var encoding = interest.wireEncode(wireFormat);
  1984. var signer = Crypto.createHmac('sha256', key.buf());
  1985. signer.update(encoding.signedBuf());
  1986. var newSignatureBits = new Blob(signer.digest(), false);
  1987. // Use the flexible Blob.equals operator.
  1988. return newSignatureBits.equals(signature.getSignature());
  1989. };
  1990. KeyChain.getDefaultKeyParams = function() { return KeyChain.defaultKeyParams_; };
  1991. /**
  1992. * @deprecated Use getDefaultKeyParams().
  1993. */
  1994. KeyChain.DEFAULT_KEY_PARAMS = new RsaKeyParams();
  1995. // Private security v2 methods
  1996. /**
  1997. * Get the PIB factories map. On the first call, this initializes the map with
  1998. * factories for standard PibImpl implementations.
  1999. * @return {object} A map where the key is the scheme string and the value is a
  2000. * function makePibImpl(location) which takes a string location and returns a
  2001. * new PibImpl object.
  2002. */
  2003. KeyChain.getPibFactories_ = function()
  2004. {
  2005. if (KeyChain.pibFactories_ == null) {
  2006. KeyChain.pibFactories_ = {};
  2007. // Add the standard factories.
  2008. if (PibSqlite3)
  2009. // PibSqlite3 is defined for Node.js .
  2010. KeyChain.pibFactories_[PibSqlite3.getScheme()] =
  2011. function(location) { return new PibSqlite3(location); };
  2012. KeyChain.pibFactories_[PibMemory.getScheme()] =
  2013. function(location) { return new PibMemory(); };
  2014. }
  2015. return KeyChain.pibFactories_;
  2016. };
  2017. /**
  2018. * Get the TPM factories map. On the first call, this initializes the map with
  2019. * factories for standard TpmBackEnd implementations.
  2020. * @return {object} A map where the key is the scheme string and the value is a
  2021. * function makeTpmBackEnd(location) which takes a string location and returns a
  2022. * new TpmBackEnd object.
  2023. */
  2024. KeyChain.getTpmFactories_ = function()
  2025. {
  2026. if (KeyChain.tpmFactories_ == null) {
  2027. KeyChain.tpmFactories_ = {};
  2028. // Add the standard factories.
  2029. if (TpmBackEndFile)
  2030. // TpmBackEndFile is defined for Node.js .
  2031. KeyChain.tpmFactories_[TpmBackEndFile.getScheme()] =
  2032. function(location) { return new TpmBackEndFile(location); };
  2033. KeyChain.tpmFactories_[TpmBackEndMemory.getScheme()] =
  2034. function(location) { return new TpmBackEndMemory(); };
  2035. }
  2036. return KeyChain.tpmFactories_;
  2037. };
  2038. /**
  2039. * Parse the uri and set the scheme and location.
  2040. * @param {string} uri The URI to parse.
  2041. * @param {Array<string>} scheme Set scheme[0] to the scheme.
  2042. * @param {Array<string>} location Set location[0] to the location.
  2043. */
  2044. KeyChain.parseLocatorUri_ = function(uri, scheme, location)
  2045. {
  2046. iColon = uri.indexOf(':');
  2047. if (iColon >= 0) {
  2048. scheme[0] = uri.substring(0, iColon);
  2049. location[0] = uri.substring(iColon + 1);
  2050. }
  2051. else {
  2052. scheme[0] = uri;
  2053. location[0] = "";
  2054. }
  2055. };
  2056. /**
  2057. * Parse the pibLocator and set the pibScheme and pibLocation.
  2058. * @param {string} pibLocator The PIB locator to parse.
  2059. * @param {Array<string>} pibScheme Set pibScheme[0] to the PIB scheme.
  2060. * @param {Array<string>} pibLocation Set pibLocation[0] to the PIB location.
  2061. */
  2062. KeyChain.parseAndCheckPibLocator_ = function(pibLocator, pibScheme, pibLocation)
  2063. {
  2064. KeyChain.parseLocatorUri_(pibLocator, pibScheme, pibLocation);
  2065. if (pibScheme[0] == "")
  2066. pibScheme[0] = KeyChain.getDefaultPibScheme_();
  2067. if (KeyChain.getPibFactories_()[pibScheme[0]] == undefined)
  2068. throw new KeyChain.Error(new Error
  2069. ("PIB scheme `" + pibScheme[0] + "` is not supported"));
  2070. };
  2071. /**
  2072. * Parse the tpmLocator and set the tpmScheme and tpmLocation.
  2073. * @param {string} tpmLocator The TPM locator to parse.
  2074. * @param {Array<string>} tpmScheme Set tpmScheme[0] to the TPM scheme.
  2075. * @param {Array<string>} tpmLocation Set tpmLocation[0] to the TPM location.
  2076. */
  2077. KeyChain.parseAndCheckTpmLocator_ = function(tpmLocator, tpmScheme, tpmLocation)
  2078. {
  2079. KeyChain.parseLocatorUri_(tpmLocator, tpmScheme, tpmLocation);
  2080. if (tpmScheme[0] == "")
  2081. tpmScheme[0] = KeyChain.getDefaultTpmScheme_();
  2082. if (KeyChain.getTpmFactories_()[tpmScheme[0]] == undefined)
  2083. throw new KeyChain.Error(new Error
  2084. ("TPM scheme `" + tpmScheme[0] + "` is not supported"));
  2085. };
  2086. /**
  2087. * @return {string}
  2088. */
  2089. KeyChain.getDefaultPibScheme_ = function() { return PibSqlite3.getScheme(); };
  2090. /**
  2091. * @return {string}
  2092. */
  2093. KeyChain.getDefaultTpmScheme_ = function()
  2094. {
  2095. // Assume we are in Node.js, so check the system.
  2096. if (process.platform === "darwin")
  2097. throw new KeyChain.Error(new Error
  2098. ("TpmBackEndOsx is not implemented. You must use tpm-file."));
  2099. return TpmBackEndFile.getScheme();
  2100. };
  2101. /**
  2102. * Create a Pib according to the pibLocator.
  2103. * @param {string} pibLocator The PIB locator, e.g., "pib-sqlite3:/example/dir".
  2104. * @return {Pib} A new Pib object.
  2105. */
  2106. KeyChain.createPib_ = function(pibLocator)
  2107. {
  2108. var pibScheme = [null];
  2109. var pibLocation = [null];
  2110. KeyChain.parseAndCheckPibLocator_(pibLocator, pibScheme, pibLocation);
  2111. var pibFactory = KeyChain.getPibFactories_()[pibScheme[0]];
  2112. return new Pib(pibScheme[0], pibLocation[0], pibFactory(pibLocation[0]));
  2113. };
  2114. /**
  2115. * Set up tpm according to the tpmLocator. This is called by
  2116. * Pib.initializePromise_ after determining the correct tpmLocator.
  2117. * @param {Tpm} tpm The Tpm to set up.
  2118. * @param {string} tpmLocator The TPM locator, e.g., "tpm-memory:".
  2119. * @return {Tpm} A new Tpm object.
  2120. */
  2121. KeyChain.setUpTpm_ = function(tpm, tpmLocator)
  2122. {
  2123. var tpmScheme = [null];
  2124. var tpmLocation = [null];
  2125. KeyChain.parseAndCheckTpmLocator_(tpmLocator, tpmScheme, tpmLocation);
  2126. var tpmFactory = KeyChain.getTpmFactories_()[tpmScheme[0]];
  2127. tpm.scheme_ = tpmScheme[0];
  2128. tpm.location_ = tpmLocation[0];
  2129. tpm.backEnd_ = tpmFactory(tpmLocation[0]);
  2130. };
  2131. /**
  2132. * @param {ConfigFile} config
  2133. * @return {string}
  2134. */
  2135. KeyChain.getDefaultPibLocator_ = function(config)
  2136. {
  2137. if (KeyChain.defaultPibLocator_ != null)
  2138. return KeyChain.defaultPibLocator_;
  2139. var clientPib = process.env.NDN_CLIENT_PIB;
  2140. if (clientPib != undefined && clientPib != "")
  2141. KeyChain.defaultPibLocator_ = clientPib;
  2142. else
  2143. KeyChain.defaultPibLocator_ = config.get
  2144. ("pib", KeyChain.getDefaultPibScheme_() + ":");
  2145. return KeyChain.defaultPibLocator_;
  2146. };
  2147. /**
  2148. * @param {ConfigFile} config
  2149. * @return {string}
  2150. */
  2151. KeyChain.getDefaultTpmLocator_ = function(config)
  2152. {
  2153. if (KeyChain.defaultTpmLocator_ != null)
  2154. return KeyChain.defaultTpmLocator_;
  2155. var clientTpm = process.env.NDN_CLIENT_TPM;
  2156. if (clientTpm != undefined && clientTpm != "")
  2157. KeyChain.defaultTpmLocator_ = clientTpm;
  2158. else
  2159. KeyChain.defaultTpmLocator_ = config.get
  2160. ("tpm", KeyChain.getDefaultTpmScheme_() + ":");
  2161. return KeyChain.defaultTpmLocator_;
  2162. };
  2163. /**
  2164. * Prepare a Signature object according to signingInfo and get the signing key
  2165. * name.
  2166. * @param {SigningInfo} params The signing parameters.
  2167. * @param {Array<Name>} keyName Set keyName[0] to the signing key name.
  2168. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  2169. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  2170. * an async Promise.
  2171. * @return {Promise|SyncPromise} A promise which returns a new Signature object
  2172. * with the SignatureInfo, or a promise rejected with InvalidSigningInfoError
  2173. * when the requested signing method cannot be satisfied.
  2174. */
  2175. KeyChain.prototype.prepareSignatureInfoPromise_ = function
  2176. (params, keyName, useSync)
  2177. {
  2178. var identity = null;
  2179. var key = null;
  2180. var thisKeyChain = this;
  2181. return SyncPromise.resolve()
  2182. .then(function() {
  2183. if (params.getSignerType() == SigningInfo.SignerType.NULL) {
  2184. return thisKeyChain.pib_.getDefaultIdentityPromise(useSync)
  2185. .then(function(localIdentity) {
  2186. identity = localIdentity;
  2187. return SyncPromise.resolve(null);
  2188. }, function(err) {
  2189. // There is no default identity, so use sha256 for signing.
  2190. keyName[0] = SigningInfo.getDigestSha256Identity();
  2191. return SyncPromise.resolve(new DigestSha256Signature());
  2192. });
  2193. }
  2194. else if (params.getSignerType() == SigningInfo.SignerType.ID) {
  2195. identity = params.getPibIdentity();
  2196. if (identity == null) {
  2197. return thisKeyChain.pib_.getIdentityPromise(params.getSignerName(), useSync)
  2198. .then(function(localIdentity) {
  2199. identity = localIdentity;
  2200. return SyncPromise.resolve(null);
  2201. }, function(err) {
  2202. return SyncPromise.reject(new InvalidSigningInfoError(new Error
  2203. ("Signing identity `" + params.getSignerName().toUri() +
  2204. "` does not exist")));
  2205. });
  2206. }
  2207. else
  2208. return SyncPromise.resolve(null);
  2209. }
  2210. else if (params.getSignerType() == SigningInfo.SignerType.KEY) {
  2211. key = params.getPibKey();
  2212. if (key == null) {
  2213. identityName = PibKey.extractIdentityFromKeyName(
  2214. params.getSignerName());
  2215. return thisKeyChain.pib_.getIdentityPromise(identityName, useSync)
  2216. .then(function(localIdentity) {
  2217. return localIdentity.getKeyPromise(params.getSignerName(), useSync)
  2218. .then(function(localKey) {
  2219. key = localKey;
  2220. // We will use the PIB key instance, so reset the identity.
  2221. identity = null;
  2222. return SyncPromise.resolve(null);
  2223. });
  2224. }, function(err) {
  2225. return SyncPromise.reject(new InvalidSigningInfoError(new Error
  2226. ("Signing key `" + params.getSignerName().toUri() +
  2227. "` does not exist")));
  2228. });
  2229. }
  2230. else
  2231. return SyncPromise.resolve(null);
  2232. }
  2233. else if (params.getSignerType() == SigningInfo.SignerType.CERT) {
  2234. var identityName = CertificateV2.extractIdentityFromCertName
  2235. (params.getSignerName());
  2236. return thisKeyChain.pib_.getIdentityPromise(identityName, useSync)
  2237. .then(function(localIdentity) {
  2238. identity = localIdentity;
  2239. return identity.getKeyPromise
  2240. (CertificateV2.extractKeyNameFromCertName(params.getSignerName()), useSync)
  2241. .then(function(localKey) {
  2242. key = localKey;
  2243. return SyncPromise.resolve(null);
  2244. });
  2245. }, function(err) {
  2246. return SyncPromise.reject(new InvalidSigningInfoError(new Error
  2247. ("Signing certificate `" + params.getSignerName().toUri() +
  2248. "` does not exist")));
  2249. });
  2250. }
  2251. else if (params.getSignerType() == SigningInfo.SignerType.SHA256) {
  2252. keyName[0] = SigningInfo.getDigestSha256Identity();
  2253. return SyncPromise.resolve(new DigestSha256Signature());
  2254. }
  2255. else
  2256. // We don't expect this to happen.
  2257. return SyncPromise.reject(new InvalidSigningInfoError(new Error
  2258. ("Unrecognized signer type")));
  2259. })
  2260. .then(function(signingInfo) {
  2261. if (signingInfo != null)
  2262. // We already have the result (a DigestSha256Signature).
  2263. return SyncPromise.resolve(signingInfo);
  2264. else {
  2265. if (identity == null && key == null)
  2266. return SyncPromise.reject(new InvalidSigningInfoError(new Error
  2267. ("Cannot determine signing parameters")));
  2268. return SyncPromise.resolve()
  2269. .then(function() {
  2270. if (identity != null && key == null) {
  2271. return identity.getDefaultKeyPromise(useSync)
  2272. .then(function(localKey) {
  2273. key = localKey;
  2274. return SyncPromise.resolve(null);
  2275. }, function(err) {
  2276. return SyncPromise.reject(new InvalidSigningInfoError(new Error
  2277. ("Signing identity `" + identity.getName().toUri() +
  2278. "` does not have default certificate")));
  2279. });
  2280. }
  2281. else
  2282. return SyncPromise.resolve();
  2283. })
  2284. .then(function() {
  2285. if (key.getKeyType() == KeyType.RSA &&
  2286. params.getDigestAlgorithm() == DigestAlgorithm.SHA256)
  2287. signatureInfo = new Sha256WithRsaSignature();
  2288. else if (key.getKeyType() == KeyType.EC &&
  2289. params.getDigestAlgorithm() == DigestAlgorithm.SHA256)
  2290. signatureInfo = new Sha256WithEcdsaSignature()
  2291. else
  2292. return SyncPromise.reject(new KeyChain.Error(new Error
  2293. ("Unsupported key type")));
  2294. if (params.getValidityPeriod().hasPeriod() &&
  2295. ValidityPeriod.canGetFromSignature(signatureInfo))
  2296. // Set the ValidityPeriod from the SigningInfo params.
  2297. ValidityPeriod.getFromSignature(signatureInfo).setPeriod
  2298. (params.getValidityPeriod().getNotBefore(),
  2299. params.getValidityPeriod().getNotAfter());
  2300. var keyLocator = KeyLocator.getFromSignature(signatureInfo);
  2301. keyLocator.setType(KeyLocatorType.KEYNAME);
  2302. keyLocator.setKeyName(key.getName());
  2303. keyName[0] = key.getName();
  2304. return SyncPromise.resolve(signatureInfo);
  2305. });
  2306. }
  2307. });
  2308. };
  2309. /**
  2310. * Sign the byte buffer using the key with name keyName.
  2311. * @param {Buffer} buffer The input byte buffer.
  2312. * @param {Name} keyName The name of the key.
  2313. * @param {number} digestAlgorithm The digest algorithm as an int from the
  2314. * DigestAlgorithm enum.
  2315. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  2316. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  2317. * an async Promise.
  2318. * @return {Promise|SyncPromise} A promise which returns the signature Blob (or
  2319. * an isNull Blob if the key does not exist), or a promise rejected
  2320. * with TpmBackEnd.Error for an error in signing.
  2321. */
  2322. KeyChain.prototype.signBufferPromise_ = function
  2323. (buffer, keyName, digestAlgorithm, useSync)
  2324. {
  2325. if (keyName.equals(SigningInfo.getDigestSha256Identity())) {
  2326. var hash = Crypto.createHash('sha256');
  2327. hash.update(buffer);
  2328. return SyncPromise.resolve(new Blob(hash.digest(), false));
  2329. }
  2330. return this.tpm_.signPromise(buffer, keyName, digestAlgorithm, useSync);
  2331. };
  2332. // Private security v1 methods
  2333. KeyChain.prototype.onCertificateData = function(interest, data, nextStep)
  2334. {
  2335. // Try to verify the certificate (data) according to the parameters in nextStep.
  2336. this.verifyData
  2337. (data, nextStep.onVerified, nextStep.onValidationFailed, nextStep.stepCount);
  2338. };
  2339. KeyChain.prototype.onCertificateInterestTimeout = function
  2340. (interest, retry, onValidationFailed, originalDataOrInterest, nextStep)
  2341. {
  2342. if (retry > 0) {
  2343. // Issue the same expressInterest as in verifyData except decrement retry.
  2344. var thisKeyChain = this;
  2345. this.face_.expressInterest
  2346. (interest,
  2347. function(callbackInterest, callbackData) {
  2348. thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
  2349. },
  2350. function(callbackInterest) {
  2351. thisKeyChain.onCertificateInterestTimeout
  2352. (callbackInterest, retry - 1, onValidationFailed,
  2353. originalDataOrInterest, nextStep);
  2354. });
  2355. }
  2356. else {
  2357. try {
  2358. onValidationFailed
  2359. (originalDataOrInterest, "The retry count is zero after timeout for fetching " +
  2360. interest.getName().toUri());
  2361. } catch (ex) {
  2362. console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
  2363. }
  2364. }
  2365. };
  2366. /**
  2367. * Get the default certificate from the identity storage and return its name.
  2368. * If there is no default identity or default certificate, then create one.
  2369. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  2370. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  2371. * an async Promise.
  2372. * @return {Promise|SyncPromise} A promise that returns the default certificate
  2373. * name.
  2374. */
  2375. KeyChain.prototype.prepareDefaultCertificateNamePromise_ = function(useSync)
  2376. {
  2377. var signingCertificate;
  2378. var thisKeyChain = this;
  2379. return this.identityManager_.getDefaultCertificatePromise(useSync)
  2380. .then(function(localCertificate) {
  2381. signingCertificate = localCertificate;
  2382. if (signingCertificate != null)
  2383. return SyncPromise.resolve();
  2384. // Set the default certificate and get the certificate again.
  2385. return thisKeyChain.setDefaultCertificatePromise_(useSync)
  2386. .then(function() {
  2387. return thisKeyChain.identityManager_.getDefaultCertificatePromise(useSync);
  2388. })
  2389. .then(function(localCertificate) {
  2390. signingCertificate = localCertificate;
  2391. return SyncPromise.resolve();
  2392. });
  2393. })
  2394. .then(function() {
  2395. return SyncPromise.resolve(signingCertificate.getName());
  2396. });
  2397. }
  2398. /**
  2399. * Create the default certificate if it is not initialized. If there is no
  2400. * default identity yet, creating a new tmp-identity.
  2401. * @param {boolean} useSync (optional) If true then return a SyncPromise which
  2402. * is already fulfilled. If omitted or false, this may return a SyncPromise or
  2403. * an async Promise.
  2404. * @return {Promise|SyncPromise} A promise that resolves when the default
  2405. * certificate is set.
  2406. */
  2407. KeyChain.prototype.setDefaultCertificatePromise_ = function(useSync)
  2408. {
  2409. var thisKeyChain = this;
  2410. return this.identityManager_.getDefaultCertificatePromise(useSync)
  2411. .then(function(certificate) {
  2412. if (certificate != null)
  2413. // We already have a default certificate.
  2414. return SyncPromise.resolve();
  2415. var defaultIdentity;
  2416. return thisKeyChain.identityManager_.getDefaultIdentityPromise(useSync)
  2417. .then(function(localDefaultIdentity) {
  2418. defaultIdentity = localDefaultIdentity;
  2419. return SyncPromise.resolve();
  2420. }, function(ex) {
  2421. // Create a default identity name.
  2422. randomComponent = Crypto.randomBytes(4);
  2423. defaultIdentity = new Name().append("tmp-identity")
  2424. .append(new Blob(randomComponent, false));
  2425. return SyncPromise.resolve();
  2426. })
  2427. .then(function() {
  2428. return thisKeyChain.identityManager_.createIdentityAndCertificatePromise
  2429. (defaultIdentity, KeyChain.getDefaultKeyParams(), useSync);
  2430. })
  2431. .then(function() {
  2432. return thisKeyChain.identityManager_.setDefaultIdentityPromise
  2433. (defaultIdentity, useSync);
  2434. });
  2435. });
  2436. };
  2437. KeyChain.defaultPibLocator_ = null // string
  2438. KeyChain.defaultTpmLocator_ = null // string
  2439. KeyChain.pibFactories_ = null // string => MakePibImpl
  2440. KeyChain.tpmFactories_ = null // string => MakeTpmBackEnd
  2441. KeyChain.defaultSigningInfo_ = new SigningInfo();
  2442. KeyChain.defaultKeyParams_ = new RsaKeyParams();
  2443. /**
  2444. * Create an InvalidSigningInfoError which extends KeyChain.Error to indicate
  2445. * that the supplied SigningInfo is invalid.
  2446. * Call with: throw new InvalidSigningInfoError(new Error("message")).
  2447. * @param {Error} error The exception created with new Error.
  2448. * @constructor
  2449. */
  2450. var InvalidSigningInfoError = function InvalidSigningInfoError(error)
  2451. {
  2452. // Call the base constructor.
  2453. KeyChain.Error.call(this, error);
  2454. }
  2455. InvalidSigningInfoError.prototype = new KeyChain.Error();
  2456. InvalidSigningInfoError.prototype.name = "InvalidSigningInfoError";
  2457. exports.InvalidSigningInfoError = InvalidSigningInfoError;
  2458. exports.InvalidSigningInfoError = InvalidSigningInfoError;
  2459. /**
  2460. * Create a LocatorMismatchError which extends KeyChain.Error to indicate that
  2461. * the supplied TPM locator does not match the locator stored in the PIB.
  2462. * Call with: throw new LocatorMismatchError(new Error("message")).
  2463. * @param {Error} error The exception created with new Error.
  2464. * @constructor
  2465. */
  2466. var LocatorMismatchError = function LocatorMismatchError(error)
  2467. {
  2468. // Call the base constructor.
  2469. KeyChain.Error.call(this, error);
  2470. }
  2471. LocatorMismatchError.prototype = new KeyChain.Error();
  2472. LocatorMismatchError.prototype.name = "LocatorMismatchError";
  2473. exports.LocatorMismatchError = LocatorMismatchError;
  2474. // Put these last to avoid a require loop.
  2475. /** @ignore */
  2476. var Pib = require('./pib/pib.js').Pib; /** @ignore */
  2477. var PibImpl = require('./pib/pib-impl.js').PibImpl; /** @ignore */
  2478. var PibKey = require('./pib/pib-key.js').PibKey; /** @ignore */
  2479. var PibSqlite3 = require('./pib/pib-sqlite3.js').PibSqlite3; /** @ignore */
  2480. var PibMemory = require('./pib/pib-memory.js').PibMemory;