Skip to content

Commit 3fe2f76

Browse files
author
Simon Stone
committed
[FAB-16521] Remove dependency on x509 module
The x509 module is unmaintained, and no longer builds on Node.js v12. It no longer built on Node.js v10, but we managed to patch it in Fabric v1.4 when we upgraded to Node.js v10. For Fabric v2.0, we will remove this dependency and remove the getX509Certificate() API which returned a class instance from this module. This will improve build times as there is no need to build this native dependency. Also, we were using TWO certificate parsers for the same job, so dump both x509 and jsrsasign, and move to @fidm/x509 which does the job nicely. The fabric-shim-crypto package still uses jsrsasign, but that package actually has to perform crypto ops. Signed-off-by: Simon Stone <sstone1@uk.ibm.com> Change-Id: I257ca8ee0a1b3cd4118af48c2cd8f57c796bf2ed
1 parent cfd41a4 commit 3fe2f76

File tree

7 files changed

+2445
-2189
lines changed

7 files changed

+2445
-2189
lines changed

fabric-shim-crypto/package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fabric-shim/lib/chaincode.js

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
const ProtoLoader = require('./protoloader');
1010
const path = require('path');
1111
const util = require('util');
12-
const X509 = require('@ampretia/x509');
13-
const jsrsasign = require('jsrsasign');
12+
const {Certificate} = require('@fidm/x509');
1413
const Logger = require('./logger');
1514

1615
const utils = require('./utils/utils');
@@ -213,7 +212,7 @@ class Shim {
213212
}
214213
}
215214

216-
// special OID used by Fabric to save attributes in x.509 certificates
215+
// special OID used by Fabric to save attributes in X.509 certificates
217216
const FABRIC_CERT_ATTR_OID = '1.2.3.4.5.6.7.8.1';
218217

