[英]Hyperledger Fabric: Unable to Update Certificate Attributes in Node SDK
I'm making a block chain application for which I'm using Hyperledger Fabric Node SDK .我正在制作一个使用Hyperledger Fabric Node SDK的区块链应用程序。 When a user signs up then the user's certificate is added to the wallet as an identity.
当用户注册时,用户的证书将作为身份添加到钱包中。 Now the attributes that I'm storing in a user's certificate are the email and password .
现在我存储在用户证书中的属性是email 和 password 。 Also, the user's password is not stored anywhere else, but only in the certificate.
此外,用户的密码不会存储在其他任何地方,而只会存储在证书中。 Now, I also need to update the user's password.
现在,我还需要更新用户的密码。
Searching on the internet, I got to know that the attributes in the certificate can be updated using the identityService's update function provided in Node and you don't have to re-enroll a user if you're using the identityService's update function.在互联网上搜索,我知道证书中的属性可以使用 Node 中提供的identityService 的更新 function进行更新,如果您使用的是 identityService 的更新 function,则无需重新注册用户。 The issue is that I tried it and the response showed the updated password.
问题是我试过了,响应显示更新的密码。 But then when I checked the certificate, the old password was still there ie it had not been updated.
但是当我检查证书时,旧密码仍然存在,即尚未更新。 I'm using the fabric-ca-client package for the FabricCAServices and the x509 package for the x509 certificates.
我将fabric-ca-client package 用于 FabricCAServices,将x509 package 用于 x509 证书。
The code with which I am enrolling and registering the user is as follows:我注册和注册用户的代码如下:
let ccp = await getCCP(orgName);
const caURL = await getCaUrl(orgName, ccp)
const ca = new FabricCAServices(caURL);
const walletPath = await getWalletPath(orgName);
const wallet = await Wallets.newFileSystemWallet(walletPath);
logger.info(`Wallet path: ${walletPath}`);
const userIdentity = await wallet.get(email); //getting user from the wallet
if (userIdentity) //if found so user is already registered
{
return "User Already Exists";
}
//else user does not exist so checking if admin exists
let adminIdentity = await wallet.get('admin'); //getting admin from wallet
if (!adminIdentity) { //if not found so admin does not exist
logger.debug('An identity for the admin user "admin" does not exist in the wallet');
await enrollAdmin(orgName, ccp); //enrolling the admin
adminIdentity = await wallet.get('admin');
logger.debug("Admin Enrolled Successfully");
}
//now admin exists, so making a user object for authenticating with the CA(i.e. admin)
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
let secret;
try {
//registering the user, enrolling the user, and importing the new identity into the wallet.
secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: email, role: 'client', attrs: [{name: 'userType', value: userType, ecert: true},{name: 'password', value: password, ecert: true}]}, adminUser);
} catch (error) {
return error.message;
}
const enrollment = await ca.enroll({ enrollmentID: email, enrollmentSecret: secret, attr_reqs: [{ name: 'userType', optional: false }, { name: 'password', optional: false }] });
let x509Identity;
if (orgName == "Org1") {
x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
} else if (orgName == "Org2") {
x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org2MSP',
type: 'X.509',
};
}
await wallet.put(email, x509Identity); //adding user to wallet
return "Registered!";
And the code with which I check the attributes stored in the password is:我检查存储在密码中的属性的代码是:
//Getting wallet path for orgName...
const walletPath = await getWalletPath(orgName);
const wallet = await Wallets.newFileSystemWallet(walletPath);
logger.info(`Wallet path: ${walletPath}`);
//getting this user from the wallet
const userIdentity = await wallet.get(email);
if (userIdentity) { //if found i.e. user is registered
//parsing certificate to get password
var issuer = x509.parseCert(userIdentity.credentials.certificate);
var jsn = issuer.extensions['1.2.3.4.5.6.7.8.1'];
jsn = jsn.substring(2);
jsn = (JSON.parse(jsn));
//here jsn.attrs.password has the password
}
And the code that I'm using to update the certificate attributes is:我用来更新证书属性的代码是:
let ccp = await getCCP(orgName);
const caURL = await getCaUrl(orgName, ccp);
const ca = new FabricCAServices(caURL);
//Getting wallet path for orgName...
const walletPath = await getWalletPath(orgName);
const wallet = await Wallets.newFileSystemWallet(walletPath);
logger.info(`Wallet path: ${walletPath}`);
const userIdentity = await wallet.get(email); //getting this user from the wallet
if (userIdentity) { //if found i.e. user is registered
//Create a new gateway for connecting to our peer node
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: email, discovery: { enabled: true, asLocalhost: true } });
const identityService = ca.newIdentityService();
let adminIdentity = await wallet.get('admin'); //getting admin from wallet
//now making a user object of the admin
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
var theIdentityRequest = { enrollmentID: email, affiliation: 'org1.department1', attrs: [ {name: 'userType', value: 'Student', ecert: true},{name: 'password', value: newPassword, ecert: true} ] };
logger.warn("The Request: ", theIdentityRequest);
let response = await identityService.update(email, theIdentityRequest, adminUser);
logger.warn("userIdenity attributes: ",response.result.attrs);
await gateway.disconnect();
}
I want to know why the certificate still has the old password and how to update the password in the certificate.我想知道为什么证书仍然有旧密码以及如何更新证书中的密码。 And I also want to know that does the identityService update the attributes in the x509 certificate or is reenrolling the user necessary for this?
而且我还想知道 identityService 是否更新了 x509 证书中的属性,还是为此重新注册了必要的用户?
You can fix it by doing reenroll
as you said.您可以按照您所说的
reenroll
来修复它。
The update
command of IdentityService
is to update the identity of registered
user in CA. IdentityService
的update
命令是更新 CA 中registered
用户的身份。
Since this is not the process of updating the certificate, the only way to obtain a certificate containing the newly modified Attr
is to obtain a new certificate (the certificate is the X.509 standard).由于这不是更新证书的过程,因此获取包含新修改的
Attr
的证书的唯一方法是获取新证书(该证书是 X.509 标准)。
Why does the attr change require a new certificate?为什么 attr 更改需要新证书?
Attr
is existed in extensions
in the X509(v3) certificate and has the following format.Attr
存在于 X509(v3) 证书的extensions
中,格式如下。X509v3 extensions:
...
1.2.3.4.5.6.7.8.1:
{"attrs":{"hf.Affiliation":"org1.department1","hf.EnrollmentID":"appUser5","hf.Type":"client","userType":"userType"}}
...
Attr
is modified, extensions
are modified.Attr
被修改时, extensions
被修改。extenstions
are also included in the certificate integrity verification process.extenstions
也包含在证书完整性验证过程中。PKI
and Hash
, and is provided in the form of attaching the signature
signed by the CA to the hashed data (including extensions) to the certificate.PKI
和Hash
实现,并以 CA 签署的signature
附加到证书的散列数据(包括扩展)的形式提供。extensions
are modified, the signature
in the certificate must be modified, which means that a new certificate must be issued .extensions
,则必须修改证书中的signature
,这意味着必须颁发新的证书。 Come back to Fabric,回到面料,
reenroll
command is an act of newly issuing
enrolled user data based on the registered user
. reenroll
命令是基于registered user
newly issuing
注册用户数据的行为。updating
, a new certificate is issued through the reenroll
command to obtain a certificate that includes new Attrs
in the corresponding certificate. updating
后,通过reenroll
命令颁发新证书,获取对应证书中包含new Attrs
的证书。 The following example code has been tested and works.以下示例代码已经过测试并且可以工作。 See this.
看到这个。
// registerUser, enrollUser, updateUser, reEnrollUser
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const { Wallets } = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const fs = require('fs');
const path = require('path');
async function main() {
try {
// 0. given, already enrolled 'admin'
const ccpPath = path.resolve(__dirname, '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
const provider = wallet.getProviderRegistry().getProvider('X.509');
// 1. register testUser
const adminIdentity = await wallet.get('admin');
const appUser = 'testUser';
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
const secret = await ca.register({
affiliation: 'org1.department2',
attrs: [{name: 'userType', value: 'userType', ecert: true}],
enrollmentID: appUser,
role: 'client'
}, adminUser);
// 2. enroll testUser
const enrollment = await ca.enroll({
enrollmentID: appUser,
enrollmentSecret: secret
});
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put(appUser, x509Identity);
// 3. update testUser's Identity in Fabric-CA
const appUserIdentity = await wallet.get(appUser);
const newAppUser = await provider.getUserContext(appUserIdentity, appUser);
const identityService = ca.newIdentityService();
var theIdentityRequest = { enrollmentID: appUser, affiliation: 'org1.department1', attrs: [ {name: 'userType', value: 'Student', ecert: true} ] };
let response = await identityService.update(appUser, theIdentityRequest, adminUser);
console.log("userIdenity attributes: ", response.result.attrs);
// 4. reenroll testUser
const newEnrollment = await ca.reenroll(newAppUser);
const newX509Identity = {
credentials: {
certificate: newEnrollment.certificate,
privateKey: newEnrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put(`new_${appUser}`, newX509Identity);
} catch (error) {
console.error(`Failed to register user "appUser": ${error}`);
process.exit(1);
}
}
ls wallet
testUser.id new_testUser.id
The result of docode the issued certificate ( hf.Affiliation
and userType
are updated) docode 颁发证书的结果(更新
hf.Affiliation
和userType
)
// attrs in 'enroll' Certificate's extensions
{"attrs": "hf.Affiliation":"org1.department2","hf.EnrollmentID":"testUser","hf.Type":"client","userType":"userType"}}
// attrs in 'reenroll' Certificate's extensions
{"attrs":{"hf.Affiliation":"org1.department1","hf.EnrollmentID":"testUser","hf.Type":"client","userType":"Student"}}
[PS] Looking at the Version
indicated in the client's identity, it seems that there may be a way to upgrade the existing one, but I have not checked or tried it. [PS] 看客户身份标明的
Version
,好像有办法升级现有的,但我没有检查或尝试过。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.