UNPKG

ndn-js

Version:

A JavaScript client library for Named Data Networking

320 lines (287 loc) 11.8 kB
/** * Copyright (C) 2014-2019 Regents of the University of California. * @author: Jeff Thompson <jefft0@remap.ucla.edu> * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * A copy of the GNU Lesser General Public License is in the file COPYING. */ /** @ignore */ var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */ var DerNode = require('../../encoding/der/der-node.js').DerNode; /** * PrivateKeyStorage is an abstract class which declares methods for working * with a private key storage. You should use a subclass. * @constructor */ var PrivateKeyStorage = function PrivateKeyStorage() { }; exports.PrivateKeyStorage = PrivateKeyStorage; /** * Generate a pair of asymmetric keys. * @param {Name} keyName The name of the key pair. * @param {KeyParams} params The parameters of the key. * @param {boolean} (optional) useSync If true then return a SyncPromise which * is already fulfilled. If omitted or false, this may return a SyncPromise or * an async Promise. * @return {Promise|SyncPromise} A promise that fulfills when the pair is * generated. */ PrivateKeyStorage.prototype.generateKeyPairPromise = function (keyName, params, useSync) { return SyncPromise.reject(new Error ("PrivateKeyStorage.generateKeyPairPromise is not implemented")); }; /** * Generate a pair of asymmetric keys. * @param {Name} keyName The name of the key pair. * @param {KeyParams} params The parameters of the key. * @throws Error If generateKeyPairPromise doesn't return a SyncPromise which * is already fulfilled. */ PrivateKeyStorage.prototype.generateKeyPair = function(keyName, params) { SyncPromise.getValue(this.generateKeyPairPromise(keyName, params, true)); }; /** * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing. * @param {Name} keyName The name of the key pair. * @param {boolean} useSync (optional) If true then return a SyncPromise which * is already fulfilled. If omitted or false, this may return a SyncPromise or * an async Promise. * @return {Promise|SyncPromise} A promise that fulfills when the key pair is * deleted. */ PrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName, useSync) { return SyncPromise.reject(new Error ("PrivateKeyStorage.deleteKeyPairPromise is not implemented")); }; /** * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing. * @param {Name} keyName The name of the key pair. * @throws Error If deleteKeyPairPromise doesn't return a SyncPromise which * is already fulfilled. */ PrivateKeyStorage.prototype.deleteKeyPair = function(keyName) { SyncPromise.getValue(this.deleteKeyPairPromise(keyName, true)); }; /** * Get the public key * @param {Name} keyName The name of public key. * @param {boolean} useSync (optional) If true then return a SyncPromise which * is already fulfilled. If omitted or false, this may return a SyncPromise or * an async Promise. * @return {Promise|SyncPromise} A promise that returns the PublicKey. */ PrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName, useSync) { return SyncPromise.reject(new Error ("PrivateKeyStorage.getPublicKeyPromise is not implemented")); }; /** * Get the public key * @param {Name} keyName The name of public key. * @return {PublicKey} The public key. * @throws Error If getPublicKeyPromise doesn't return a SyncPromise which * is already fulfilled. */ PrivateKeyStorage.prototype.getPublicKey = function(keyName) { return SyncPromise.getValue(this.getPublicKeyPromise(keyName, true)); }; /** * Fetch the private key for keyName and sign the data to produce a signature Blob. * @param {Buffer} data Pointer to the input byte array. * @param {Name} keyName The name of the signing key. * @param {number} digestAlgorithm (optional) The digest algorithm from * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use * DigestAlgorithm.SHA256. * @param {boolean} useSync (optional) If true then return a SyncPromise which * is already fulfilled. If omitted or false, this may return a SyncPromise or * an async Promise. * @return {Promise|SyncPromise} A promise that returns the signature Blob. */ PrivateKeyStorage.prototype.signPromise = function (data, keyName, digestAlgorithm, useSync) { return SyncPromise.reject(new Error("PrivateKeyStorage.sign is not implemented")); }; /** * Fetch the private key for keyName and sign the data to produce a signature Blob. * @param {Buffer} data Pointer to the input byte array. * @param {Name} keyName The name of the signing key. * @param {number} digestAlgorithm (optional) The digest algorithm from * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use * DigestAlgorithm.SHA256. * @return {Blob} The signature Blob. * @throws Error If signPromise doesn't return a SyncPromise which is already * fulfilled. */ PrivateKeyStorage.prototype.sign = function(data, keyName, digestAlgorithm) { return SyncPromise.getValue (this.signPromise(data, keyName, digestAlgorithm, true)); }; /** * Decrypt data. * @param {Name} keyName The name of the decrypting key. * @param {Buffer} data The byte to be decrypted. * @param {boolean} isSymmetric (optional) If true symmetric encryption is used, * otherwise asymmetric encryption is used. If omitted, use asymmetric * encryption. * @return {Blob} The decrypted data. */ PrivateKeyStorage.prototype.decrypt = function(keyName, data, isSymmetric) { throw new Error("PrivateKeyStorage.decrypt is not implemented"); }; /** * Encrypt data. * @param {Name} keyName The name of the encrypting key. * @param {Buffer} data The byte to be encrypted. * @param {boolean} isSymmetric (optional) If true symmetric encryption is used, * otherwise asymmetric encryption is used. If omitted, use asymmetric * encryption. * @return {Blob} The encrypted data. */ PrivateKeyStorage.prototype.encrypt = function(keyName, data, isSymmetric) { throw new Error("PrivateKeyStorage.encrypt is not implemented"); }; /** * Generate a symmetric key. * @param {Name} keyName The name of the key. * @param {KeyParams} params The parameters of the key. */ PrivateKeyStorage.prototype.generateKey = function(keyName, params) { throw new Error("PrivateKeyStorage.generateKey is not implemented"); }; /** * Check if a particular key exists. * @param {Name} keyName The name of the key. * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC, * KeyClass.PRIVATE, or KeyClass.SYMMETRIC. * @param {boolean} useSync (optional) If true then return a SyncPromise which * is already fulfilled. If omitted or false, this may return a SyncPromise or * an async Promise. * @return {Promise|SyncPromise} A promise which returns true if the key exists. */ PrivateKeyStorage.prototype.doesKeyExistPromise = function (keyName, keyClass, useSync) { return SyncPromise.reject(new Error ("PrivateKeyStorage.doesKeyExist is not implemented")); }; /** * Check if a particular key exists. * @param {Name} keyName The name of the key. * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC, * KeyClass.PRIVATE, or KeyClass.SYMMETRIC. * @return {boolean} True if the key exists. * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which * is already fulfilled. */ PrivateKeyStorage.prototype.doesKeyExist = function(keyName, keyClass) { return SyncPromise.getValue(this.doesKeyExistPromise(keyName, keyClass, true)); }; /** * Encode the private key to a PKCS #8 private key. We do this explicitly here * to avoid linking to extra OpenSSL libraries. * @param {Buffer} privateKeyDer The input private key DER. * @param {OID} oid The OID of the privateKey. * @param {DerNode} parameters The DerNode of the parameters for the OID. * @return {Blob} The PKCS #8 private key DER. */ PrivateKeyStorage.encodePkcs8PrivateKey = function (privateKeyDer, oid, parameters) { var algorithmIdentifier = new DerNode.DerSequence(); algorithmIdentifier.addChild(new DerNode.DerOid(oid)); algorithmIdentifier.addChild(parameters); var result = new DerNode.DerSequence(); result.addChild(new DerNode.DerInteger(0)); result.addChild(algorithmIdentifier); result.addChild(new DerNode.DerOctetString(privateKeyDer)); return result.encode(); }; /** * Encode the RSAKey private key as a PKCS #1 private key. * @param {RSAKey} rsaKey The RSAKey private key. * @return {Blob} The PKCS #1 private key DER. */ PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey = function(rsaKey) { // Imitate KJUR getEncryptedPKCS5PEMFromRSAKey. var result = new DerNode.DerSequence(); result.addChild(new DerNode.DerInteger(0)); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n))); result.addChild(new DerNode.DerInteger(rsaKey.e)); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.d))); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.p))); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.q))); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmp1))); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmq1))); result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.coeff))); return result.encode(); }; /** * Encode the public key values in the RSAKey private key as a * SubjectPublicKeyInfo. * @param {RSAKey} rsaKey The RSAKey private key with the public key values. * @return {Blob} The SubjectPublicKeyInfo DER. */ PrivateKeyStorage.encodePublicKeyFromRSAKey = function(rsaKey) { var rsaPublicKey = new DerNode.DerSequence(); rsaPublicKey.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n))); rsaPublicKey.addChild(new DerNode.DerInteger(rsaKey.e)); var algorithmIdentifier = new DerNode.DerSequence(); algorithmIdentifier.addChild (new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID))); algorithmIdentifier.addChild(new DerNode.DerNull()); var result = new DerNode.DerSequence(); result.addChild(algorithmIdentifier); result.addChild(new DerNode.DerBitString(rsaPublicKey.encode().buf(), 0)); return result.encode(); }; /** * Convert a BigInteger to a Buffer. * @param {BigInteger} bigInteger The BigInteger. * @return {Buffer} The Buffer. */ PrivateKeyStorage.bigIntegerToBuffer = function(bigInteger) { // Imitate KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex. var hex = bigInteger.toString(16); if (hex.substr(0, 1) == "-") throw new Error ("PrivateKeyStorage.bigIntegerToBuffer: Negative integers are not currently supported"); if (hex.length % 2 == 1) // Odd number of characters. hex = "0" + hex; else { if (! hex.match(/^[0-7]/)) // The first byte is >= 0x80, so prepend a zero to keep it positive. hex = "00" + hex; } return new Buffer(hex, 'hex'); }; PrivateKeyStorage.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1"; PrivateKeyStorage.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";