219218
/**
@@ -248,23 +247,25 @@ class ClientIdentity {
248247

249248
this.mspId = signingId.getMspid();
250249

251-
const idBytes = signingId.getIdBytes().toBuffer();
252-
const normalizedCert = normalizeX509(idBytes.toString(), loggerPrefix);
253-
const cert = X509.parseCert(normalizedCert);
254-
this.cert = cert;
250+
this.idBytes = signingId.getIdBytes().toBuffer();
251+
const normalizedCert = normalizeX509(this.idBytes.toString(), loggerPrefix);
255252

253+
// assemble the unique ID based on certificate
254+
const certificate = Certificate.fromPEM(normalizedCert);
255+
function formatDN(dn) {
256+
return dn.attributes.map((attribute) => {
257+
const value = attribute.value.replace('/', '\\/');
258+
return `/${attribute.shortName}=${value}`;
259+
}).join('');
260+
}
261+
this.id = `x509::${formatDN(certificate.subject)}::${formatDN(certificate.issuer)}`;
262+
const extension = certificate.extensions.find((ext) => ext.oid === FABRIC_CERT_ATTR_OID);
256263
this.attrs = {};
257-
if (cert && cert.extensions && cert.extensions[FABRIC_CERT_ATTR_OID]) {
258-
const attr_string = cert.extensions[FABRIC_CERT_ATTR_OID];
259-
const attr_object = JSON.parse(attr_string);
260-
const attrs = attr_object.attrs;
261-
this.attrs = attrs;
264+
if (extension) {
265+
const str = extension.value.toString();
266+
const obj = JSON.parse(str);
267+
this.attrs = obj.attrs;
262268
}
263-
264-
// assemble the unique ID based on certificate
265-
const x = new jsrsasign.X509();
266-
x.readCertPEM(normalizedCert);
267-
this.id = `x509::${x.getSubjectString()}::${x.getIssuerString()}`;
268269
logger.debug(`${loggerPrefix} Generated client identity`, this.mspId, this.attrs, this.id);
269270
}
270271

@@ -285,12 +286,24 @@ class ClientIdentity {
285286
return this.mspId;
286287
}
287288

289+
/**
290+
* getIDBytes returns the ID bytes associated with the invoking identity. If the MSP is
291+
* implemented with X.509 certificates, then these ID bytes will be those of the X.509
292+
* certificate. If you wish to inspect the contents of the X.509 certificate, then you
293+
* must use an X.509 parsing library (for example, jsrsasign or @fidm/x509) to decode
294+
* these ID bytes.
295+
* @returns {Uint8Array}
296+
*/
297+
getIDBytes() {
298+
return this.idBytes;
299+
}
300+
288301
/**
289302
* getAttributeValue returns the value of the client's attribute named `attrName`.
290303
* If the invoking identity possesses the attribute, returns the value of the attribute.
291304
* If the invoking identity does not possess the attribute, returns null.
292305
* @param {string} attrName Name of the attribute to retrieve the value from the
293-
* identity's credentials (such as x.509 certificate for PKI-based MSPs).
306+
* identity's credentials (such as X.509 certificate for PKI-based MSPs).
294307
* @returns {string | null} Value of the attribute or null if the invoking identity
295308
* does not possess the attribute.
296309
*/
@@ -307,7 +320,7 @@ class ClientIdentity {
307320
* assertAttributeValue verifies that the invoking identity has the attribute named `attrName`
308321
* with a value of `attrValue`.
309322
* @param {string} attrName Name of the attribute to retrieve the value from the
310-
* identity's credentials (such as x.509 certificate for PKI-based MSPs)
323+
* identity's credentials (such as X.509 certificate for PKI-based MSPs)
311324
* @param {string} attrValue Expected value of the attribute
312325
* @returns {boolean} True if the invoking identity possesses the attribute and the attribute
313326
* value matches the expected value. Otherwise, returns false.
@@ -322,52 +335,6 @@ class ClientIdentity {
322335
return false;
323336
}
324337
}
325-
326-
/**
327-
* An object representing an x.509 certificate with the following structure:
328-
* <br><pre>
329-
* { subject: {
330-
* countryName: 'US',
331-
* postalCode: '10010',
332-
* stateOrProvinceName: 'NY',
333-
* localityName: 'New York',
334-
* streetAddress: '902 Broadway, 4th Floor',
335-
* organizationName: 'Nodejitsu',
336-
* organizationalUnitName: 'PremiumSSL Wildcard',
337-
* commonName: '*.nodejitsu.com'
338-
* },
339-
* issuer: {
340-
* countryName: 'GB',
341-
* stateOrProvinceName: 'Greater Manchester',
342-
* localityName: 'Salford',
343-
* organizationName: 'COMODO CA Limited',
344-
* commonName: 'COMODO High-Assurance Secure Server CA'
345-
* },
346-
* notBefore: Sun Oct 28 2012 20:00:00 GMT-0400 (EDT),
347-
* notAfter: Wed Nov 26 2014 18:59:59 GMT-0500 (EST),
348-
* altNames: [ '*.nodejitsu.com', 'nodejitsu.com' ],
349-
* signatureAlgorithm: 'sha1WithRSAEncryption',
350-
* fingerPrint: 'E4:7E:24:8E:86:D2:BE:55:C0:4D:41:A1:C2:0E:06:96:56:B9:8E:EC',
351-
* publicKey: {
352-
* algorithm: 'rsaEncryption',
353-
* e: '65537',
354-
* n: '.......'
355-
* }
356-
* }
357-
* @typedef {object} X509Certificate
358-
* @class
359-
* @memberof fabric-shim
360-
*/
361-
362-
/**
363-
* getX509Certificate returns the X509 certificate associated with the invoking identity,
364-
* or null if it was not identified by an X509 certificate, for instance if the MSP is
365-
* implemented with an alternative to PKI such as [Identity Mixer]{@link https://jira.hyperledger.org/browse/FAB-5673}.
366-
* @returns {X509Certificate | null}
367-
*/
368-
getX509Certificate() {
369-
return this.cert;
370-
}
371338
}
372339

373340
function parsePeerUrl(url) {
@@ -403,7 +370,7 @@ function isTLS() {
403370
/*
404371
* Make sure there's a start line with '-----BEGIN CERTIFICATE-----'
405372
* and end line with '-----END CERTIFICATE-----', so as to be compliant
406-
* with x509 parsers
373+
* with X.509 parsers
407374
*/
408375
function normalizeX509(raw, loggerPrefix) {
409376
logger.debug(`${loggerPrefix} [normalizeX509] raw cert: ${raw}`);

0 commit comments

Comments
 (0)