在Hyperledger Fabric中为用户身份设置PEM属性 [英] Setting PEM attributes for user identities in Hyperledger Fabric

查看:167
本文介绍了在Hyperledger Fabric中为用户身份设置PEM属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有一个Fabric CA的单组织设置. CA Server与MySQL一起运行.我正在使用NodeSDK来连接事务并将其发布到Chaincode.

I have a single-org setup running with one Fabric CA. CA Server is running with MySQL. I'm using NodeSDK to connect and issue transactions to chaincode.

我可以为同行和订购者设置国家,州,地区,组织和组织单位属性.但是,当我在Fabric中注册和注册用户"时,并不是所有属性都已设置.从证书文件中可以看到,仅设置了公用名"和组织单位"属性.

I'm able to set Country, State, Locality, Organisation and Organisation Unit attributes for the peers and orderers. However, when I register and enroll "users" with the Fabric, not all attributes are being set. Only the Common Name and Organisation Unit attributes are set as seen from the certificate file.

以下是我用于注册和注册用户的代码段:

Following is my snippet for registering and enrolling users:

await gateway.connect(connectionProfile, { wallet, identity: 'admin', discovery: { enabled: false } });

ca = await gateway.getClient().getCertificateAuthority();
adminIdentity = gateway.getCurrentIdentity();

const secret = await ca.register({
                affiliation: user.$affiliation,
                enrollmentID: user.$name,
                role: user.$role,
               }, adminIdentity);

const enrollment = await ca.enroll({
                    enrollmentID: user.$name,
                    enrollmentSecret: secret,
                 });
const userIdentity = await X509WalletMixin.createIdentity(process.env.ACTIVE_MSP, enrollment.certificate, enrollment.key.toBytes());

在这里,用户"是我在应用程序中使用的参与者的模型.公用名(CN)设置为"enrollmentID",组织单位设置为"role" +"affiliation",并且为用户生成的证书具有以下信息:

Here, "user" is a model for a participant that I'm using in my application. The Common Name (CN) is set to "enrollmentID" and Organisation Unit is set to "role" + "affiliation" and the resultant certificate for the user has the following information:

Owner: CN=jondoe, OU=client + OU=admin.forwarder.com
Issuer: CN=ca.allparticipants.logistics.com, 
O=allparticipants.logistics.com, L=Bengaluru, ST=Karnataka, C=IN
Serial number: ea385863390c07c320fd6717de7878fd9f81dc3e
Valid from: Mon Apr 15 14:11:00 IST 2019 until: Tue Apr 14 14:16:00 IST 2020
Certificate fingerprints:
     MD5:  …<value>
     SHA1: …<value>
     SHA256: …<value>
Signature algorithm name: SHA256withECDSA
Subject Public Key Algorithm: 256-bit EC key
Version: 3

Extensions: 
…

我们可以看到,颁发者的完整C,ST,L,O,OU和CN属性可用.这属于相应组织的MSP.但是,只有用户的CN和OU可用.

As we can see, complete C, ST, L, O, OU and CN attributes of the Issuer is available. This belongs to MSP of the respective Org. However, only CN and OU of the user is available.

因此,有一种方法可以在注册或注册用户时设置用户的其他属性(C,ST,L和O).还是我们必须从发行者信息中推断出这些属性?

So is there a way with which we can set other attributes of the user (C, ST, L and O) while registering or enrolling user. Or do we have to infer these attributes from the issuer information?

更新:1 : 我检查了node-sdk内部调用的fabric-ca-client cli选项.检查了注册api.它也没有设置C,ST,L和O的选项.

Update: 1: I checked the fabric-ca-client cli options which the node-sdk calls internally. Checked the register api. It does not give an option to set C, ST, L, and O either.

更新: fabric-ca是否支持将这些属性设置为使用者名称"?

Updates: Does fabric-ca support setting these attributes to the Subject Name?

更新:2 : 仔细阅读fabric-ca-client的文档并按照@nyet的建议,我观察到我们可以在csr.names属性中设置这些值,并将其提供给enroll命令的'csr'参数.下面是更新的代码段:

Update: 2: Going through the documentation of fabric-ca-client and as suggested by @nyet, I observed that we can set these values in csr.names attribute and supply it to 'csr' argument of the enroll command. The updated code snippet below:

await gateway.connect(connectionProfile, { wallet, identity: 'admin', discovery: { enabled: false } });

ca = await gateway.getClient().getCertificateAuthority();

adminIdentity = gateway.getCurrentIdentity();

adminIdentity = gateway.getCurrentIdentity();

const secret = await ca.register({
            affiliation: user.$affiliation,
            enrollmentID: user.$name,
            role: user.$role,
           }, adminIdentity);

const csrObj: any = {};
csrObj.names = 'O=Forwarder,C=IN,ST=Karnataka,L=Bengaluru';

const enrollment = await ca.enroll({
            csr: csrObj.toString(),
            enrollmentID: user.$name,
            enrollmentSecret: secret,
            });

const userIdentity = await X509WalletMixin.createIdentity(process.env.ACTIVE_MSP, enrollment.certificate, enrollment.key.toBytes());

但是,我收到这样的错误消息:

However, I get an error with this that says:

无法注册smithdoe20,错误:%o message =注册失败,错误[[{{code:0," message:" {\"code \":9002,\ message \:\" CSR解码失败\}"}]]],堆栈=错误:注册失败,错误为[[{{code:0," message:" {\"code \":9002,\"message \:\" CSR解码失败\}"}]]

Failed to enroll smithdoe20, error:%o message=Enrollment failed with errors [[{"code":0,"message":"{\"code\":9002,\" message\":\"CSR Decode failed\"}"}]], stack=Error: Enrollment failed with errors [[{"code":0,"message":"{\"code\":9002,\"message\":\"CSR Decode failed\"}"}]]

类似的JIRA问题:

Similar JIRA issue: https://jira.hyperledger.org/browse/FAB-14051?jql=project%20%3D%20FAB%20AND%20statusCategory%20!%3D%20Done%20AND%20type%20%3D%20Bug%20AND%20component%20%3D%20fabric-sdk-node%20AND%20project%20%3D%20FAB%20ORDER%20BY%20createdDate%20ASC

更新:3 : Node-SDK文档指出,CSR字段应为PEM编码的PKCS#10证书签名请求.

Update: 3: The Node-SDK documentation states that the CSR field should be a PEM-encoded PKCS#10 certificate signing request.

  1. 我尝试利用node-forge npm模块生成密钥并使用它签名建议.但是,这提供了RSA密钥.
  2. 尝试使用node-pem.也没有解决.

最后,尝试使用以下命令生成ECDSA密钥并离线创建CSR: 1.密钥生成:openssl ecparam -name prime256v1 -genkey -noout -out my-key.pem 2. CSR:openssl req -new -sha256 -key my-key.pem -out my.csr

Finally, tried generating the ECDSA keys and created a CSR offline using the following commands: 1. Keys generation: openssl ecparam -name prime256v1 -genkey -noout -out my-key.pem 2. CSR: openssl req -new -sha256 -key my-key.pem -out my.csr

从文件系统中读取此CSR,并将其传递给注册请求,如下所示:

Read this CSR from the file system and passed it to Enrolment Request as follows:

 const csrNewVal = readFileSync('/Users/mrudavshukla/projects/pem-trials/ecdsa/my.csr', 'utf8');
 const enrollment = await ca.enroll({
                    csr: csrNewVal,
                    enrollmentID: user.$name,
                    enrollmentSecret: secret,
                });

能够成功注册用户.

现在,当我们通过CSR时,fabric-ca不会将注册密钥返回给我们.因此,我从文件系统的#1命令中检索了私钥,并尝试按如下方式将该用户的身份详细信息保存在X509钱包中:

Now, when we're passing the CSR, fabric-ca does not return us the enrolment key back. Thus, I retrieved the private key from #1 command from the file system and tried saving this user's identity details in X509 wallet as follows:

const privateNewVal = readFileSync('/Users/mrudavshukla/projects/pem-trials/ecdsa/my-key.pem', 'utf8');
const userIdentity = await X509WalletMixin.createIdentity(process.env.ACTIVE_MSP, enrollment.certificate, privateNewVal);

但是,这将引发以下错误:

However, this throws the following error:

错误:[crypto_ecdsa_aes]:importKey-{"message":不了解ECDSA私钥和证书以外的PEM内容",堆栈":错误:不了解ECDSA私钥和证书以外的PEM内容....

error: [crypto_ecdsa_aes]: importKey - {"message":"Does not understand PEM contents other than ECDSA private keys and certificates","stack":"Error: Does not understand PEM contents other than ECDSA private keys and certificates....

接下来,我尝试使用不提供CSR时fabric-ca生成的证书检查为该用户保存的证书.两者的结构和用于公钥的签名算法都完全相同.

Next, I tried checking the certificate that was saved for this user with the one that fabric-ca generates when we do not supply CSR. Both are quite identical in structure and the signature algorithms used for the public key.

我错过任何重要环节吗?

Am I missing out on any critical portion?

推荐答案

毫无意义地寻找其他模块来生成ECDSA密钥并使用这些密钥对CSR进行签名.架构本身提供了执行此操作的模块.解决方法如下:

There's no point looking out for additional modules to generate ECDSA keys and signing CSR with those keys. The fabric itself provides modules to do that. Solution steps below:

  1. "fabric-client"模块提供CryptoSuite实现.使用此加密套件,我们可以生成密钥.这些密钥将是ECDSA 256位密钥.
  2. 我们可以使用"jsrsasign"模块创建CSR.在创建CSR时,我们可以将#1中生成的密钥与主题信息一起传递给该方法.它的实现将对其进行签名.当我们不通过CSR时,Fabric内部使用此方法.
  3. 接下来,将此CSR传递给EnrollmentRequest.
  4. 在使用X509WalletMixin创建要存储到钱包中的身份时,请使用注册请求中的证书和#1生成的密钥.

以下代码:

await gateway.connect(connectionProfile, { wallet, identity: 'admin', discovery: { enabled: false } });

ca = await gateway.getClient().getCertificateAuthority();
adminIdentity = gateway.getCurrentIdentity();

const secret = await ca.register({
                affiliation: user.$virtualOrganizationBranch,
                enrollmentID: user.$name,
                role: user.$role,
            }, adminIdentity);

const privateKey = await hfc.newCryptoSuite().generateKey({ephemeral: true});

const subjectDN: string = 'CN=' + user.$name + ',C=IN,ST=Karnataka,L=Bengaluru,O=Forwarder';

const asn1 = jsrsa.asn1;
const csr = asn1.csr.CSRUtil.newCSRPEM({
                sbjprvkey: privateKey.toBytes(),
                sbjpubkey: privateKey.getPublicKey().toBytes(),
                sigalg: 'SHA256withECDSA',
                subject: {str: asn1.x509.X500Name.ldapToOneline(subjectDN)},
            });

const enrollment = await ca.enroll({
                csr,
                enrollmentID: user.$name,
                enrollmentSecret: secret,
            });

const userIdentity = await X509WalletMixin.createIdentity(process.env.ACTIVE_MSP, enrollment.certificate, privateKey.toBytes());
await wallet.import(user.$name, userIdentity);

这篇关于在Hyperledger Fabric中为用户身份设置PEM属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