Skip to content

Commit

Permalink
FAB-1421 Implement Identity and MSP classes
Browse files Browse the repository at this point in the history
as an initial step, implementing the Identity and MSP classes
so that the SDK can construct identity objects from PEM certs
in configs, which would eventually come from the
Configuration/Genesis Block.

- added back util for handling X509 certificates
- rebased on top of changeset 3313
- rebased on top of master

Change-Id: I49c5a4773645312197651326c421767bef512884
Signed-off-by: Jim Zhang <jzhang@us.ibm.com>
  • Loading branch information
jimthematrix committed Dec 19, 2016
1 parent 9c3e33f commit 669acce
Show file tree
Hide file tree
Showing 10 changed files with 439 additions and 517 deletions.
78 changes: 0 additions & 78 deletions hfc/lib/X509Certificate.js

This file was deleted.

93 changes: 65 additions & 28 deletions hfc/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ module.exports.CryptoSuite = class {
* Imports a key from its raw representation using opts.
* @param {byte[]} raw Raw bytes of the key to import
* @param {Object} opts
* algorithm: an identifier for the algorithm to be used
* ephemeral: true if the key to generate has to be ephemeral
* <br>`type`: type of information that 'raw' represents: x509 certificate,
* <br>`algorithm`: an identifier for the algorithm to be used
* <br>`ephemeral`: true if the key to generate has to be ephemeral
* @returns {Key} An instance of the Key class wrapping the raw key bytes
*/
importKey(raw, opts) {}
Expand Down Expand Up @@ -213,6 +214,65 @@ module.exports.Key = class {
toBytes() {}
};

module.exports.CryptoAlgorithms = {
// ECDSA Elliptic Curve Digital Signature Algorithm (key gen, import, sign, verify),
// at default security level.
// Each BCCSP may or may not support default security level. If not supported than
// an error will be returned.
ECDSA: 'ECDSA',
// ECDSA Elliptic Curve Digital Signature Algorithm over P-256 curve
ECDSAP256: 'ECDSAP256',
// ECDSA Elliptic Curve Digital Signature Algorithm over P-384 curve
ECDSAP384: 'ECDSAP384',
// ECDSAReRand ECDSA key re-randomization
ECDSAReRand: 'ECDSA_RERAND',

// RSA at the default security level.
// Each BCCSP may or may not support default security level. If not supported than
// an error will be returned.
RSA: 'RSA',
// RSA at 1024 bit security level.
RSA1024: 'RSA1024',
// RSA at 2048 bit security level.
RSA2048: 'RSA2048',
// RSA at 3072 bit security level.
RSA3072: 'RSA3072',
// RSA at 4096 bit security level.
RSA4096: 'RSA4096',

// AES Advanced Encryption Standard at the default security level.
// Each BCCSP may or may not support default security level. If not supported than
// an error will be returned.
AES: 'AES',
// AES Advanced Encryption Standard at 128 bit security level
AES128: 'AES128',
// AES Advanced Encryption Standard at 192 bit security level
AES192: 'AES192',
// AES Advanced Encryption Standard at 256 bit security level
AES256: 'AES256',

// HMAC keyed-hash message authentication code
HMAC: 'HMAC',
// HMACTruncated256 HMAC truncated at 256 bits.
HMACTruncated256: 'HMAC_TRUNCATED_256',

// SHA Secure Hash Algorithm using default family.
// Each BCCSP may or may not support default security level. If not supported than
// an error will be returned.
SHA: 'SHA',
// SHA256
SHA256: 'SHA256',
// SHA384
SHA384: 'SHA384',
// SHA3_256
SHA3_256: 'SHA3_256',
// SHA3_384
SHA3_384: 'SHA3_384',

// X509Certificate Label for X509 certificate related operation
X509Certificate: 'X509Certificate'
};

/**
* Represents enrollment data for a user.
*
Expand All @@ -235,31 +295,14 @@ module.exports.Enrollment = class {
}
};

/**
* @class
*/
module.exports.PrivacyLevel = {
/**
* @member {constant} Nominal Representing a certain identity
* @memberof module:api.PrivacyLevel
*/
Nominal: 0,

/**
* @member {constant} Anonymous Anonymous
* @memberof module:api.PrivacyLevel
*/
Anonymous: 1
};

/**
* The base Certificate class
*
* @class
*/
module.exports.Certificate = class {

constructor(cert, privateKey, privacyLevel) {
constructor(cert, privateKey) {
/**
* @member {buffer} cert The certificate
* @memberof module:api.Certificate
Expand All @@ -271,12 +314,6 @@ module.exports.Certificate = class {
* @memberof module:api.Certificate
*/
this._privateKey = privateKey;

/**
* @member {module:api.PrivacyLevel} privacyLevel - Denoting if the Certificate is anonymous or carrying its owner's identity.
* @memberof module:api.Certificate
*/
this._privacyLevel = privacyLevel;
}

encode() {
Expand All @@ -292,7 +329,7 @@ module.exports.Certificate = class {
module.exports.ECert = class extends module.exports.Certificate {

constructor(cert, privateKey) {
super(cert, privateKey, module.exports.PrivacyLevel.Nominal);
super(cert, privateKey);
}

};
Expand All @@ -305,7 +342,7 @@ module.exports.ECert = class extends module.exports.Certificate {
module.exports.TCert = class extends module.exports.Certificate {

constructor(publicKey, privateKey) {
super(publicKey, privateKey, module.exports.PrivacyLevel.Anonymous);
super(publicKey, privateKey);
}
};

3 changes: 1 addition & 2 deletions hfc/lib/impl/CryptoSuite_ECDSA_AES.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite {

/**
* This is an implementation of {@link module:api.CryptoSuite#importKey}
* To be implemented
*/
importKey(raw, opts) {
if (!opts)
Expand All @@ -166,7 +165,7 @@ var CryptoSuite_ECDSA_AES = class extends api.CryptoSuite {
if (!opts.algorithm)
throw new Error('Parameter "opts" missing required field "algorithm"');

if (opts.algorithm === 'X509Certificate') {
if (opts.algorithm === api.CryptoAlgorithms.X509Certificate) {
// importing public key from an x.509 certificate
var pemString = Buffer.from(raw).toString();
try {
Expand Down
1 change: 1 addition & 0 deletions hfc/lib/impl/ecdsa/key.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ module.exports = class ECDSA_KEY {
buff = pointToOctet(this.getPublicKey()._key);
}

// always use SHA256 regardless of the key size in effect
return Hash.sha2_256(buff);
}

Expand Down
120 changes: 120 additions & 0 deletions hfc/lib/msp/identity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use strict';

var grpc = require('grpc');

var identityProto = grpc.load(__dirname + '/../protos/identity.proto').msp;

/**
* This interface is shared within the peer and client API of the membership service provider.
* Identity interface defines operations associated to a "certificate".
* That is, the public part of the identity could be thought to be a certificate,
* and offers solely signature verification capabilities. This is to be used
* at the client side when validating certificates that endorsements are signed
* with, and verifying signatures that correspond to these certificates.
*
* @class
*/
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
*/
constructor(id, certificate, publicKey, msp) {
if (!id)
throw new Error('Missing required parameter "id".');

if (!certificate)
throw new Error('Missing required parameter "certificate".');

if (!publicKey)
throw new Error('Missing required parameter "publicKey".');

if (!msp)
throw new Error('Missing required parameter "msp".');

this._id = id;
this._certificate = certificate;
this._publicKey = publicKey;
this._msp = msp;
}

/**
* Returns the identifier of this identity
* @returns {string}
*/
getId() {
return this._id;
}

/**
* Returns the identifier of the Membser Service Provider that manages
* this identity in terms of being able to understand the key algorithms
* and have access to the trusted roots needed to validate it
* @returns {string}
*/
getMSPId() {
return this._msp.getId();
}

/**
* This uses the rules that govern this identity to validate it.
* E.g., if it is a fabric TCert implemented as identity, validate
* will check the TCert signature against the assumed root certificate
* authority.
* @returns {boolean}
*/
isValid() {
this._msp.validate(this);
}

/**
* Returns the organization units this identity is related to
* as long as this is public information. In certain implementations
* this could be implemented by certain attributes that are publicly
* associated to that identity, or the identifier of the root certificate
* authority that has provided signatures on this certificate.
* Examples:
* - OrganizationUnit of a fabric-tcert that was signed by TCA under name
* "Organization 1", would be "Organization 1".
* - OrganizationUnit of an alternative implementation of tcert signed by a public
* CA used by organization "Organization 1", could be provided in the clear
* as part of that tcert structure that this call would be able to return.
* @returns {string}
*/
getOrganizationUnits() {
return 'dunno!';
}

/**
* Verify a signature over some message using this identity as reference
* @param {byte[]} msg The message to be verified
* @param {byte[]} signature The signature generated against the message "msg"
* @param {Object} opts Options include 'policy' and 'label'
*/
verify(msg, signature, opts) {
return this._msp.cryptoSuite.verify(this._publicKey, signature, msg);
}

/**
* Verify attributes against the given attribute spec
* TODO: when this method's design is finalized
*/
verifyAttributes(proof, attributeProofSpec) {
return true;
}

/**
* Converts this identity to bytes
* @returns {Buffer} protobuf-based serialization with two fields: "mspid" and "certificate PEM bytes"
*/
serialize() {
var serializedIdentity = new identityProto.SerializedIdentity();
serializedIdentity.Mspid = this.getMSPId();
serializedIdentity.IdBytes = Buffer.from(this._certificate);
return serializedIdentity.toBuffer();
}
};

module.exports = Identity;
Loading

0 comments on commit 669acce

Please sign in to comment.