diff --git a/.gitignore b/.gitignore index 2991eedd3d..95efa1fa76 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ tmp .DS_Store fabric-client/.DS_Store fabric-ca-client/.DS_Store -test/fixtures/src/github.com/example_cc/junk.go \ No newline at end of file +test/fixtures/src/github.com/example_cc/junk.go diff --git a/fabric-ca-client/lib/FabricCAClientImpl.js b/fabric-ca-client/lib/FabricCAClientImpl.js index 0116cbedce..1a80e2d3cc 100644 --- a/fabric-ca-client/lib/FabricCAClientImpl.js +++ b/fabric-ca-client/lib/FabricCAClientImpl.js @@ -64,9 +64,9 @@ var FabricCAServices = class { this.cryptoPrimitives = cryptoSuite; } else { this.cryptoPrimitives = utils.newCryptoSuite(); + this.cryptoPrimitives.setCryptoKeyStore(utils.newCryptoKeyStore()); } - this._fabricCAClient = new FabricCAClient({ caname: caName, protocol: endpoint.protocol, diff --git a/fabric-client/lib/Client.js b/fabric-client/lib/Client.js index 7be0aec2f6..985ca1e505 100644 --- a/fabric-client/lib/Client.js +++ b/fabric-client/lib/Client.js @@ -27,10 +27,9 @@ var Packager = require('./Packager.js'); var Peer = require('./Peer.js'); var Orderer = require('./Orderer.js'); var MSP = require('./msp/msp.js'); -var MSPManager = require('./msp/msp-manager.js'); + var logger = sdkUtils.getLogger('Client.js'); var util = require('util'); -var path = require('path'); var fs = require('fs-extra'); var Constants = require('./Constants.js'); @@ -73,7 +72,19 @@ var Client = class { } /** - * Returns a new instance of the CryptoSuite API implementation + * Returns a new instance of the CryptoSuite API implementation. + * + * Creating a new CryptoSuite is optional and should be used if options other than defaults are needed. + * This instance should be set on the User and the Fabric CA Client. + * + * If not specified, an instance of {@link CryptoSuite} will be constructed based on the current configuration settings: + * crypto-hsm: use an implementation for Hardware Security Module (if set to true) or software-based key management (if set to false) + * crypto-keysize: security level, or key size, to use with the digital signature public key algorithm. Currently ECDSA + * is supported and the valid key sizes are 256 and 384 + * crypto-hash-algo: hashing algorithm + * key-value-store: some CryptoSuite implementation requires a key store to persist private keys. A {@link CryptoKeyStore} + * is provided for this purpose, which can be used on top of any implementation of the {@link KeyValueStore} interface, + * such as a file-based store or a database-based one. The specific implementation is determined by the value of this configuration setting. * * @param {object} setting This optional parameter is an object with the following optional properties: * - software {boolean}: Whether to load a software-based implementation (true) or HSM implementation (false) @@ -82,14 +93,10 @@ var Client = class { * - keysize {number}: The key size to use for the crypto suite instance. default is value of the setting 'crypto-keysize' * - algorithm {string}: Digital signature algorithm, currently supporting ECDSA only with value "EC" * - hash {string}: 'SHA2' or 'SHA3' - * @param {function} KVSImplClass Optional. The built-in key store saves private keys. The key store may be backed by different - * {@link KeyValueStore} implementations. If specified, the value of the argument must point to a module implementing the - * KeyValueStore interface. - * @param {object} opts Implementation-specific option object used in the constructor * returns a new instance of the CryptoSuite API implementation */ - newCryptoSuite(setting, KVSImplClass, opts) { - this._cryptoSuite = sdkUtils.newCryptoSuite(setting, KVSImplClass, opts); + newCryptoSuite(setting) { + this._cryptoSuite = sdkUtils.newCryptoSuite(setting); return this._cryptoSuite; } @@ -101,6 +108,24 @@ var Client = class { return this._cryptoSuite; } + /** + * Returns a new instance of the CryptoKeyStore. + * + * When the application needs to use a key store other than the default, + * it should create a new CryptoKeyStore and set it on the CryptoSuite. + * + * cryptosuite.setCryptoKeyStore(client.newCryptoKeyStore(KVSImplClass, opts)) + * + * @param {function} KVSImplClass Optional. The built-in key store saves private keys. The key store may be backed by different + * {@link KeyValueStore} implementations. If specified, the value of the argument must point to a module implementing the + * KeyValueStore interface. + * @param {object} opts Implementation-specific option object used in the constructor + * returns a new instance of the CryptoKeystore + */ + newCryptoKeyStore (KVSImplClass, opts) { + return sdkUtils.newCryptoKeyStore(KVSImplClass, opts); + } + /** * Determine if dev mode is enabled. */ @@ -1052,14 +1077,19 @@ var Client = class { (!opts.cryptoContent.privateKeyPEM || !opts.cryptoContent.signedCertPEM)) { return Promise.reject(new Error('Client.createUser both parameters \'opts cryptoContent privateKeyPEM and signedCertPEM\' strings are required.')); } - } else { return Promise.reject(new Error('Client.createUser parameter \'opts cryptoContent\' is required.')); } if (this._cryptoSuite == null) { + logger.debug('cryptoSuite is null, creating default cryptoSuite and cryptoKeyStore'); this._cryptoSuite = sdkUtils.newCryptoSuite(); + this._cryptoSuite.setCryptoKeyStore(this.newCryptoKeyStore()); + } else { + if (this._cryptoSuite._cryptoKeyStore) logger.debug('cryptoSuite has a cryptoKeyStore'); + else logger.info('cryptoSuite does not have a cryptoKeyStore'); } + var self = this; return new Promise((resolve, reject) => { logger.info('loading user from files'); @@ -1073,14 +1103,19 @@ var Client = class { // first load the private key and save in the BCCSP's key store var promise, member, importedKey; + if (opts.cryptoContent.privateKey) { promise = readFile(opts.cryptoContent.privateKey); } else { promise = Promise.resolve(opts.cryptoContent.privateKeyPEM); } promise.then((data) => { - logger.debug('then privateKeyPEM data'); - return self._cryptoSuite.importKey(data.toString()); + if (data) { + logger.debug('then privateKeyPEM data'); + return self._cryptoSuite.importKey(data.toString()); + } else { + throw new Error('failed to load private key data'); + } }).then((key) => { logger.debug('then key'); importedKey = key; @@ -1260,4 +1295,4 @@ function _getChaincodePackageData(request, devMode) { }); } -module.exports = Client; +module.exports = Client; \ No newline at end of file diff --git a/fabric-client/lib/User.js b/fabric-client/lib/User.js index 04447c2bf9..cbdf70fb24 100644 --- a/fabric-client/lib/User.js +++ b/fabric-client/lib/User.js @@ -24,7 +24,6 @@ var idModule = require('./msp/identity.js'); var Identity = idModule.Identity; var SigningIdentity = idModule.SigningIdentity; var Signer = idModule.Signer; -var LocalMSP = require('./msp/msp.js'); /** * The User class represents users that have been enrolled and represented by @@ -71,7 +70,7 @@ var User = class { this._enrollmentSecret = ''; this._identity = null; this._signingIdentity = null; - this._mspImpl = null; + this._mspId = ''; this._cryptoSuite = null; } @@ -135,6 +134,15 @@ var User = class { return this._cryptoSuite; } + /** + * Set the cryptoSuite. + * + * When the application needs to use crypto settings or a key store other than the default, + * it needs to set a cryptoSuite instance that was created with the desired CryptoSuite + * settings and CryptoKeyStore options. + * + * @param {CryptoSuite} cryptoSuite The cryptoSuite. + */ setCryptoSuite(cryptoSuite) { this._cryptoSuite = cryptoSuite; } @@ -144,18 +152,6 @@ var User = class { * @param {Key} privateKey the private key object * @param {string} certificate the PEM-encoded string of certificate * @param {string} mspId The Member Service Provider id for the local signing identity - * @param {object} opts optional. an object with the following attributes, all optional: - * - cryptoSettings: {object} an object with the following attributes: - * - software {boolean}: Whether to load a software-based implementation (true) or HSM implementation (false) - * default is true (for software based implementation), specific implementation module is specified - * in the setting 'crypto-suite-software' - * - keysize {number}: The key size to use for the crypto suite instance. default is value of the setting 'crypto-keysize' - * - algorithm {string}: Digital signature algorithm, currently supporting ECDSA only with value "EC" - * - hash {string}: 'SHA2' or 'SHA3' - * - KVSImplClass: {function} the User class persists crypto keys in a {@link CryptoKeyStore}, there is a file-based implementation - * that is provided as the default. Application can use this parameter to override the default, such as saving the keys in a key store - * backed by database. If present, the value must be the class for the alternative implementation. - * - kvsOpts: {object}: an options object specific to the implementation in KVSImplClass * @returns {Promise} Promise for successful completion of creating the user's signing Identity */ setEnrollment(privateKey, certificate, mspId) { @@ -171,19 +167,18 @@ var User = class { throw new Error('Invalid parameter. Must have a valid mspId.'); } + this._mspId = mspId; + if (!this._cryptoSuite) { this._cryptoSuite = sdkUtils.newCryptoSuite(); + this._cryptoSuite.setCryptoKeyStore(sdkUtils.newCryptoKeyStore()); } - this._mspImpl = new LocalMSP({ - id: mspId, - cryptoSuite: this._cryptoSuite - }); - return this._mspImpl.cryptoSuite.importKey(certificate) + return this._cryptoSuite.importKey(certificate) .then((pubKey) => { - var identity = new Identity('testIdentity', certificate, pubKey, this._mspImpl); + var identity = new Identity(certificate, pubKey, mspId, this._cryptoSuite); this._identity = identity; - this._signingIdentity = new SigningIdentity('testSigningIdentity', certificate, pubKey, this._mspImpl, new Signer(this._mspImpl.cryptoSuite, privateKey)); + this._signingIdentity = new SigningIdentity(certificate, pubKey, mspId, this._cryptoSuite, new Signer(this._cryptoSuite, privateKey)); }); } @@ -215,39 +210,36 @@ var User = class { if (typeof state.mspid === 'undefined' || state.mspid === null || state.mspid === '') { throw new Error('Failed to find "mspid" in the deserialized state object for the user. Likely due to an outdated state store.'); } + this._mspId = state.mspid; if (!this._cryptoSuite) { this._cryptoSuite = sdkUtils.newCryptoSuite(); + this._cryptoSuite.setCryptoKeyStore(sdkUtils.newCryptoKeyStore()); } - this._mspImpl = new LocalMSP({ - id: state.mspid, - cryptoSuite: this._cryptoSuite - }); - var self = this; var pubKey; - return this._mspImpl.cryptoSuite.importKey(state.enrollment.identity.certificate, { algorithm: api.CryptoAlgorithms.X509Certificate }) + return this._cryptoSuite.importKey(state.enrollment.identity.certificate, { algorithm: api.CryptoAlgorithms.X509Certificate }) .then((key) => { pubKey = key; - var identity = new Identity(state.enrollment.identity.id, state.enrollment.identity.certificate, pubKey, self._mspImpl); + var identity = new Identity( state.enrollment.identity.certificate, pubKey, self._mspId, this._cryptoSuite); self._identity = identity; // during serialization (see toString() below) only the key's SKI are saved // swap out that for the real key from the crypto provider - return self._mspImpl.cryptoSuite.getKey(state.enrollment.signingIdentity); + return self._cryptoSuite.getKey(state.enrollment.signingIdentity); }).then((privateKey) => { // the key retrieved from the key store using the SKI could be a public key // or a private key, check to make sure it's a private key if (privateKey.isPrivate()) { self._signingIdentity = new SigningIdentity( - state.enrollment.identity.id, state.enrollment.identity.certificate, pubKey, - self._mspImpl, - new Signer(self._mspImpl.cryptoSuite, privateKey)); + self._mspId, + self._cryptoSuite, + new Signer(self._cryptoSuite, privateKey)); return self; } else { @@ -268,14 +260,13 @@ var User = class { if (this._identity) { serializedEnrollment.identity = { - id: this._identity.getId(), certificate: this._identity._certificate }; } var state = { name: this._name, - mspid: this._mspImpl ? this._mspImpl.getId() : 'null', + mspid: this._mspId, roles: this._roles, affiliation: this._affiliation, enrollmentSecret: this._enrollmentSecret, diff --git a/fabric-client/lib/impl/CryptoKeyStore.js b/fabric-client/lib/impl/CryptoKeyStore.js index 3919c733e0..6892f6596f 100644 --- a/fabric-client/lib/impl/CryptoKeyStore.js +++ b/fabric-client/lib/impl/CryptoKeyStore.js @@ -20,7 +20,7 @@ var jsrsasign = require('jsrsasign'); var KEYUTIL = jsrsasign.KEYUTIL; var api = require('../api.js'); -var utils = require('../utils'); +var utils = require('../utils.js'); var ECDSAKey = require('./ecdsa/key.js'); var logger = utils.getLogger('CryptoKeyStore.js'); @@ -104,4 +104,4 @@ function _getKeyIndex(ski, isPrivateKey) { return ski + '-pub'; } -module.exports = CryptoKeyStore; \ No newline at end of file +module.exports = CryptoKeyStore; diff --git a/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js b/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js index 9455225557..b1aed11829 100755 --- a/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js +++ b/fabric-client/lib/impl/CryptoSuite_ECDSA_AES.js @@ -27,13 +27,10 @@ var KEYUTIL = jsrsa.KEYUTIL; var util = require('util'); var BN = require('bn.js'); var Signature = require('elliptic/lib/elliptic/ec/signature.js'); -var path = require('path'); -const os = require('os'); var hashPrimitives = require('../hash.js'); var utils = require('../utils'); var ECDSAKey = require('./ecdsa/key.js'); -var CKS = require('./CryptoKeyStore.js'); var logger = utils.getLogger('crypto_ecdsa_aes'); @@ -49,53 +46,38 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { * constructor * * @param {number} keySize Key size for the ECDSA algorithm, can only be 256 or 384 - * @param {object} opts Implementation-specific options object for the {@link KeyValueStore} class to instantiate an instance - * @param {string} KVSImplClass Optional. The built-in key store saves private keys. The key store may be backed by different - * {@link KeyValueStore} implementations. If specified, the value of the argument must point to a module implementing the - * KeyValueStore interface. * @param {string} hash Optional. Hash algorithm, supported values are "SHA2" and "SHA3" */ - constructor(keySize, opts, KVSImplClass, hash) { - logger.debug('constructor, keySize: '+keySize+', opts: '+opts); + constructor(keySize, hash) { + logger.debug('constructor, keySize: '+keySize); super(); if (keySize !== 256 && keySize !== 384) { throw new Error('Illegal key size: ' + keySize + ' - this crypto suite only supports key sizes 256 or 384'); } - if (typeof hash === 'string' && hash !== null && hash !== '') { this._hashAlgo = hash; } else { this._hashAlgo = utils.getConfigSetting('crypto-hash-algo'); } + this._keySize = keySize; + this._cryptoKeyStore = null; - if (typeof opts === 'undefined' || opts === null) { - opts = { - path: CryptoSuite_ECDSA_AES.getDefaultKeyStorePath() - }; - } - - var superClass; + this._initialize(); - if (typeof KVSImplClass !== 'undefined' && KVSImplClass !== null) { - if (typeof KVSImplClass !== 'function') { - throw new Error('Super class for the key store must be a module.'); - } else { - superClass = KVSImplClass; - } - } else { - // no super class specified, use the default key value store implementation - superClass = require(utils.getConfigSetting('key-value-store')); - logger.debug('constructor, no super class specified, config: '+utils.getConfigSetting('key-value-store')); - } + } - this._keySize = keySize; - this._store = null; - this._storeConfig = { - superClass: superClass, - opts: opts - }; - this._initialize(); + /** + * Set the cryptoKeyStore. + * + * When the application needs to use a key store other than the default, + * it should use the {@link Client} newCryptoKeyStore to create an instance and + * use this function to set the instance on the CryptoSuite. + * + * @param {CryptoKeyStore} cryptoKeyStore The cryptoKeyStore. + */ + setCryptoKeyStore(cryptoKeyStore) { + this._cryptoKeyStore = cryptoKeyStore; } _initialize() { @@ -141,8 +123,10 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { /** * This is an implementation of {@link module:api.CryptoSuite#generateKey} * Returns an instance of {@link module.api.Key} representing the private key, which also - * encapsulates the public key. It'll also save the private key in the KeyValueStore + * encapsulates the public key. It'll also save the private key in the KeyValueStore. * + * @param {object} opts Optional. + * *
`ephemeral`: {boolean} Optional. If not set, defaults to saving the key. If true, will not save the key. * @returns {Key} Promise of an instance of {@link module:ECDSA_KEY} containing the private key and the public key */ generateKey(opts) { @@ -151,12 +135,15 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { if (typeof opts !== 'undefined' && typeof opts.ephemeral !== 'undefined' && opts.ephemeral === true) { return Promise.resolve(new ECDSAKey(pair.prvKeyObj)); } else { + if (!this._cryptoKeyStore) { + throw new Error('generateKey opts.ephemeral is false, which requires CryptoKeyStore to be set.'); + } // unless "opts.ephemeral" is explicitly set to "true", default to saving the key var key = new ECDSAKey(pair.prvKeyObj); var self = this; return new Promise((resolve, reject) => { - self._getKeyStore() + self._cryptoKeyStore._getKeyStore() .then ((store) => { logger.debug('generateKey, store.setValue'); return store.putKey(key) @@ -166,6 +153,7 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { reject(err); }); }); + }); } } @@ -189,6 +177,9 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { if(typeof storeKey === 'boolean') { store_key = storeKey; } + if (!!store_key && !this._cryptoKeyStore) { + throw new Error('importKey storeKey is true, which requires CryptoKeyStore to be set.'); + } var self = this; // attempt to import the raw content, assuming it's one of the following: @@ -231,7 +222,7 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { return Promise.reject(error); } return new Promise((resolve, reject) => { - return self._getKeyStore() + return self._cryptoKeyStore._getKeyStore() .then ((store) => { return store.putKey(theKey); }).then(() => { @@ -239,6 +230,7 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { }).catch((err) => { reject(err); }); + }); } } @@ -251,8 +243,11 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { var self = this; var store; + if (!self._cryptoKeyStore) { + throw new Error('getKey requires CryptoKeyStore to be set.'); + } return new Promise((resolve, reject) => { - self._getKeyStore() + self._cryptoKeyStore._getKeyStore() .then ((st) => { store = st; return store.getKey(ski); @@ -267,27 +262,7 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { }).catch((err) => { reject(err); }); - }); - } - _getKeyStore() { - var self = this; - return new Promise((resolve, reject) => { - if (self._store === null) { - logger.info(util.format('This class requires a CryptoKeyStore to save keys, using the store: %j', self._storeConfig)); - - CKS(self._storeConfig.superClass, self._storeConfig.opts) - .then((ks) => { - logger.debug('_getKeyStore returning ks'); - self._store = ks; - return resolve(self._store); - }).catch((err) => { - reject(err); - }); - } else { - logger.debug('_getKeyStore resolving store'); - return resolve(self._store); - } }); } @@ -368,10 +343,6 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite { decrypt(key, cipherText, opts) { throw new Error('Not implemented yet'); } - - static getDefaultKeyStorePath() { - return path.join(os.homedir(), '.hfc-key-store'); - } }; // [Angelo De Caro] ECDSA signatures do not have unique representation and this can facilitate diff --git a/fabric-client/lib/impl/bccsp_pkcs11.js b/fabric-client/lib/impl/bccsp_pkcs11.js index e481295d7f..d713bf6d00 100644 --- a/fabric-client/lib/impl/bccsp_pkcs11.js +++ b/fabric-client/lib/impl/bccsp_pkcs11.js @@ -51,6 +51,7 @@ var CryptoSuite_PKCS11 = class extends api.CryptoSuite { /** * @param {number} keySize Length of key (in bytes), a.k.a "security level" + * @param {string} hash Optional. Hash algorithm, supported values are "SHA2" and "SHA3" * @param {object} opts Option is the form { lib: string, slot: number, pin: string } * * If lib is not specified or null, its value will be taken from the @@ -65,7 +66,7 @@ var CryptoSuite_PKCS11 = class extends api.CryptoSuite { * CRYPTO_PKCS11_PIN env var, and if the env var is not set, its value will * be taken from the crypto-pkcs11-pin key in the configuration file. */ - constructor(keySize, opts) { + constructor(keySize, hash, opts) { if (typeof keySize === 'undefined' || keySize === null) throw new Error(__func() + 'keySize must be specified'); if (typeof keySize === 'string') keySize = parseInt(keySize, 10); diff --git a/fabric-client/lib/msp/identity.js b/fabric-client/lib/msp/identity.js index 668eef479a..809562d58f 100755 --- a/fabric-client/lib/msp/identity.js +++ b/fabric-client/lib/msp/identity.js @@ -16,14 +16,13 @@ var identityProto = grpc.load(__dirname + '/../protos/msp/identities.proto').msp */ var Identity = class { /** - * @param {string} id Identifier of this identity object * @param {string} certificate HEX string for the PEM encoded certificate * @param {Key} publicKey The public key represented by the certificate - * @param {MSP} msp The associated MSP that manages this identity + * @param {string} mspId The associated MSP's mspId that manages this identity + * @param {CryptoSuite} cryptoSuite The underlying {@link CryptoSuite} implementation for the digital + * signature algorithm */ - constructor(id, certificate, publicKey, msp) { - if (!id) - throw new Error('Missing required parameter "id".'); + constructor(certificate, publicKey, mspId, cryptoSuite) { if (!certificate) throw new Error('Missing required parameter "certificate".'); @@ -31,21 +30,16 @@ var Identity = class { if (!publicKey) throw new Error('Missing required parameter "publicKey".'); - if (!msp) - throw new Error('Missing required parameter "msp".'); + if (!mspId) + throw new Error('Missing required parameter "mspId".'); + + if (!cryptoSuite) + throw new Error('Missing required parameter "cryptoSuite".'); - this._id = id; this._certificate = certificate; this._publicKey = publicKey; - this._msp = msp; - } - - /** - * Returns the identifier of this identity - * @returns {string} - */ - getId() { - return this._id; + this._mspId = mspId; + this._cryptoSuite = cryptoSuite; } /** @@ -55,7 +49,7 @@ var Identity = class { * @returns {string} */ getMSPId() { - return this._msp.getId(); + return this._mspId; } /** @@ -66,7 +60,7 @@ var Identity = class { * @returns {boolean} */ isValid() { - return this._msp.validate(this); + return true; } /** @@ -94,7 +88,7 @@ var Identity = class { * @param {Object} opts Options include 'policy' and 'label' */ verify(msg, signature, opts) { - return this._msp.cryptoSuite.verify(this._publicKey, signature, msg); + return this._cryptoSuite.verify(this._publicKey, signature, msg); } /** @@ -177,15 +171,16 @@ var Signer = class { */ var SigningIdentity = class extends Identity { /** - * @param {string} id Identifier of this identity object * @param {string} certificate HEX string for the PEM encoded certificate * @param {Key} publicKey The public key represented by the certificate + * @param {string} mspId The associated MSP's ID that manages this identity + * @param {CryptoSuite} cryptoSuite The underlying {@link CryptoSuite} implementation for the digital + * signature algorithm * @param {Signer} signer The signer object encapsulating the opaque private key and the corresponding * digital signature algorithm to be used for signing operations - * @param {MSP} msp The associated MSP that manages this identity */ - constructor(id, certificate, publicKey, msp, signer) { - super(id, certificate, publicKey, msp); + constructor(certificate, publicKey, mspId, cryptoSuite, signer) { + super(certificate, publicKey, mspId, cryptoSuite); if (!signer) throw new Error('Missing required parameter "signer".'); @@ -211,7 +206,7 @@ var SigningIdentity = class extends Identity { hashFunction = opts.hashFunction; } else { - hashFunction = this._msp.cryptoSuite.hash.bind(this._msp.cryptoSuite); + hashFunction = this._cryptoSuite.hash.bind(this._cryptoSuite); } var digest = hashFunction(msg); diff --git a/fabric-client/lib/msp/msp-manager.js b/fabric-client/lib/msp/msp-manager.js index f336e977e3..ac822849db 100755 --- a/fabric-client/lib/msp/msp-manager.js +++ b/fabric-client/lib/msp/msp-manager.js @@ -79,6 +79,7 @@ var MSPManager = class { // TODO: for now using application-scope defaults but crypto parameters like key size, hash family // and digital signature algorithm should be from the config itself var cs = utils.newCryptoSuite(); + cs.setCryptoKeyStore(utils.newCryptoKeyStore()); // get the application org names var orgs = []; diff --git a/fabric-client/lib/msp/msp.js b/fabric-client/lib/msp/msp.js index beabecc8ba..86555b54da 100755 --- a/fabric-client/lib/msp/msp.js +++ b/fabric-client/lib/msp/msp.js @@ -147,15 +147,13 @@ var MSP = class { logger.debug('Encoded cert from deserialized identity: %s', cert); if(!store_key) { var publicKey =this.cryptoSuite.importKey(cert, { algorithm: api.CryptoAlgorithms.X509Certificate }, false); - // TODO: the id of the new Identity instance should probably be derived from the subject info in the cert? - var sdk_identity = new Identity('SomeDummyValue', cert, publicKey, this); + var sdk_identity = new Identity(cert, publicKey, this.getId(), this.cryptoSuite); return sdk_identity; } else { return this.cryptoSuite.importKey(cert, { algorithm: api.CryptoAlgorithms.X509Certificate }) .then((publicKey) => { - // TODO: the id of the new Identity instance should probably be derived from the subject info in the cert? - return new Identity('SomeDummyValue', cert, publicKey, this); + return new Identity(cert, publicKey, this.getId(), this.cryptoSuite); }); } } @@ -168,6 +166,7 @@ var MSP = class { validate(id) { return true; } + }; module.exports = MSP; diff --git a/fabric-client/lib/utils.js b/fabric-client/lib/utils.js index f29fd30a14..eb5734df4f 100644 --- a/fabric-client/lib/utils.js +++ b/fabric-client/lib/utils.js @@ -20,6 +20,8 @@ var util = require('util'); var winston = require('winston'); var fs = require('fs-extra'); var crypto = require('crypto'); +var path = require('path'); +var os = require('os'); var Config = require('./Config.js'); // @@ -42,13 +44,9 @@ var sha3_256 = require('js-sha3').sha3_256; // - algorithm {string}: Digital signature algorithm, currently supporting ECDSA only with value "EC" // - hash {string}: 'SHA2' or 'SHA3' // -// @param {function} KVSImplClass Optional. The built-in key store saves private keys. The key store may be backed by different -// {@link KeyValueStore} implementations. If specified, the value of the argument must point to a module implementing the -// KeyValueStore interface. -// @param {object} opts Implementation-specific option object used in the constructor // -module.exports.newCryptoSuite = function(setting, KVSImplClass, opts) { - var csImpl, keysize, algorithm, hashAlgo, haveSettings = false; +module.exports.newCryptoSuite = function(setting) { + var csImpl, keysize, algorithm, hashAlgo, opts = null; var useHSM = false; if (setting && typeof setting.software === 'boolean') { @@ -59,30 +57,25 @@ module.exports.newCryptoSuite = function(setting, KVSImplClass, opts) { csImpl = useHSM ? this.getConfigSetting('crypto-suite-hsm') : this.getConfigSetting('crypto-suite-software'); - // this function supports skipping any of the arguments such that it can be called in any of the following fashions: - // - newCryptoSuite({software: true, keysize: 256, algorithm: EC}, CouchDBKeyValueStore, {name: 'member_db', url: 'http://localhost:5984'}) - // - newCryptoSuite(CouchDBKeyValueStore, {name: 'member_db', url: 'http://localhost:5984'}) - // - newCryptoSuite({software: true, keysize: 256, algorithm: EC}, {path: '/tmp/app-state-store'}) - // - newCryptoSuite({software: false}, {lib: '/usr/local/bin/pkcs11.so', slot: 0, pin: '1234'}) + // this function supports the following: + // - newCryptoSuite({software: true, keysize: 256, algorithm: EC}) + // - newCryptoSuite({software: false, lib: '/usr/local/bin/pkcs11.so', slot: 0, pin: '1234'}) // - newCryptoSuite({keysize: 384}) // - newCryptoSuite() // step 1: what's the cryptosuite impl to use, key size and algo if (setting && setting.keysize && typeof setting === 'object' && typeof setting.keysize === 'number') { keysize = setting.keysize; - haveSettings = true; } else keysize = this.getConfigSetting('crypto-keysize'); if (setting && setting.algorithm && typeof setting === 'object' && typeof setting.algorithm === 'string') { algorithm = setting.algorithm.toUpperCase(); - haveSettings = true; } else algorithm = 'EC'; if (setting && setting.hash && typeof setting === 'object' && typeof setting.hash === 'string') { hashAlgo = setting.hash.toUpperCase(); - haveSettings = true; } else hashAlgo = null; @@ -92,37 +85,13 @@ module.exports.newCryptoSuite = function(setting, KVSImplClass, opts) { if (!csImpl) throw new Error(util.format('Desired CryptoSuite module not found supporting algorithm "%s"', algorithm)); - // expecting a path to an alternative implementation var cryptoSuite = require(csImpl); - // step 2: what's the super class to use for the crypto key store? - var keystoreSuperClass; - - if (typeof KVSImplClass === 'function') { - keystoreSuperClass = KVSImplClass; - } else { - keystoreSuperClass = null; - } + // the 'opts' argument to be passed or none at all + opts = (typeof setting === 'undefined') ? null : setting; - // step 3: what 'opts' object should be passed to the cryptosuite impl? - if (KVSImplClass && typeof opts === 'undefined') { - if (typeof KVSImplClass === 'function') { - // the super class module was passed in, but not the 'opts' - opts = null; - } else { - // called with only one argument for the 'opts' but KVSImplClass was skipped - opts = KVSImplClass; - } - } else if (typeof KVSImplClass === 'undefined' && typeof opts === 'undefined') { - if (haveSettings) { - // the function was called with only the 'settings' argument - opts = null; - } else { - // the function was called with only the 'opts' argument or none at all - opts = (typeof setting === 'undefined') ? null : setting; - } - } - return new cryptoSuite(keysize, opts, keystoreSuperClass, hashAlgo); + //opts Option is the form { lib: string, slot: number, pin: string } + return new cryptoSuite(keysize, hashAlgo, opts); }; // Provide a Promise-based keyValueStore for couchdb, etc. @@ -431,3 +400,75 @@ module.exports.readFile = function(path) { }); }); }; + +module.exports.getDefaultKeyStorePath = function() { + return path.join(os.homedir(), '.hfc-key-store'); +}; + +var CryptoKeyStore = function(KVSImplClass, opts) { + this.logger = module.exports.getLogger('utils.CryptoKeyStore'); + this.logger.debug('CryptoKeyStore, constructor - start'); + if (KVSImplClass && typeof opts === 'undefined') { + if (typeof KVSImplClass === 'function') { + // the super class module was passed in, but not the 'opts' + opts = null; + } else { + // called with only one argument for the 'opts' but KVSImplClass was skipped + opts = KVSImplClass; + KVSImplClass = null; + } + } + + if (typeof opts === 'undefined' || opts === null) { + opts = { + path: module.exports.getDefaultKeyStorePath() + }; + } + var superClass; + if (typeof KVSImplClass !== 'undefined' && KVSImplClass !== null) { + superClass = KVSImplClass; + } else { + // no super class specified, use the default key value store implementation + superClass = require(module.exports.getConfigSetting('key-value-store')); + this.logger.debug('constructor, no super class specified, using config: '+module.exports.getConfigSetting('key-value-store')); + } + + this._store = null; + this._storeConfig = { + superClass: superClass, + opts: opts + + }; + + this._getKeyStore = function() { + var CKS = require('./impl/CryptoKeyStore.js'); + + var self = this; + return new Promise((resolve, reject) => { + if (self._store === null) { + self.logger.info(util.format('This class requires a CryptoKeyStore to save keys, using the store: %j', self._storeConfig)); + + CKS(self._storeConfig.superClass, self._storeConfig.opts) + .then((ks) => { + self.logger.debug('_getKeyStore returning ks'); + self._store = ks; + return resolve(self._store); + }).catch((err) => { + reject(err); + }); + } else { + self.logger.debug('_getKeyStore resolving store'); + return resolve(self._store); + } + }); + }; + +}; + +module.exports.newCryptoKeyStore = function(KVSImplClass, opts) { + // this function supports skipping any of the arguments such that it can be called in any of the following fashions: + // - newCryptoKeyStore(CouchDBKeyValueStore, {name: 'member_db', url: 'http://localhost:5984'}) + // - newCryptoKeyStore({path: '/tmp/app-state-store'}) + // - newCryptoKeyStore() + return new CryptoKeyStore(KVSImplClass, opts); +}; diff --git a/test/integration/client.js b/test/integration/client.js index 93126c5306..977396b3ea 100644 --- a/test/integration/client.js +++ b/test/integration/client.js @@ -50,7 +50,9 @@ test('\n\n ** createUser happy path - file store **\n\n', function (t) { var keyStoreOpts = {path: path.join(testUtil.getTempDir(), caImport.orgs[userOrg].storePath)}; var client = new Client(); - var cryptoSuite = client.newCryptoSuite(keyStoreOpts); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore(keyStoreOpts)); + client.setCryptoSuite(cryptoSuite); logger.info('try to cleanup kvs Path: '+keyStoreOpts.path); // clean up @@ -107,7 +109,9 @@ test('\n\n ** createUser happy path - CouchDB **\n\n', function (t) { var sgnCert = path.join(__dirname, caImport.orgs[userOrg].cryptoContent.signedCert); var client = new Client(); - var cryptoSuite = client.newCryptoSuite(keyStoreOpts); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore(keyStoreOpts)); + client.setCryptoSuite(cryptoSuite); couchdbUtil.destroy(dbname, keyValStorePath) .then((status) => { @@ -160,7 +164,10 @@ test('\n\n ** createUser happy path - Cloudant **\n\n', function (t) { var sgnCert = path.join(__dirname, caImport.orgs[userOrg].cryptoContent.signedCert); var client = new Client(); - var cryptoSuite = client.newCryptoSuite(keyStoreOpts); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore(keyStoreOpts)); + client.setCryptoSuite(cryptoSuite); + couchdbUtil.destroy(dbname, cloudantUrl) .then((status) => { t.comment(tag+'Cleanup of existing ' + dbname + ' returned '+status); @@ -208,7 +215,10 @@ test('\n\n ** createUser happy path - Cloudant - PEM Strings **\n\n', function logger.info('cloudant keyStoreOpts: '+ JSON.stringify(keyStoreOpts)); var client = new Client(); - var cryptoSuite = client.newCryptoSuite(keyStoreOpts); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore(keyStoreOpts)); + client.setCryptoSuite(cryptoSuite); + couchdbUtil.destroy(dbname, cloudantUrl) .then((status) => { t.comment(tag+'Cleanup of existing ' + dbname + ' returned '+status); diff --git a/test/integration/cloudant-fabricca-tests.js b/test/integration/cloudant-fabricca-tests.js index d513f0955f..6bd8fc7b03 100644 --- a/test/integration/cloudant-fabricca-tests.js +++ b/test/integration/cloudant-fabricca-tests.js @@ -77,7 +77,9 @@ test('Use FabricCAServices wih a Cloudant CouchDB KeyValueStore', function(t) { function(kvs) { t.comment('Setting client keyValueStore to: ' + kvs); member = new User('admin2'); - cryptoSuite = client.newCryptoSuite(options); + cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore(options)); + client.setCryptoSuite(cryptoSuite); member.setCryptoSuite(cryptoSuite); t.comment('Setting client keyValueStore to: ' +kvs); diff --git a/test/integration/couchdb-fabricca-tests.js b/test/integration/couchdb-fabricca-tests.js index 6e8b124b48..dd3a3b13a3 100644 --- a/test/integration/couchdb-fabricca-tests.js +++ b/test/integration/couchdb-fabricca-tests.js @@ -81,6 +81,8 @@ test('Use FabricCAServices with a CouchDB KeyValueStore', function(t) { member = new User('admin2'); cryptoSuite = client.newCryptoSuite(options); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore(options)); + client.setCryptoSuite(cryptoSuite); member.setCryptoSuite(cryptoSuite); t.comment('Setting client keyValueStore to: ' +kvs); diff --git a/test/integration/e2e/create-channel.js b/test/integration/e2e/create-channel.js index 44286b059e..ab1a31254f 100644 --- a/test/integration/e2e/create-channel.js +++ b/test/integration/e2e/create-channel.js @@ -15,6 +15,8 @@ */ 'use strict'; +if (global && global.hfc) global.hfc.config = undefined; +require('nconf').reset(); var utils = require('fabric-client/lib/utils.js'); var logger = utils.getLogger('E2E create-channel'); @@ -246,6 +248,9 @@ test('\n\n***** SDK Built config update create flow *****\n\n', function(t) { path: testUtil.storePathForOrg(org) }).then((store) => { client.setStateStore(store); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(org)})); + client.setCryptoSuite(cryptoSuite); return testUtil.getOrderAdminSubmitter(client, t); }).then((admin) =>{ diff --git a/test/integration/e2e/e2eUtils.js b/test/integration/e2e/e2eUtils.js index 09229ad1b8..b4c901316f 100644 --- a/test/integration/e2e/e2eUtils.js +++ b/test/integration/e2e/e2eUtils.js @@ -50,7 +50,9 @@ function installChaincode(org, chaincode_path, version, t) { var chain = client.newChain(channel_name); var orgName = ORGS[org].name; - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); var caRootsPath = ORGS.orderer.tls_cacerts; let data = fs.readFileSync(path.join(__dirname, caRootsPath)); @@ -174,7 +176,9 @@ function instantiateChaincode(userOrg, chaincode_path, version, upgrade, t){ var chain = client.newChain(channel_name); var orgName = ORGS[userOrg].name; - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); var caRootsPath = ORGS.orderer.tls_cacerts; let data = fs.readFileSync(path.join(__dirname, caRootsPath)); @@ -465,7 +469,9 @@ function invokeChaincode(userOrg, version, t){ var chain = client.newChain(channel_name); var orgName = ORGS[userOrg].name; - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); var caRootsPath = ORGS.orderer.tls_cacerts; let data = fs.readFileSync(path.join(__dirname, caRootsPath)); @@ -694,7 +700,9 @@ function queryChaincode(org, version, value, t, transientMap) { var chain = client.newChain(channel_name); var orgName = ORGS[org].name; - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); var targets = []; // set up the chain to use each org's 'peer1' for diff --git a/test/integration/fabric-ca-services-tests.js b/test/integration/fabric-ca-services-tests.js index 3fa7119e92..7dc4f84366 100644 --- a/test/integration/fabric-ca-services-tests.js +++ b/test/integration/fabric-ca-services-tests.js @@ -30,7 +30,7 @@ var hfc = require('fabric-client'); var X509 = require('x509'); var util = require('util'); -var fs = require('fs'); +var fs = require('fs-extra'); var path = require('path'); var testUtil = require('../unit/util.js'); var LocalMSP = require('fabric-client/lib/msp/msp.js'); @@ -64,7 +64,10 @@ var fabricCAEndpoint = ORGS[userOrg].ca.url; //run the enroll test -test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { +test('\n\n ** FabricCAServices: Test enroll() With Dynamic CSR **\n\n', function (t) { + + utils.getConfigSetting('crypto-keysize', '256');//force for gulp test + utils.setConfigSetting('crypto-hash-algo', 'SHA2');//force for gulp test var caService = new FabricCAServices(fabricCAEndpoint, tlsOptions, ORGS[userOrg].ca.name); @@ -103,7 +106,8 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { cryptoSuite: caService.cryptoPrimitives }); - var signingIdentity = new SigningIdentity('testSigningIdentity', eResult.certificate, pubKey, msp, new Signer(msp.cryptoSuite, eResult.key)); + var signingIdentity = new SigningIdentity(eResult.certificate, pubKey, msp.getId(), msp.cryptoSuite, + new Signer(msp.cryptoSuite, eResult.key)); t.comment('Registering '+enrollmentID); return caService._fabricCAClient.register(enrollmentID, null, 'client', userOrg, 1, [], signingIdentity); },(err) => { @@ -133,7 +137,7 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { t.comment('Successfully constructed a user object based on the enrollment'); return caService.register({enrollmentID: 'testUserX', affiliation: 'bank_X'}, member); },(err) => { - t.fail('Failed to configuration the user with proper enrollment materials.'); + t.fail('Failed to configure the user with proper enrollment materials.'); t.end(); }).then((secret) => { t.fail('Should not have been able to register user of a affiliation "bank_X" because "admin" does not belong to that affiliation'); @@ -234,7 +238,7 @@ test('FabricCAServices: Test enroll() With Dynamic CSR', function (t) { }); }); -test('FabricCAClient: Test enroll With Static CSR', function (t) { +test('\n\n ** FabricCAClient: Test enroll With Static CSR **\n\n', function (t) { var endpoint = FabricCAServices._parseURL(fabricCAEndpoint); var client = new FabricCAClient({ protocol: endpoint.protocol, diff --git a/test/integration/fileKeyValueStore-fabricca-tests.js b/test/integration/fileKeyValueStore-fabricca-tests.js index 0781febc2c..5b22934b7b 100644 --- a/test/integration/fileKeyValueStore-fabricca-tests.js +++ b/test/integration/fileKeyValueStore-fabricca-tests.js @@ -75,7 +75,8 @@ test('Use FabricCAServices with a File KeyValueStore', function(t) { function(kvs) { member = new User('admin2'); - cryptoSuite = client.newCryptoSuite({path: keyValStorePath}); + cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: keyValStorePath})); member.setCryptoSuite(cryptoSuite); t.comment('Setting client keyValueStore to: ' +kvs); diff --git a/test/integration/get-config.js b/test/integration/get-config.js index 0103741398..43bfb423e5 100644 --- a/test/integration/get-config.js +++ b/test/integration/get-config.js @@ -104,7 +104,10 @@ test(' ---->>>>> get config <<<<<-----', function(t) { path: testUtil.storePathForOrg(orgName) }).then( function (store) { client.setStateStore(store); - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); + testUtil.getSubmitter(client, t, org) .then( function(admin) { diff --git a/test/integration/grpc.js b/test/integration/grpc.js index eb4d9202d8..e1b08515c0 100644 --- a/test/integration/grpc.js +++ b/test/integration/grpc.js @@ -46,7 +46,9 @@ test('\n\n*** GRPC communication tests ***\n\n', (t) => { var orgName = ORGS[userOrg].name; var submitter; - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); var junkpath = path.join(__dirname, '../fixtures/src/github.com/example_cc/junk.go'); // create a file of size 1M diff --git a/test/integration/new-chain.js b/test/integration/new-chain.js index 43262baf4d..e42e191835 100644 --- a/test/integration/new-chain.js +++ b/test/integration/new-chain.js @@ -39,7 +39,9 @@ hfc.addConfigFile(path.join(__dirname, 'e2e', 'config.json')); var ORGS = hfc.getConfigSetting('test-network'); var org = 'org1'; var orgName = ORGS[org].name; -client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); +var cryptoSuite = client.newCryptoSuite(); +cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); +client.setCryptoSuite(cryptoSuite); var caRootsPath = ORGS.orderer.tls_cacerts; let data = fs.readFileSync(path.join(__dirname, 'e2e', caRootsPath)); @@ -91,7 +93,10 @@ test('\n\n** TEST ** new chain - chain.createChannel() fail due to already exist .then( function (store) { client.setStateStore(store); - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); + return testUtil.getSubmitter(client, t, org); } ) diff --git a/test/integration/query.js b/test/integration/query.js index 6706f3be2e..40e3c9c3ea 100644 --- a/test/integration/query.js +++ b/test/integration/query.js @@ -113,7 +113,10 @@ chain.addPeer(peer1); test(' ---->>>>> Query chain working <<<<<-----', function(t) { utils.setConfigSetting('key-value-store','fabric-client/lib/impl/FileKeyValueStore.js'); - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); + var cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: testUtil.storePathForOrg(orgName)})); + client.setCryptoSuite(cryptoSuite); + return hfc.newDefaultKeyValueStore({ path: testUtil.storePathForOrg(orgName) }).then( function (store) { diff --git a/test/integration/upgrade.js b/test/integration/upgrade.js index e7952bb59e..b3b69e8d8b 100644 --- a/test/integration/upgrade.js +++ b/test/integration/upgrade.js @@ -87,7 +87,6 @@ test('\n\n **** E R R O R T E S T I N G on upgrade call', (t) => { }) .then((store) => { client.setStateStore(store); - client.newCryptoSuite({path: testUtil.storePathForOrg(orgName)}); return testUtil.getSubmitter(client, t, true /* use peer org admin */, org); }) diff --git a/test/unit/client.js b/test/unit/client.js index 3a0f84374b..a9ec0d3372 100644 --- a/test/unit/client.js +++ b/test/unit/client.js @@ -883,7 +883,7 @@ test('\n\n ** createUser error path - missing required cryptoContent privateKeyP }); }); -test('\n\n ** createUser error path - missing required keyStoreOpts **\n\n', function (t) { +test('\n\n ** createUser error path - invalid cryptoContent **\n\n', function (t) { var msg = 'Failed to load key or certificate and save to local stores'; var userOrg = 'org1'; diff --git a/test/unit/crypto-key-store.js b/test/unit/crypto-key-store.js index fbda5bec56..f07354da13 100644 --- a/test/unit/crypto-key-store.js +++ b/test/unit/crypto-key-store.js @@ -20,10 +20,12 @@ var tape = require('tape'); var _test = require('tape-promise'); var test = _test(tape); +var util = require('util'); var testutil = require('./util.js'); var utils = require('fabric-client/lib/utils.js'); var fs = require('fs-extra'); var path = require('path'); +var os = require('os'); var jsrsa = require('jsrsasign'); var KEYUTIL = jsrsa.KEYUTIL; var CouchdbMock = require('mock-couch'); @@ -234,4 +236,47 @@ function testKeyStore(store, t) { t.notEqual(recoveredKey, null, 'Successfully read public key from store using SKI'); t.equal(recoveredKey.isPrivate(), false, 'Test if the recovered key is a public key'); }); -} +}; + +test('\n\n** CryptoKeyStore tests - newCryptoKeyStore tests **\n\n', function(t) { + utils.setConfigSetting('key-value-store', 'fabric-ca-client/lib/impl/FileKeyValueStore.js');//force for 'gulp test' + let keyValStorePath = 'tmp/keyValStore1'; + let config = { path: keyValStorePath }; + t.comment('test opts as first parameter'); + let cs = utils.newCryptoKeyStore(config); + t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config)); + t.equal(typeof cs._storeConfig.superClass, 'function', 'Returned instance should have store config superClass'); + + t.comment('test default KVS path'); + let defaultKVSPath = path.join(os.homedir(), '.hfc-key-store'); + cs = utils.newCryptoKeyStore(); + t.equal(cs._storeConfig.opts.path, defaultKVSPath, util.format('Returned instance should have store config opts.path of %s', defaultKVSPath)); + t.equal(typeof cs._storeConfig.superClass, 'function', 'Returned instance should have store config superClass'); + + t.comment('test KVSImplClass as first parameter'); + let kvsImplClass = require(utils.getConfigSetting('key-value-store')); + cs = utils.newCryptoKeyStore(kvsImplClass); + t.equal(cs._storeConfig.opts.path, defaultKVSPath, util.format('Returned instance should have store config opts.path of %s', defaultKVSPath)); + t.equal(typeof cs._storeConfig.superClass, 'function', 'Returned instance should have store config superClass'); + + t.comment('test both parameters: (KVSImplClass, opts)'); + kvsImplClass = require(utils.getConfigSetting('key-value-store')); + cs = utils.newCryptoKeyStore(kvsImplClass, config); + t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config)); + t.equal(typeof cs._storeConfig.superClass, 'function', 'Returned instance should have store config superClass'); + + t.end(); +}); + +test('\n\n** CryptoKeyStore tests - getKey error tests **\n\n', function(t) { + var cryptoSuite = utils.newCryptoSuite(); + t.throws( + () => { + cryptoSuite.getKey('blah'); + }, + /getKey requires CryptoKeyStore to be set./, + 'Test missing cryptoKeyStore: cryptoSuite.getKey' + ); + t.end(); + +}); diff --git a/test/unit/cryptosuite-ecdsa-aes.js b/test/unit/cryptosuite-ecdsa-aes.js index 160bfcfde0..2361730c22 100644 --- a/test/unit/cryptosuite-ecdsa-aes.js +++ b/test/unit/cryptosuite-ecdsa-aes.js @@ -113,13 +113,13 @@ var TEST_KEY_PRIVATE_CERT_PEM = '-----BEGIN CERTIFICATE-----' + var TEST_USER_ENROLLMENT = { 'name': 'admin2', + 'mspid': 'test', 'roles':null, 'affiliation':'', 'enrollmentSecret':'', 'enrollment': { 'signingIdentity': '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a', 'identity': { - 'id': 'testIdentity', 'certificate': TEST_KEY_PRIVATE_CERT_PEM } } @@ -135,29 +135,17 @@ var _client = new hfc(); test('\n\n** utils.newCryptoSuite tests **\n\n', (t) => { testutil.resetDefaults(); - let config = { path: keyValStorePath }; - - let cs = utils.newCryptoSuite({keysize: 384, algorithm: 'EC'}, config); + let cs = utils.newCryptoSuite({keysize: 384, algorithm: 'EC'}); t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Should return an instance of CryptoSuite_ECDSA_AES'); t.equal(cs._keySize, 384, 'Returned instance should have keysize of 384'); - t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config)); - t.equal(typeof cs._storeConfig.superClass, 'function', 'Returned instance should have store config superClass'); - cs = utils.newCryptoSuite({keysize: 384}, config); + cs = utils.newCryptoSuite({keysize: 384}); t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Default test: should return an instance of CryptoSuite_ECDSA_AES'); t.equal(cs._keySize, 384, 'Returned instance should have keysize of 384'); - t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config)); - - cs = utils.newCryptoSuite({algorithm: 'EC'}, config); - t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Should return an instance of CryptoSuite_ECDSA_AES'); - t.equal(cs._keySize, 256, 'Returned instance should have keysize of 256'); - t.equal(cs._storeConfig.opts, config, util.format('Returned instance should have store config opts of %j', config)); - let defaultKVSPath = path.join(os.homedir(), '.hfc-key-store'); cs = utils.newCryptoSuite({algorithm: 'EC'}); t.equal(cs instanceof CryptoSuite_ECDSA_AES, true, 'Should return an instance of CryptoSuite_ECDSA_AES'); t.equal(cs._keySize, 256, 'Returned instance should have keysize of 256'); - t.equal(cs._storeConfig.opts.path, defaultKVSPath, util.format('Returned instance should have store config opts.path of %s', defaultKVSPath)); // each app instance is expected to use either HSM or software-based key management, as such this question // is answered with a config setting rather than controlled on a case-by-case basis @@ -169,101 +157,31 @@ test('\n\n** utils.newCryptoSuite tests **\n\n', (t) => { /Error:.*\/usr\/local\/lib/, 'Should attempt to load the bccsp_pkcs11 module and fail because of the dummy library path' ); + t.end(); +}); - utils.setConfigSetting('crypto-hsm', false); - t.doesNotThrow( +test('\n\n ** CryptoSuite_ECDSA_AES - error tests **\n\n', function (t) { + testutil.resetDefaults(); + var cryptoUtils = utils.newCryptoSuite(); + t.throws( () => { - cs = utils.newCryptoSuite({lib: '/usr/local/lib', slot: 0, pin: '1234' }); - cs._getKeyStore() - .then((store) => { - t.fail('Should not have been able to get a valid key store because of invalid store config'); - }).catch((err) => { - t.pass('Successfully rejected _getKeyStore() due to invalid config'); - }); + cryptoUtils.importKey(TEST_CERT_PEM); }, - null, - 'Load the CryptoSuite_ECDSA_AES module and pass in an invalid config object' + /importKey storeKey is true, which requires CryptoKeyStore to be set./, + 'Test missing cryptoKeyStore: cryptoSuite.importKey' ); - - // make sure the "software: true" setting overrides the config setting - utils.setConfigSetting('crypto-hsm', true); - cs = utils.newCryptoSuite({software: true, algorithm: 'EC', keysize: 256}, CouchDBKeyValueStore, { name: 'test_db', url: 'http://dummyUrl' }); - cs._getKeyStore() - .then(() => { - t.fail('Should not have been able to get a valid key store because the url was invalid'); - t.end(); - }).catch((err) => { - if (err.message.indexOf('Error creating test_db database to store membership data: Error: getaddrinfo ENOTFOUND dummyurl') >= 0) { - t.pass('Successfully loaded CryptoKeyStore based on CouchDBKeyValueStore, but rejected _getKeyStore() because the url was invalid'); - } else { - t.fail(err); - } - - t.end(); - }); -}); - -test('\n\n ** CryptoSuite_ECDSA_AES - constructor tests **\n\n', function (t) { - cleanupFileKeyValueStore(keyValStorePath); - - var keyValueStore = null; - let cs; - - utils.setConfigSetting('crypto-hsm', false); - - cs = new CryptoSuite_ECDSA_AES(256, { name: 'test_db', url: 'http://dummyUrl'}, CouchDBKeyValueStore); - cs._getKeyStore() - .then(() => { - t.fail('Should not have been able to get a valid key store because the url was invalid'); - }).catch((err) => { - if (err.message.indexOf('Error creating test_db database to store membership data: Error: getaddrinfo ENOTFOUND dummyurl') >= 0) { - t.pass('Successfully rejected _getKeyStore() because the url was invalid'); - } else { - t.fail(err); - } - - t.doesNotThrow( - () => { - cs = utils.newCryptoSuite(keyValStorePath); - }, - null, - 'CryptoSuite_ECDSA_AES constructor tests: pass in a string as kvs path' - ); - - return cs._getKeyStore(); - }).then(() => { - t.fail('Should not have been able to obtain a proper key store due to invalid config'); - }).catch(() => { - t.pass('Successfully rejected attempt to obtain a proper key store'); - - utils.setConfigSetting('key-value-store', 'fabric-client/lib/impl/FileKeyValueStore.js'); - - let cs1 = utils.newCryptoSuite({ - path: keyValStorePath - }); - - return cs1._getKeyStore(); - }).then((store) => { - t.notEqual(store, null, 'Crypto Key Store successfully initialized by CryptoSuite_ECDSA_AES'); - t.equal(typeof store.getKey, 'function', 'Crypto key store much have the "getKey()" function'); - t.equal(typeof store.putKey, 'function', 'Crypto key store much have the "putKey()" function'); - - let cs2 = new CryptoSuite_ECDSA_AES(256, {path: keyValStorePath}); - return cs2._getKeyStore(); - }).then((store) => { - t.notEqual(store, null, 'Crypto Key Store successfully initialized by CryptoSuite_ECDSA_AES'); - t.equal(typeof store.getKey, 'function', 'Crypto key store much have the "getKey()" function'); - t.equal(typeof store.putKey, 'function', 'Crypto key store much have the "putKey()" function'); - t.end(); - }).catch((err) => { - t.fail(err.stack ? err.stack : err); - t.end(); - }); + t.throws( + () => { + cryptoUtils.generateKey(); + }, + /generateKey opts.ephemeral is false, which requires CryptoKeyStore to be set./, + 'Test missing cryptoKeyStore: cryptoSuite.generateKey' + ); + t.end(); }); test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { testutil.resetDefaults(); - utils.setConfigSetting('key-value-store', 'fabric-ca-client/lib/impl/FileKeyValueStore.js');//force for 'gulp test' var cryptoUtils = utils.newCryptoSuite(); @@ -285,7 +203,9 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { //reset to default key size utils.setConfigSetting('crypto-keysize', 256); + utils.setConfigSetting('key-value-store','fabric-client/lib/impl/FileKeyValueStore.js');//force for gulp test cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); cryptoUtils.generateKey() .then(function (key) { @@ -296,9 +216,12 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { utils.setConfigSetting('crypto-hash-algo', 'SHA3'); utils.setConfigSetting('crypto-keysize', 256); cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); return cryptoUtils.generateKey(); - }) - .then(function (key) { + },(err) => { + t.fail('Failed to generateKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); + }).then(function (key) { t.equal('secp256r1', key.getPublicKey()._key.curveName, 'CryptoSuite_ECDSA_AES function tests: ccryptoUtils generated public key curveName == secp256r1'); @@ -312,6 +235,7 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { utils.setConfigSetting('crypto-hash-algo', 'SHA3'); utils.setConfigSetting('crypto-keysize', 384); cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); t.equal(cryptoUtils.hash(TEST_MSG), HASH_MSG_SHA3_384, 'CryptoSuite_ECDSA_AES function tests: using "SHA3" hashing algorithm with key size 384'); @@ -320,8 +244,10 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { 'CryptoSuite_ECDSA_AES function tests: using "SHA3" hashing algorithm with key size 384'); return cryptoUtils.generateKey(); - }) - .then(function (key) { + },(err) => { + t.fail('Failed to generateKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); + }).then(function (key) { t.equal('secp384r1', key.getPublicKey()._key.curveName, 'CryptoSuite_ECDSA_AES function tests: ccryptoUtils generated public key curveName == secp384r1'); @@ -332,13 +258,17 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { utils.setConfigSetting('crypto-hash-algo', 'sha3'); //lower or upper case is allowed cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); + t.equal(cryptoUtils.hash(TEST_MSG), HASH_MSG_SHA3_384, 'CryptoSuite_ECDSA_AES function tests: using "SHA3" hashing algorithm with key size 384'); // test generation options return cryptoUtils.generateKey({ ephemeral: true }); - }) - .then(function (key) { + },(err) => { + t.fail('Failed to generateKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); + }).then(function (key) { if (!!key._key) t.pass('CryptoSuite_ECDSA_AES function tests: verify generateKey ephemeral=true return object'); else @@ -366,9 +296,13 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { utils.setConfigSetting('crypto-keysize', 256); utils.setConfigSetting('crypto-hash-algo', 'SHA3'); cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); + return cryptoUtils.generateKey(); - }) - .then(function (key) { + },(err) => { + t.fail('Failed to generateKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); + }).then(function (key) { t.throws( function () { cryptoUtils.sign(); @@ -437,6 +371,7 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { utils.setConfigSetting('crypto-keysize', 256); utils.setConfigSetting('crypto-hash-algo', 'SHA2'); cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); var testVerify = function (sig, msg, expected) { // manually construct a key based on the saved privKeyHex and pubKeyHex @@ -456,17 +391,23 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { // test importKey() return cryptoUtils.importKey(TEST_CERT_PEM); + },(err) => { + t.fail('Failed to importKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); }).then((pubKey) => { t.equal(pubKey.isPrivate(), false, 'Test imported public key isPrivate()'); t.equal(pubKey.getSKI(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef', 'Test imported public key SKI'); // verify that the pub key has been saved in the key store by the proper key t.equal( - fs.existsSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef-pub')), + fs.existsSync(path.join(utils.getDefaultKeyStorePath(), 'b5cb4942005c4ecaa9f73a49e1936a58baf549773db213cf1e22a1db39d9dbef-pub')), true, 'Check that the imported public key has been saved in the key store'); return cryptoUtils.importKey(TEST_KEY_PRIVATE_PEM); + },(err) => { + t.fail('Failed to importKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); }).then((privKey) => { t.equal(privKey.isPrivate(), true, 'Test imported private key isPrivate'); t.equal(privKey.getSKI(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a', 'Test imported private key SKI'); @@ -474,7 +415,7 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { // verify that the imported private key has been saved in the key store by the proper key t.equal( - fs.existsSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv')), + fs.existsSync(path.join(utils.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv')), true, 'Check that the imported private key has been saved in the key store'); @@ -487,18 +428,31 @@ test('\n\n ** CryptoSuite_ECDSA_AES - function tests **\n\n', function (t) { // manufacture an error condition where the private key does not exist for the SKI, and only the public key does return cryptoUtils.importKey(TEST_KEY_PRIVATE_CERT_PEM); + },(err) => { + t.fail('Failed to importKey. Can not progress any further. Exiting. ' + err.stack ? err.stack : err); + t.end(); }).then((pubKey) => { - fs.removeSync(path.join(CryptoSuite_ECDSA_AES.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv')); + t.comment('then pubKey of importKey TEST_KEY_PRIVATE_CERT_PEM'); + fs.removeSync(path.join(utils.getDefaultKeyStorePath(), '0e67f7fa577fd76e487ea3b660e1a3ff15320dbc95e396d8b0ff616c87f8c81a-priv')); + + var poorUser = new User('admin2'); + poorUser.setCryptoSuite(cryptoUtils); - var poorUser = new User('admin2', _client); return poorUser.fromString(JSON.stringify(TEST_USER_ENROLLMENT)); }).then(() => { t.fail('Failed to catch missing private key expected from a user enrollment object'); t.end(); },(err) => { - t.pass('Successfully caught missing private key expected from a user enrollment object'); - t.end(); + var msg = 'Private key missing from key store'; + if (err.message && err.message.indexOf(msg) > -1) { + t.pass('Successfully caught missing private key expected from a user enrollment object'); + t.end(); + } else { + t.fail('Unexpected message. Expecting "'+msg+'"'); + t.end(); + } }).catch((err) => { + t.comment('final catch, caught err...'); t.fail(err.stack ? err.stack : err); t.end(); }); diff --git a/test/unit/identity.js b/test/unit/identity.js index ff6cfa84d5..a3ea0f141d 100644 --- a/test/unit/identity.js +++ b/test/unit/identity.js @@ -85,21 +85,13 @@ test('\n\n ** Identity class tests **\n\n', function (t) { function() { new Identity(); }, - /Missing required parameter "id"/, - 'Checking required input parameters' - ); - - t.throws( - function() { - new Identity('id'); - }, /Missing required parameter "certificate"/, 'Checking required input parameters' ); t.throws( function() { - new Identity('id', 'cert'); + new Identity('cert'); }, /Missing required parameter "publicKey"/, 'Checking required input parameters' @@ -107,9 +99,9 @@ test('\n\n ** Identity class tests **\n\n', function (t) { t.throws( function() { - new Identity('id', 'cert', 'pubKey'); + new Identity('cert', 'pubKey'); }, - /Missing required parameter "msp"/, + /Missing required parameter "mspId"/, 'Checking required input parameters' ); @@ -165,21 +157,13 @@ test('\n\n ** Identity class tests **\n\n', function (t) { function() { new SigningIdentity(); }, - /Missing required parameter "id"/, - 'Checking required input parameters' - ); - - t.throws( - function() { - new SigningIdentity('id'); - }, /Missing required parameter "certificate"/, 'Checking required input parameters' ); t.throws( function() { - new SigningIdentity('id', 'cert'); + new SigningIdentity('cert'); }, /Missing required parameter "publicKey"/, 'Checking required input parameters' @@ -187,36 +171,38 @@ test('\n\n ** Identity class tests **\n\n', function (t) { t.throws( function() { - new SigningIdentity('id', 'cert', 'pubKey'); + new SigningIdentity('cert', 'pubKey'); }, - /Missing required parameter "msp"/, + /Missing required parameter "mspId"/, 'Checking required input parameters' ); t.throws( function() { - new SigningIdentity('id', 'cert', 'pubKey', 'msp'); + new SigningIdentity('cert', 'pubKey', 'mspId', 'cryptoSuite'); }, /Missing required parameter "signer"/, 'Checking required input parameters' ); + var cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); + // test identity serialization and deserialization var mspImpl = new MSP({ rootCerts: [], admins: [], id: 'testMSP', - cryptoSuite: utils.newCryptoSuite() + cryptoSuite: cryptoUtils }); - var cryptoUtils = utils.newCryptoSuite(); var pubKey = cryptoUtils.importKey(TEST_CERT_PEM, { algorithm: api.CryptoAlgorithms.X509Certificate }); - var identity = new Identity('testIdentity', TEST_CERT_PEM, pubKey, mspImpl); + var identity = new Identity(TEST_CERT_PEM, pubKey, mspImpl.getId(), cryptoUtils); var serializedID = identity.serialize(); // deserializeIdentity should work both ways ... with promise and without var identity_g = mspImpl.deserializeIdentity(serializedID, false); - t.equals(identity_g.getId(),'SomeDummyValue', 'deserializeIdentity call without promise'); + t.equals(identity_g.getMSPId(),'testMSP', 'deserializeIdentity call without promise'); mspImpl.deserializeIdentity(serializedID) .then((dsID) => { @@ -232,7 +218,7 @@ test('\n\n ** Identity class tests **\n\n', function (t) { var signer = new Signer(cryptoUtils, testKey); t.equal(signer.getPublicKey().isPrivate(), false, 'Test Signer class getPublicKey() method'); - var signingID = new SigningIdentity('testSigningIdentity', TEST_KEY_PRIVATE_CERT_PEM, pubKey, mspImpl, signer); + var signingID = new SigningIdentity(TEST_KEY_PRIVATE_CERT_PEM, pubKey, mspImpl.getId(), cryptoUtils, signer); t.throws( () => { diff --git a/test/unit/msp.js b/test/unit/msp.js index 8ceaa905f0..c6247eeeb6 100644 --- a/test/unit/msp.js +++ b/test/unit/msp.js @@ -137,6 +137,7 @@ test('\n\n** MSP Tests **\n\n', (t) => { // test deserialization using the msp manager var cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); var mspImpl = new MSP({ rootCerts: [], admins: [], @@ -145,13 +146,12 @@ test('\n\n** MSP Tests **\n\n', (t) => { }); var pubKey = cryptoUtils.importKey(TEST_CERT_PEM); - var identity = new Identity('testIdentity', TEST_CERT_PEM, pubKey, mspImpl); + var identity = new Identity(TEST_CERT_PEM, pubKey, mspImpl.getId(), cryptoUtils); var serializedID = identity.serialize(); - return mspm.deserializeIdentity(serializedID); }).then((identity) => { - t.equal(identity.getId(), 'SomeDummyValue', 'Deserialized identity using MSP manager'); + t.equal(identity.getMSPId(), 'peerOrg0', 'Deserialized identity using MSP manager'); t.equal(mspm.getMSP('peerOrg0').getId(), 'peerOrg0', 'Checking MSPManager getMSP() method' ); t.end(); diff --git a/test/unit/user.js b/test/unit/user.js index d60dfa9419..fa18189467 100644 --- a/test/unit/user.js +++ b/test/unit/user.js @@ -133,6 +133,7 @@ test('\n\n ** User - constructor set get tests **\n\n', function (t) { // test set enrollment for identity and signing identity var cryptoUtils = utils.newCryptoSuite(); + cryptoUtils.setCryptoKeyStore(utils.newCryptoKeyStore()); cryptoUtils.generateKey() .then(function (key) { // the private key and cert don't match, but it's ok, the code doesn't check diff --git a/test/unit/util.js b/test/unit/util.js index 1873dc8921..408c773bdb 100644 --- a/test/unit/util.js +++ b/test/unit/util.js @@ -128,11 +128,10 @@ function getMember(username, password, client, t, userOrg) { } var member = new User(username); - var cryptoSuite = null; + var cryptoSuite = client.newCryptoSuite(); if (userOrg) { - cryptoSuite = client.newCryptoSuite({path: module.exports.storePathForOrg(ORGS[userOrg].name)}); - } else { - cryptoSuite = client.newCryptoSuite(); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: module.exports.storePathForOrg(ORGS[userOrg].name)})); + client.setCryptoSuite(cryptoSuite); } member.setCryptoSuite(cryptoSuite); @@ -164,8 +163,10 @@ function getAdmin(client, t, userOrg) { var certPath = path.join(__dirname, util.format('../fixtures/channel/crypto-config/peerOrganizations/%s.example.com/users/Admin@%s.example.com/signcerts', userOrg, userOrg)); var certPEM = readAllFiles(certPath)[0]; + var cryptoSuite = client.newCryptoSuite(); if (userOrg) { - client.newCryptoSuite({path: module.exports.storePathForOrg(ORGS[userOrg].name)}); + cryptoSuite.setCryptoKeyStore(client.newCryptoKeyStore({path: module.exports.storePathForOrg(ORGS[userOrg].name)})); + client.setCryptoSuite(cryptoSuite); } return Promise.resolve(client.createUser({