diff --git a/lib/Chain.js b/lib/Chain.js index 36335c05e2..5700788121 100644 --- a/lib/Chain.js +++ b/lib/Chain.js @@ -14,6 +14,8 @@ limitations under the License. */ +'use strict'; + /** * This module contains the implementation of the [Chain]{@link module:api.Chain} abstract class. * @@ -34,178 +36,174 @@ var Member = require('./Member.js'); * @class Chain * @memberof module:Chain */ -module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ - - // Name of the chain is only meaningful to the client - _name: "", +module.exports = class extends api.Chain { - // The peers on this chain to which the client can connect - _peers: [], // Peer[] + /** + * @param {string} name to identify different chain instances. The naming of chain instances + * is completely at the client application's discretion. + */ + constructor(name) { + super(); - // Security enabled flag - _securityEnabled: true, + // Name of the chain is only meaningful to the client + this._name = ""; - // A member cache associated with this chain - // TODO: Make an LRU to limit size of member cache - _members: {}, // associated array of [name] <-> Member + // The peers on this chain to which the client can connect + this._peers = []; // Peer[] - // The number of tcerts to get in each batch - _tcertBatchSize: 200, + // Security enabled flag + this._securityEnabled = true; - // The registrar (if any) that registers & enrolls new members/users - _registrar: null, // Member + // A member cache associated with this chain + // TODO: Make an LRU to limit size of member cache + this._members = {}; // associated array of [name] <-> Member - // The member services used for this chain - _memberServices: null, // MemberServices + // The number of tcerts to get in each batch + this._tcertBatchSize = 200; - // The key-val store used for this chain - _keyValStore: null, // KeyValueStore; + // The registrar (if any) that registers & enrolls new members/users + this._registrar = null; // Member - // Is in dev mode or network mode - _devMode: false, + // The member services used for this chain + this._memberServices = null; // MemberServices - // If in prefetch mode, we prefetch tcerts from member services to help performance - _preFetchMode: true, + // The key-val store used for this chain + this._keyValStore = null; // KeyValueStore; - // Temporary variables to control how long to wait for deploy and invoke to complete before - // emitting events. This will be removed when the SDK is able to receive events from the - _deployWaitTime: 20, - _invokeWaitTime: 5, + // Is in dev mode or network mode + this._devMode = false; - // The crypto primitives object - cryptoPrimitives: utils.getCryptoSuite(), + // If in prefetch mode, we prefetch tcerts from member services to help performance + this._preFetchMode = true; - /** - * @param {string} name to identify different chain instances. The naming of chain instances - * is completely at the client application's discretion. - */ - constructor: function(name) { - this._name = name; - this._members = {}; - }, + // Temporary variables to control how long to wait for deploy and invoke to complete before + // emitting events. This will be removed when the SDK is able to receive events from the + this._deployWaitTime = 20; + this._invokeWaitTime = 5; + } /** * Get the chain name. * @returns {string} The name of the chain. */ - getName: function() { + getName() { return this._name; - }, + } /** * Get the member whose credentials are used to register and enroll other users, or undefined if not set. * @returns [Member]{@link module:api.Member} The member whose credentials are used to perform registration, or undefined if not set. */ - getRegistrar: function() { + getRegistrar() { return this._registrar; - }, + } /** * Set the member whose credentials are used to register and enroll other users. * @param [Member]{@link module:api.Member} registrar The member whose credentials are used to perform registration. */ - setRegistrar: function(registrar) { + setRegistrar(registrar) { this._registrar = registrar; - }, + } /** * Set the member services URL * @param {string} url Member services URL of the form: "grpc://host:port" or "grpcs://host:port" * @param {string} pem String value of the TLS certificate for the local client */ - setMemberServicesUrl: function(url, pem) { + setMemberServicesUrl(url, pem) { this.setMemberServices(new MemberServices(url, pem)); - }, + } /** * Get the member service associated this chain. * @returns [MemberService]{@link module:api.MemberService} Return the current member service, or undefined if not set. */ - getMemberServices: function() { + getMemberServices() { return this._memberServices; - }, + } /** * Set the member service associated this chain. This allows the default implementation of member service to be overridden. * @param [MemberService]{@link module:api.MemberService} an instance of the MemberServices class */ - setMemberServices: function(memberServices) { + setMemberServices(memberServices) { this._memberServices = memberServices; if (memberServices instanceof MemberServices) { this.cryptoPrimitives = memberServices.getCrypto(); } - }, + } /** * Determine if security is enabled. */ - isSecurityEnabled: function() { + isSecurityEnabled() { return this._memberServices !== undefined; - }, + } /** * Determine if pre-fetch mode is enabled to prefetch tcerts. */ - isPreFetchMode: function() { + isPreFetchMode() { return this._preFetchMode; - }, + } /** * Set prefetch mode to true or false. */ - setPreFetchMode: function(preFetchMode) { + setPreFetchMode(preFetchMode) { this._preFetchMode = preFetchMode; - }, + } /** * Determine if dev mode is enabled. */ - isDevMode: function() { + isDevMode() { return this._devMode - }, + } /** * Set dev mode to true or false. */ - setDevMode: function(devMode) { + setDevMode(devMode) { this._devMode = devMode; - }, + } /** * Get the key val store implementation (if any) that is currently associated with this chain. * @returns {KeyValueStore} Return the current KeyValueStore associated with this chain, or undefined if not set. */ - getKeyValueStore: function() { + getKeyValueStore() { return this._keyValStore; - }, + } /** * Set the key value store implementation. */ - setKeyValueStore: function(keyValStore) { + setKeyValueStore(keyValStore) { this._keyValStore = keyValStore; - }, + } /** * Get the tcert batch size. */ - getTCertBatchSize: function() { + getTCertBatchSize() { return this._tcertBatchSize; - }, + } /** * Set the tcert batch size. */ - setTCertBatchSize: function(batchSize) { + setTCertBatchSize(batchSize) { this._tcertBatchSize = batchSize; - }, + } /** * Get the user member named 'name' or create * a new member if the member does not exist. * @returns Promise for the Member object */ - getMember: function(name) { + getMember(name) { var self = this; return new Promise(function(resolve, reject) { if (!self._keyValStore) { @@ -230,7 +228,7 @@ module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ } ); }); - }, + } /** * Get a user. @@ -238,9 +236,9 @@ module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ * Another type of member is a peer. * @returns Promise for the Member object */ - getUser: function(name) { + getUser(name) { return this.getMember(name); - }, + } // Try to get the member from cache. // If not found, create a new one. @@ -273,7 +271,7 @@ module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ } ); }); - }, + } /** * Register a user or other member type with the chain. @@ -297,7 +295,7 @@ module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ } ); }); - }, + } /** * Enroll a user or other identity which has already been registered. @@ -327,7 +325,7 @@ module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ } ); }); - }, + } /** * Register and enroll a user or other member type. @@ -362,5 +360,5 @@ module.exports = api.Chain.extend(/** @lends module:Chain.Chain.prototype */{ ); }); } -}); +}; diff --git a/lib/CryptoSuite_ECDSA_SHA.js b/lib/CryptoSuite_ECDSA_SHA.js index 1516b2b3f7..c4a3ae0fc8 100644 --- a/lib/CryptoSuite_ECDSA_SHA.js +++ b/lib/CryptoSuite_ECDSA_SHA.js @@ -14,6 +14,8 @@ * limitations under the License. */ +'use strict'; + // requires var api = require('./api.js'); @@ -58,75 +60,76 @@ const DEFAULT_SECURITY_LEVEL = 256; /** * The crypto class contains implementations of various crypto primitives. */ -var ECDSA_SHA = api.CryptoSuite.extend({ - - _hashAlgorithm: DEFAULT_HASH_ALGORITHM, - _securityLevel: DEFAULT_SECURITY_LEVEL, - _curveName: "", - _suite: "", - _hashFunction: null, - _hashFunctionKeyDerivation: null, - _hashOutputSize: -1, - _ecdsaCurve: null, - - constructor: function() { +var ECDSA_SHA = class extends api.CryptoSuite { + + constructor() { + super(); + this._hashAlgorithm = DEFAULT_HASH_ALGORITHM; + this._securityLevel = DEFAULT_SECURITY_LEVEL; + this._curveName = ""; + this._suite = ""; + this._hashFunction = null; + this._hashFunctionKeyDerivation = null; + this._hashOutputSize = -1; + this._ecdsaCurve = null; + this._initialize(); - }, + } /** * must match one of the values in ca.proto */ - getPublicKeyAlgorithm: function() { + getPublicKeyAlgorithm() { return "ECDSA"; - }, + } /** * Get the security level * @returns The security level */ - getSecurityLevel: function() { + getSecurityLevel() { return this._securityLevel; - }, + } /** * Set the security level * @params securityLevel The security level */ - setSecurityLevel: function(securityLevel) { + setSecurityLevel(securityLevel) { this._checkSecurityLevel(securityLevel); this._securityLevel = securityLevel; this._initialize(); - }, + } /** * Get the hash algorithm * @returns {string} The hash algorithm */ - getHashAlgorithm: function() { + getHashAlgorithm() { return this._hashAlgorithm; - }, + } /** * Set the hash algorithm * @params hashAlgorithm The hash algorithm ('SHA2' or 'SHA3') */ - setHashAlgorithm: function(hashAlgorithm) { + setHashAlgorithm(hashAlgorithm) { this._checkHashFunction(hashAlgorithm); this._hashAlgorithm = hashAlgorithm; this._initialize(); - }, + } - generateNonce: function() { + generateNonce() { return crypto.randomBytes(NonceSize); - }, + } - generateKeyPair: function() { + generateKeyPair() { return KEYUTIL.generateKeypair("EC", this._curveName); - }, + } - asymmetricDecrypt: function(recipientPrivateKey, cipherText) { + asymmetricDecrypt(recipientPrivateKey, cipherText) { var self = this; // debug("recipientPrivateKey=%s", util.inspect(recipientPrivateKey));//XXX var level = recipientPrivateKey.ecparams.keylen; @@ -185,30 +188,30 @@ var ECDSA_SHA = api.CryptoSuite.extend({ var decryptedBytes = cipher.update(EM.slice(IVLength)); // debug("decryptedBytes: ",new Buffer(decryptedBytes).toString('hex')); return decryptedBytes; - }, + } - getKeyPairForSigning: function(key, encoding) { + getKeyPairForSigning(key, encoding) { // select curve and hash algo based on level var keypair = new EC(this._ecdsaCurve).keyFromPrivate(key, encoding); debug('keypair: ', keypair); return keypair; - }, + } - getKeyPairForEncryption: function(key, encoding) { + getKeyPairForEncryption(key, encoding) { var publicKey = new EC(this._ecdsaCurve).keyFromPublic(key, encoding); // debug('publicKey: [%j]', publicKey); return publicKey; - }, + } - sign: function(key, msg) { + sign(key, msg) { var ecdsa = new EC(this._ecdsaCurve); var signKey = ecdsa.keyFromPrivate(key, 'hex'); var sig = ecdsa.sign(new Buffer(this._hashFunction(msg), 'hex'), signKey); debug('ecdsa signature: ', sig); return sig; - }, + } - ecdsaPEMToPublicKey: function(chainKey) { + ecdsaPEMToPublicKey(chainKey) { // enrollChainKey is a PEM. Extract the key from it. var pem = new Buffer(chainKey, 'hex').toString(); debug("ChainKey %s", pem); @@ -225,9 +228,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ var ecdsaChainKey = this.getKeyPairForEncryption(ab, 'hex'); return ecdsaChainKey - }, + } - ecdsaPrivateKeyToASN1: function(prvKeyHex) { + ecdsaPrivateKeyToASN1(prvKeyHex) { var Ber = require('asn1').Ber; var sk = new Ber.Writer(); sk.startSequence(); @@ -246,13 +249,13 @@ var ECDSA_SHA = api.CryptoSuite.extend({ } sk.endSequence(); return sk.buffer; - }, + } - eciesKeyGen: function() { + eciesKeyGen() { return KEYUTIL.generateKeypair("EC", this._curveName); - }, + } - eciesEncryptECDSA: function(ecdsaRecipientPublicKey, msg) { + eciesEncryptECDSA(ecdsaRecipientPublicKey, msg) { var self = this; var EC = elliptic.ec; //var curve = elliptic.curves['p'+level]; @@ -289,9 +292,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ // debug('[D] ', new Buffer(D).toString('hex')); return Buffer.concat([new Buffer(Rb, 'hex'), EM, new Buffer(D)]); - }, + } - eciesEncrypt: function(recipientPublicKey, msg) { + eciesEncrypt(recipientPublicKey, msg) { var level = recipientPublicKey.ecparams.keylen; // debug("=============> %d", level); var EC = elliptic.ec; @@ -300,13 +303,13 @@ var ECDSA_SHA = api.CryptoSuite.extend({ var ecdsa = new EC(curve); return this.eciesEncryptECDSA(ecdsa.keyFromPublic(recipientPublicKey.pubKeyHex, 'hex'), msg) - }, + } - aesKeyGen: function() { + aesKeyGen() { return crypto.randomBytes(AESKeyLength); - }, + } - _aesCFBDecryt: function(key, encryptedBytes) { + _aesCFBDecryt(key, encryptedBytes) { var iv = crypto.randomBytes(IVLength); var aes = new aesjs.ModeOfOperation.cfb(key, iv, IVLength); @@ -327,9 +330,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ return decryptedBytes.slice(IVLength, decryptedBytes.length - numMissingBytes); - }, + } - aesCBCPKCS7Decrypt: function(key, bytes) { + aesCBCPKCS7Decrypt(key, bytes) { var decryptedBytes, unpaddedBytes; @@ -337,9 +340,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ unpaddedBytes = this._PKCS7UnPadding(decryptedBytes); return unpaddedBytes; - }, + } - aes256GCMDecrypt: function(key, ct) { + aes256GCMDecrypt(key, ct) { var decipher = crypto.createDecipheriv('aes-256-gcm', key, ct.slice(0, GCMStandardNonceSize)); decipher.setAuthTag(ct.slice(ct.length - GCMTagSize)); var dec = decipher.update( @@ -348,9 +351,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ ); dec += decipher.final('hex'); return dec; - }, + } - _hkdf: function(ikm, keyBitLength, salt, info) { + _hkdf(ikm, keyBitLength, salt, info) { if (!salt) salt = _zeroBuffer(this._hashOutputSize); @@ -362,9 +365,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ return bitsToBytes(key); - }, + } - hmac: function(key, bytes) { + hmac(key, bytes) { var self = this; debug('key: ', JSON.stringify(key)); debug('bytes: ', JSON.stringify(bytes)); @@ -374,33 +377,33 @@ var ECDSA_SHA = api.CryptoSuite.extend({ var result = hmac.digest(); debug("result: ", bitsToBytes(result)); return bitsToBytes(result); - }, + } - hmacAESTruncated: function(key, bytes) { + hmacAESTruncated(key, bytes) { var res = this.hmac(key, bytes); return res.slice(0, AESKeyLength); - }, + } - hash: function(bytes) { + hash(bytes) { debug('bytes: ', JSON.stringify(bytes)); return this._hashFunction(bytes); - }, + } - _checkSecurityLevel: function(securityLevel) { + _checkSecurityLevel(securityLevel) { if (securityLevel != 256 && securityLevel != 384) throw new Error("Illegal level: " + this._securityLevel + " - must be either 256 or 384"); - }, + } - _checkHashFunction: function(hashAlgorithm) { + _checkHashFunction(hashAlgorithm) { if (!_isString(hashAlgorithm)) throw new Error("Illegal Hash function family: " + hashAlgorithm + " - must be either SHA2 or SHA3"); hashAlgorithm = hashAlgorithm.toUpperCase(); if (hashAlgorithm != SHA2 && hashAlgorithm != SHA3) throw new Error("Illegal Hash function family: " + hashAlgorithm + " - must be either SHA2 or SHA3"); - }, + } - _initialize: function() { + _initialize() { this._checkSecurityLevel(this._securityLevel); this._checkHashFunction(this._hashAlgorithm); @@ -441,7 +444,7 @@ var ECDSA_SHA = api.CryptoSuite.extend({ break; } - }, + } /** HKDF with the specified hash function. * @param {bitArray} ikm The input keying material. @@ -451,7 +454,7 @@ var ECDSA_SHA = api.CryptoSuite.extend({ * @param {Object} [Hash=sjcl.hash.sha256] The hash function to use. * @return {bitArray} derived key. */ - _hkdf2: function(ikm, keyBitLength, salt, info, Hash) { + _hkdf2(ikm, keyBitLength, salt, info, Hash) { var hmac, key, i, hashLen, loops, curOut, ret = []; // Hash = Hash || sjcl.hash.sha256; @@ -491,9 +494,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ ret = sjcl.bitArray.concat(ret, curOut); } return sjcl.bitArray.clamp(ret, keyBitLength); - }, + } - _CBCDecrypt: function(key, bytes) { + _CBCDecrypt(key, bytes) { debug('key length: ', key.length); debug('bytes length: ', bytes.length); var iv = bytes.slice(0, BlockSize); @@ -534,9 +537,9 @@ var ECDSA_SHA = api.CryptoSuite.extend({ return decryptedBytes; - }, + } - _PKCS7UnPadding: function(bytes) { + _PKCS7UnPadding(bytes) { //last byte is the number of padded bytes var padding = bytes.readUInt8(bytes.length - 1); @@ -547,7 +550,7 @@ var ECDSA_SHA = api.CryptoSuite.extend({ return unpadded; } -}); // end Crypto class +}; // end Crypto class // Determine if an object is a string function _isString(obj) { diff --git a/lib/FileKeyValueStore.js b/lib/FileKeyValueStore.js index 76dcc0b962..9618879263 100644 --- a/lib/FileKeyValueStore.js +++ b/lib/FileKeyValueStore.js @@ -14,6 +14,8 @@ limitations under the License. */ +'use strict'; + /** * Built-in implementation of [KeyValueStore]{@link module:api.KeyValueStore}. Uses * a top-level directory to hold files. Each key/value pair is saved in a separate file. @@ -29,31 +31,31 @@ var path = require('path'); * @class FileKeyValueStore * @memberof module:FileKeyValueStore */ -module.exports = api.KeyValueStore.extend(/** @lends module:FileKeyValueStore.FileKeyValueStore.prototype */{ - - _dir: "", // root directory for the file store +module.exports = class extends api.KeyValueStore { /** * @param {Object} options contains a single property "path" which points to the top-level directory * for the store */ - constructor: function(options) { + constructor(options) { if (!options || !options.path) { throw new Error('Must provide the path to the directory to hold files for the store.'); } + super(); + this._dir = options.path; if (!fs.existsSync(this._dir)) { fs.mkdirSync(this._dir); } - }, + } /** * Get the value associated with name. * @param {string} name * @returns Promise for the value */ - getValue: function(name) { + getValue(name) { var self = this; return new Promise(function(resolve, reject) { @@ -70,7 +72,7 @@ module.exports = api.KeyValueStore.extend(/** @lends module:FileKeyValueStore.Fi return resolve(data); }); }); - }, + } /** * Set the value associated with name. @@ -78,7 +80,7 @@ module.exports = api.KeyValueStore.extend(/** @lends module:FileKeyValueStore.Fi * @param {string} value * @returns Promise for a "true" value on successful completion */ - setValue: function (name, value) { + setValue(name, value) { var self = this; return new Promise(function(resolve, reject) { @@ -92,5 +94,5 @@ module.exports = api.KeyValueStore.extend(/** @lends module:FileKeyValueStore.Fi }); }); } -}); +}; diff --git a/lib/Member.js b/lib/Member.js index f87d669ba0..0a95fdf20a 100644 --- a/lib/Member.js +++ b/lib/Member.js @@ -14,6 +14,8 @@ limitations under the License. */ +'use strict'; + /** * This module defines the implementations for the [Member]{@link module:api.Member} class * plus auxiliary classes for handling TCert downloads from the member services @@ -41,165 +43,144 @@ var stats = require('./stats.js'); * @class Member * @memberof module:Member */ -module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ - - _chain: null, //Chain - _name: "", - _roles: null, //string[] - _account: "", - _affiliation: "", - _enrollmentSecret: "", - _enrollment: null, - _memberServices: null, //MemberServices - _keyValStore: null, - _keyValStoreName: "", - _tcertGetterMap: {}, //{[s:string]:TCertGetter} - _tcertBatchSize: -1, +module.exports = class extends api.Member { /** * Constructor for a member. * @param cfg {string | RegistrationRequest} The member name or registration request. * @returns {Member} A member who is neither registered nor enrolled. */ - constructor: function(cfg, chain) { + constructor(cfg, chain) { + super(); + if (util.isString(cfg)) { this._name = cfg; + this._roles = null; //string[] + this._affiliation = ""; } else if (util.isObject(cfg)) { var req = cfg; this._name = req.enrollmentID || req.name; this._roles = req.roles || ['fabric.user']; - this._account = req.account; this._affiliation = req.affiliation; } + this._chain = chain; this._memberServices = chain.getMemberServices(); this._keyValStore = chain.getKeyValueStore(); this._keyValStoreName = toKeyValueStoreName(this._name); this._tcertBatchSize = chain.getTCertBatchSize(); - }, + + this._enrollmentSecret = ""; + this._enrollment = null; + this._tcertGetterMap = {}; //{[s:string]:TCertGetter} + } /** * Get the member name. * @returns {string} The member name. */ - getName: function() { + getName() { return this._name; - }, + } /** * Get the chain. * @returns {Chain} The chain. */ - getChain: function() { + getChain() { return this._chain; - }, + } /** * Get the member services. * @returns {MemberServices} The member services. */ - getMemberServices: function() { + getMemberServices() { return this._memberServices; - }, + } /** * Get the roles. * @returns {string[]} The roles. */ - getRoles: function() { + getRoles() { return this._roles; - }, + } /** * Set the roles. * @param roles {string[]} The roles. */ - setRoles: function(roles) { + setRoles(roles) { this._roles = roles; - }, - - /** - * Get the account. - * @returns {string} The account. - */ - getAccount: function() { - return this._account; - }, - - /** - * Set the account. - * @param account The account. - */ - setAccount: function(account) { - this._account = account; - }, + } /** * Get the affiliation. * @returns {string} The affiliation. */ - getAffiliation: function() { + getAffiliation() { return this._affiliation; - }, + } /** * Set the affiliation. * @param affiliation The affiliation. */ - setAffiliation: function(affiliation) { + setAffiliation(affiliation) { this._affiliation = affiliation; - }, + } /** * Get the transaction certificate (tcert) batch size, which is the number of tcerts retrieved * from member services each time (i.e. in a single batch). * @returns The tcert batch size. */ - getTCertBatchSize: function() { + getTCertBatchSize() { if (this._tcertBatchSize === undefined) { return this._chain.getTCertBatchSize(); } else { return this._tcertBatchSize; } - }, + } /** * Set the transaction certificate (tcert) batch size. * @param batchSize */ - setTCertBatchSize: function(batchSize) { + setTCertBatchSize(batchSize) { this._tcertBatchSize = batchSize; - }, + } /** * Get the enrollment info. * @returns {Enrollment} The enrollment. */ - getEnrollment: function() { + getEnrollment() { return this._enrollment; - }, + } /** * Determine if this name has been registered. * @returns {boolean} True if registered; otherwise, false. */ - isRegistered: function() { + isRegistered() { return this._enrollmentSecret !== ""; - }, + } /** * Determine if this name has been enrolled. * @returns {boolean} True if enrolled; otherwise, false. */ - isEnrolled: function() { + isEnrolled() { return this._enrollment !== null; - }, + } /** * Register the member. * @param {Object} registrationRequest */ - register: function(registrationRequest) { + register(registrationRequest) { var self = this; return new Promise(function(resolve, reject) { @@ -207,7 +188,7 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ reject(new Error("registration enrollment ID and member name are not equal")); } - var enrollmentSecret = this._enrollmentSecret; + var enrollmentSecret = self._enrollmentSecret; if (enrollmentSecret) { return resolve(enrollmentSecret); } else { @@ -229,13 +210,13 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ ); } }); - }, + } /** * Enroll the member and return the enrollment results. * @param enrollmentSecret The password or enrollment secret as returned by register. */ - enroll: function(enrollmentSecret) { + enroll(enrollmentSecret) { var self = this; return new Promise(function(resolve, reject) { @@ -275,13 +256,13 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ ); } }); - }, + } /** * Perform both registration and enrollment. * @param {Object} registrationRequest */ - registerAndEnroll: function(registrationRequest) { + registerAndEnroll(registrationRequest) { var self = this; return new Promise(function(resolve, reject) { @@ -305,15 +286,15 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ ); } }); - }, + } /** * Save the state of this member to the key value store. * @returns Promise for a "true" upon successful save */ - saveState: function() { + saveState() { return this._keyValStore.setValue(this._keyValStoreName, this.toString()); - }, + } /** * Restore the state of this member from the key value store (if found). If not found, do nothing. @@ -338,13 +319,13 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ } ); }); - }, + } /** * Get the current state of this member as a string * @return {string} The state of this member as a string */ - fromString: function(str) { + fromString(str) { var state = JSON.parse(str); if (state.name !== this.getName()) { @@ -353,11 +334,10 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ this._name = state.name; this._roles = state.roles; - this._account = state.account; this._affiliation = state.affiliation; this._enrollmentSecret = state.enrollmentSecret; this._enrollment = state.enrollment; - }, + } /** * Save the current state of this member as a string @@ -367,7 +347,6 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ var state = { name: this._name, roles: this._roles, - account: this._account, affiliation: this._affiliation, enrollmentSecret: this._enrollmentSecret, enrollment: this._enrollment @@ -375,7 +354,7 @@ module.exports = api.Member.extend(/** @lends module:Member.Member.prototype */{ return JSON.stringify(state); } -}); +}; function toKeyValueStoreName(name) { return "member." + name; diff --git a/lib/MemberServices.js b/lib/MemberServices.js index 22c4bceb18..410cc35d02 100644 --- a/lib/MemberServices.js +++ b/lib/MemberServices.js @@ -14,6 +14,8 @@ limitations under the License. */ +'use strict'; + var api = require('./api.js'); var utils = require('./utils'); var jsrsa = require('jsrsasign'); @@ -29,67 +31,64 @@ var _caProto = grpc.load(__dirname + "/protos/ca.proto").protos; /** * MemberServicesImpl is the default implementation of a member services client. */ -var MemberServices = api.MemberServices.extend({ - - _ecaaClient: null, - _ecapClient: null, - _tcapClient: null, - _tlscapClient: null, - cryptoPrimitives: null, +var MemberServices = class extends api.MemberServices { /** * MemberServicesImpl constructor * @param config The config information required by this member services implementation. * @returns {MemberServices} A MemberServices object. */ - constructor: function(url /*string*/, pem /*string*/) { + constructor(url /*string*/, pem /*string*/) { + super(); + var ep = new utils.Endpoint(url,pem); var options = { 'grpc.ssl_target_name_override' : 'tlsca', 'grpc.default_authority': 'tlsca' }; + this._ecaaClient = new _caProto.ECAA(ep.addr, ep.creds, options); this._ecapClient = new _caProto.ECAP(ep.addr, ep.creds, options); this._tcapClient = new _caProto.TCAP(ep.addr, ep.creds, options); this._tlscapClient = new _caProto.TLSCAP(ep.addr, ep.creds, options); this.cryptoPrimitives = new CryptoSuite(); - }, + } /** * Get the security level * @returns The security level */ - getSecurityLevel: function() { + getSecurityLevel() { return this.cryptoPrimitives.getSecurityLevel(); - }, + } /** * Set the security level * @params securityLevel The security level */ - setSecurityLevel: function(securityLevel) { + setSecurityLevel(securityLevel) { this.cryptoPrimitives.setSecurityLevel(securityLevel); - }, + } /** * Get the hash algorithm * @returns {string} The hash algorithm */ - getHashAlgorithm: function() { + getHashAlgorithm() { return this.cryptoPrimitives.getHashAlgorithm(); - }, + } /** * Set the hash algorithm * @params hashAlgorithm The hash algorithm ('SHA2' or 'SHA3') */ - setHashAlgorithm: function(hashAlgorithm) { + setHashAlgorithm(hashAlgorithm) { this.cryptoPrimitives.setHashAlgorithm(hashAlgorithm); - }, + } - getCrypto: function() { + getCrypto() { return this.cryptoPrimitives; - }, + } /** * Register the member and return an enrollment secret. @@ -97,7 +96,7 @@ var MemberServices = api.MemberServices.extend({ * @param registrar The identity of the registrar (i.e. who is performing the registration) * @returns Promise for the enrollmentSecret */ - register: function(req, registrar /*Member*/) { + register(req, registrar /*Member*/) { var self = this; return new Promise(function(resolve, reject) { @@ -151,14 +150,14 @@ var MemberServices = api.MemberServices.extend({ } }); }); - }, + } /** * Enroll the member and return an opaque member object * @param req Enrollment request with the following fields: name, enrollmentSecret * @returns Promise for {key,cert,chainKey} */ - enroll: function(req) { + enroll(req) { var self = this; return new Promise(function(resolve, reject) { @@ -248,7 +247,7 @@ var MemberServices = api.MemberServices.extend({ }); }); } -}); +}; // Convert a list of member type names to the role mask currently used by the peer function rolesToMask(roles /*string[]*/) { diff --git a/lib/X509Certificate.js b/lib/X509Certificate.js index 849dc6d407..ef064a790c 100644 --- a/lib/X509Certificate.js +++ b/lib/X509Certificate.js @@ -14,15 +14,15 @@ limitations under the License. */ +'use strict'; + var api = require('./api.js'); var utils = require('./utils.js'); var certPaser = require('./utils-x509cert.js'); -var X509Certificate = api.X509Certificate.extend({ - - _cert: null, +var X509Certificate = class extends api.X509Certificate { - constructor: function(buffer) { + constructor(buffer) { debug('cert:', JSON.stringify(buffer)); // convert certBuffer to arraybuffer var certBuffer = utils.toArrayBuffer(buffer); @@ -36,9 +36,9 @@ var X509Certificate = api.X509Certificate.extend({ debug('error parsing certificate bytes: ', ex) throw ex; } - }, + } - criticalExtension: function(oid) { + criticalExtension(oid) { var ext; debug('oid: ', oid); this._cert.extensions.some(function (extension) { @@ -53,7 +53,7 @@ var X509Certificate = api.X509Certificate.extend({ return _toBuffer(ext.extnValue.value_block.value_hex); } -}); +}; // utility function to convert Javascript arraybuffer to Node buffers function _toBuffer(ab) { diff --git a/lib/api.js b/lib/api.js index 9b08321de8..42e59e06c1 100644 --- a/lib/api.js +++ b/lib/api.js @@ -14,6 +14,8 @@ limitations under the License. */ +'use strict'; + /** * This module defined the API surface for node.js SDK. The APIs are defined * according to the Hyperledger Fabric's [common SDK specification]{@link https://docs.google.com/document/d/1R5RtIBMW9fZpli37E5Li5_Q9ve3BnQ4q3gWmGZj6Sv4/edit?usp=sharing} @@ -21,7 +23,7 @@ * @module api */ -var Base = require('./base.js'); +var utils = require('./utils.js'); /** * Abstract class for a Key-Value store. The Chain class uses this store @@ -34,7 +36,7 @@ var Base = require('./base.js'); * * @class */ -module.exports.KeyValueStore = Base.extend(/** @lends module:api.KeyValueStore.prototype */{ +module.exports.KeyValueStore = class { /** * Get the value associated with name. @@ -42,7 +44,7 @@ module.exports.KeyValueStore = Base.extend(/** @lends module:api.KeyValueStore.p * @param {string} name of the key * @returns Promise for the value corresponding to the key */ - getValue: function(name) {}, + getValue(name) {} /** * Set the value associated with name. @@ -52,7 +54,7 @@ module.exports.KeyValueStore = Base.extend(/** @lends module:api.KeyValueStore.p */ setValue(name, value) {} -}); +}; /** * Abstract class for a suite of crypto algorithms used by the SDK to perform encryption, @@ -62,19 +64,22 @@ module.exports.KeyValueStore = Base.extend(/** @lends module:api.KeyValueStore.p * * @class */ -module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.prototype */{ - - /** - * what's a suitable description of this property? - */ - TCertEncTCertIndex: "1.2.3.4.5.6.7", +module.exports.CryptoSuite = class { + + constructor() { + /** + * what's a good description for this property? + * @member {string} + */ + this.TCertEncTCertIndex = "1.2.3.4.5.6.7"; + } /** * Returns the supported asymmetric key algorithms that this suite represents * * @returns {string} The algorithm name such as "ECDSA", "RSA" etc. */ - getPublicKeyAlgorithm: function() {}, + getPublicKeyAlgorithm() {} /** * Get the security level of the asymmetric keys algorithm, which corresponds to the @@ -82,28 +87,28 @@ module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.proto * * @returns {number} The security level */ - getSecurityLevel: function() {}, + getSecurityLevel() {} /** * Set the security level of the asymmetric keys algorithm * * @param {number} securityLevel The security level */ - setSecurityLevel: function(securityLevel) {}, + setSecurityLevel(securityLevel) {} /** * Get the hash algorithm (such as SHA2, SHA3) * * @returns {string} The hash algorithm */ - getHashAlgorithm: function() {}, + getHashAlgorithm() {} /** * Set the hash algorithm * * @param {string} hashAlgorithm The hash algorithm */ - setHashAlgorithm: function(hashAlgorithm /*string*/ ) {}, + setHashAlgorithm(hashAlgorithm) {} /** * Generate a nonce to use as one-time state key. Size of the nonce @@ -111,7 +116,7 @@ module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.proto * * @returns {byte[]} the random number */ - generateNonce: function() {}, + generateNonce() {} /** * Generate asymmetric key pair @@ -120,7 +125,7 @@ module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.proto * prvKeyObj - RSAKey or ECDSA object of private key * pubKeyObj - RSAKey or ECDSA object of public key */ - generateKeyPair: function() {}, + generateKeyPair() {} /** * Decrypt, using the private key of an asymmetric key pair, a cipher that was @@ -128,7 +133,7 @@ module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.proto * * @returns {byte[]} Decripted bytes */ - asymmetricDecrypt: function(recipientPrivateKey, cipherText) {}, + asymmetricDecrypt(recipientPrivateKey, cipherText) {} /** * Packages the private key into a key pair to use for signing @@ -139,7 +144,7 @@ module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.proto * prvKeyObj - RSAKey or ECDSA object of private key * pubKeyObj - null, as only the private key is needed for signing */ - getKeyPairForSigning: function(privateKey, encoding) {}, + getKeyPairForSigning(privateKey, encoding) {} /** * Packages the public key into a key pair to use for encryption @@ -150,109 +155,115 @@ module.exports.CryptoSuite = Base.extend(/** @lends module:api.CryptoSuite.proto * prvKeyObj - null, as only the public key is needed for encryption * pubKeyObj - RSAKey or ECDSA object of public key */ - getKeyPairForEncryption: function(publicKey, encoding) {}, + getKeyPairForEncryption(publicKey, encoding) {} /** * Signs the message with digital signature * - * @param {Object} key The key pair object as an associative array with the following parameters: + * @param {Buffer} key The key pair object as an associative array with the following parameters: * prvKeyObj - RSAKey or ECDSA object of private key * pubKeyObj - null, as only the private key is needed for signing * @param {Buffer} msg The message content to be signed * @returns {Object} the signature */ - sign: function(key /*Buffer*/ , msg /*Buffer*/ ) {}, + sign(key, msg) {} - ecdsaPrivateKeyToASN1: function(prvKeyHex /*string*/ ) {}, - ecdsaPEMToPublicKey: function(chainKey) {}, - eciesEncryptECDSA: function(ecdsaRecipientPublicKey, msg) {}, - eciesKeyGen: function() {}, - eciesEncrypt: function(recipientPublicKey, msg) {}, - hmac: function(key, bytes) {}, - aesCBCPKCS7Decrypt: function(key, bytes) {}, - aes256GCMDecrypt(key /*Buffer*/ , ct /*Buffer*/ ) {}, - aesKeyGen: function() {}, - hmacAESTruncated: function(key, bytes) {} + ecdsaPrivateKeyToASN1(prvKeyHex /*string*/ ) {} + ecdsaPEMToPublicKey(chainKey) {} + eciesEncryptECDSA(ecdsaRecipientPublicKey, msg) {} + eciesKeyGen() {} + eciesEncrypt(recipientPublicKey, msg) {} + hmac(key, bytes) {} + aesCBCPKCS7Decrypt(key, bytes) {} + aes256GCMDecrypt(key /*Buffer*/ , ct /*Buffer*/ ) {} + aesKeyGen() {} + hmacAESTruncated(key, bytes) {} -}); +}; /** * A model to represent x.509 certificate * * @class */ -module.exports.X509Certificate = Base.extend(/** @lends module:api.X509Certificate.prototype */{ +module.exports.X509Certificate = class { /** * What would be a suitable description of this method? * * @param {Object} Object ID */ - criticalExtension: function(oid) {} + criticalExtension(oid) {} -}); +}; /** * Represents enrollment data for a user. * * @class */ -module.exports.Enrollment = Base.extend(/** @lends module:api.Enrollment.prototype */{ - /** - * @property {Buffer} key private key generated locally by the SDK - */ - key: null, - - /** - * @property {string} cert certificate issued by member services after successful enrollment - */ - cert: "", - - /** - * @property {string} chainKey what's the best description for this? - */ - chainKey: "" -}); +module.exports.Enrollment = class { + + constructor() { + /** + * @member {Buffer} key private key generated locally by the SDK + * @memberof module:api.Enrollment.prototype + */ + this.key = null; + + /** + * @member {string} cert certificate issued by member services after successful enrollment + * @memberof module:api.Enrollment.prototype + */ + this.cert = ""; + + /** + * @member {string} chainKey what's the best description for this? + * @memberof module:api.Enrollment.prototype + */ + this.chainKey = ""; + } +}; /** * A member is an entity that transacts on a chain. * Types of members include end users, peers, etc. */ -module.exports.Member = Base.extend({ +module.exports.Member = class { -}); +}; -module.exports.MemberServices = Base.extend({ +module.exports.MemberServices = class { /** * Get the security level * @returns The security level */ - getSecurityLevel: function() {}, + getSecurityLevel() {} /** * Set the security level * @params securityLevel The security level */ - setSecurityLevel: function(securityLevel /*number*/ ) {}, + setSecurityLevel(securityLevel /*number*/ ) {} /** * Get the hash algorithm * @returns The security level */ - getHashAlgorithm: function() {}, + getHashAlgorithm() {} /** * Set the security level - * @params securityLevel The security level + * @params {string }securityLevel The security level */ - setHashAlgorithm: function(hashAlgorithm /*string*/ ) {}, + setHashAlgorithm(hashAlgorithm) {} /** * Register the member and return an enrollment secret. - * @param req Registration request with the following fields: + * @param {Object} req Registration request with the following fields: * * // The enrollment ID of the member * enrollmentID: "", @@ -274,14 +285,14 @@ module.exports.MemberServices = Base.extend({ * // The allowable roles which can be registered by members registered by this member * delegateRoles: null //string[] * - * @param registrar The identity of the registar (i.e. who is performing the registration) + * @param {Member} registrar The identity of the registar (i.e. who is performing the registration) * @returns promise for enrollmentSecret */ - register: function(req /*RegistrationRequest*/ , registrar /*Member*/ ) {}, + register(req, registrar) {} /** * Enroll the member and return an opaque member object - * @param req Enrollment request with the following fields: + * @param {Object} req Enrollment request with the following fields: * * // The enrollment ID * enrollmentID: "", @@ -291,11 +302,11 @@ module.exports.MemberServices = Base.extend({ * * @returns promise for Enrollment */ - enroll: function(req /*EnrollmentRequest*/ ) {}, + enroll(req) {} /** * Get an array of transaction certificates (tcerts). - * @param req A GetTCertBatchRequest: + * @param {Object} req A GetTCertBatchRequest: * * name: string, * enrollment: an Enrollment object, @@ -304,9 +315,9 @@ module.exports.MemberServices = Base.extend({ * * @returns promise for TCert[] */ - getTCertBatch: function(req /*GetTCertBatchRequest*/ ) {} + getTCertBatch(req) {} -}); +}; module.exports.PrivacyLevel = { Nominal: 0, @@ -316,70 +327,79 @@ module.exports.PrivacyLevel = { /** * The base Certificate class */ -module.exports.Certificate = Base.extend({ +module.exports.Certificate = class { /** * @param privacyLevel - Denoting if the Certificate is anonymous or carrying its owner's identity. */ - constructor: function(cert /*Buffer*/, privateKey, privLevel /*PrivacyLevel*/) { + constructor(cert /*Buffer*/, privateKey, privLevel /*PrivacyLevel*/) { this._cert = cert; this._privateKey = privateKey; this._privacyLevel = privacyLevel; - }, + } - encode: function() { + encode() { return this._cert; } -}); +}; /** * Enrollment certificate. */ -module.exports.ECert = module.exports.Certificate.extend({ +module.exports.ECert = class extends module.exports.Certificate { - constructor: function(cert /*Buffer*/, privateKey) { - module.exports.Certificate.prototype.constructor(cert, privateKey, module.exports.PrivacyLevel.Nominal); + constructor(cert /*Buffer*/, privateKey) { + super(cert, privateKey, module.exports.PrivacyLevel.Nominal); } -}); +}; /** * Transaction certificate. */ -module.exports.TCert = module.exports.Certificate.extend({ +module.exports.TCert = class extends module.exports.Certificate { - constructor: function(publicKey, privateKey) { - module.exports.Certificate.prototype.constructor(publicKey, privateKey, module.exports.PrivacyLevel.Anonymous); + constructor(publicKey, privateKey) { + super(publicKey, privateKey, module.exports.PrivacyLevel.Anonymous); } -}); +}; /** * * @class */ -module.exports.Chain = Base.extend({ +module.exports.Chain = class { + + constructor() { + /** + * @member {api.CryptoSuite} cryptoPrimitives The crypto primitives object provides access to the crypto suite + * for functions like sign, encrypt, decrypt, etc. + * @memberof module:api.Chain.prototype + */ + this.cryptoPrimitives = utils.getCryptoSuite(); + } -}); +}; -module.exports.Peer = Base.extend({ +module.exports.Peer = class { /** * Get the chain of which this peer is a member. * @returns {Chain} The chain of which this peer is a member. */ - getChain: function() {}, + getChain() {} /** * Get the URL of the peer. * @returns {string} Get the URL associated with the peer. */ - getUrl: function() {}, + getUrl() {} /** * Send a transaction to this peer. * @param tx A transaction * @param eventEmitter The event emitter */ - sendTransaction: function(tx, eventEmitter) {} + sendTransaction(tx, eventEmitter) {} -}); +}; diff --git a/lib/base.js b/lib/base.js deleted file mode 100644 index cb7b2106ea..0000000000 --- a/lib/base.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright 2016 IBM All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Copyright © 2014 &yet, LLC and AmpersandJS contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software - * and associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -var assign = require('lodash/assign'); - -function Base() {} - -// the extend method used to extend prototypes, maintain inheritance chains for instanceof -// and allow for additions to the model definitions. -function extend(protoProps) { - /*jshint validthis:true*/ - var parent = this; - var child; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent's constructor. - if (protoProps && protoProps.hasOwnProperty('constructor')) { - child = protoProps.constructor; - } else { - child = function () { - return parent.apply(this, arguments); - }; - } - - // Add static properties to the constructor function from parent - assign(child, parent); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function. - var Surrogate = function () { this.constructor = child; }; - Surrogate.prototype = parent.prototype; - child.prototype = new Surrogate(); - - // set prototype level objects - - // Mix in all prototype properties to the subclass if supplied. - if (protoProps) { - for(var i = 0; i < arguments.length; i++) { - var def = arguments[i]; - assign(child.prototype, def); - } - } - - // Set a convenience property in case the parent's prototype is needed - // later. - child.__super__ = parent.prototype; - - return child; -} - -Base.extend = extend; - -module.exports = Base; - -