探索Fabric-CA的登记和注册

总览

Hyperledger Fabric是一个许可的区块链平台。必须先识别并获得许可,然后才能与光纤网络交互。身份是通过数字证书实现的,因此需要证书颁发机构(CA)来处理证书管理。

虽然Hyperledger Fabric允许使用Enterprise世界中可能需要的第三方CA,但它还附带了方便的Fabric-CA,可作为Fabric网络的CA。由于Fabric示例中的大多数应用示例都使用Fabric-CA(使用Basic Network和First Network),因此我们将研究Fabric-CA,尤其是其在用户注册和注册中的作用。

在本文中,我们使用部署在First Network上的Fabcar应用程序。此示例应用程序包含使用软件开发套件(SDK)的链码和客户端应用程序。特别是两个代码enrollAdmin.jsregisterUser.js已在Fabric-CA上实现了注册和注册。

为了使过程更容易证明,我对代码进行了重新整理,以使事情更清楚。同时,我们将查看Fabric-CA数据库,以更好地了解在注册和用户注册过程中Fabric-CA方面发生的情况。

设定

我们需要一个Fabric节点来进行演示。它具有所有必备软件以及与Hyperledger Fabric相关的软件。如果还没有这样的结构节点,可以参考本文创建一个。

[##

设置Hyperledger Fabric主机并创建机器映像

使用机器映像(例如AMI)来加快Hyperledger Fabric主机的准备,以进行测试和练习

一旦有了该节点,就可以运行fabric-samples/fabcar/startFabric.sh脚本以启动Fabcar。

cd fabric-samples/fabcar
./startFabric.sh

该脚本建立了第一个网络,并为每个组织建立了CA。我还有另一篇文章介绍Fabcar的细节。在这项工作中,我们的重点是针对Org1的Fabric-CA。

我们正在使用Fabcar应用程序中提供的Javascript代码。特别是,我们研究了enrollAdmin.jsregisterUser.js。因为两者都使用SDK与Fabric-CA和Fabric网络进行交互。

这是第一网络的外观,以及给定的客户端应用程序代码与光纤网​​络的交互方式。再次,我们将重点关注ca_peerOrg1以及本文中用于注册和注册的两个代码(enrollAdmin.jsregisterUser.js)。

Fabcar部署在First Network中,客户端应用程序使用SDK访问Fabric网络。

登记和注册代码

报名和注册

这是我们与Fabric-CA交互的两个过程。注册是用户请求并从给定CA获得数字证书的过程。注册通常由注册服务商完成,告诉注册管理机构颁发数字证书。

有多种方法可以向用户颁发数字证书。为了我们的利益并基于Fabcar脚本,过程如下所示

  1. 一个管理员(登记处)被登记到CA. 随后,管理员收到关于该签名密钥和证书管理。它们存储在wallet / admin目录中。
  2. 然后,管理员使用适当的信息将user1注册到CA中。CA返回一个秘密
  3. 然后,使用此机密将user1注册到CA。结果是user1的签名密钥和证书。它们存储在wallet / user1目录中,以后将用于执行链码交互(查询和调用)。

脚本enrollAdmin.js执行步骤1,而registerUser.js执行步骤2和3。

fabcar应用程序中提供的代码

重做代码

enrollAdmin.js保持不变。它仅使用默认的引导程序管理员(admin:adminpw),该默认值已在docker-compose-ca.yamlinside中预设fabric-samples/first-network/。结果是该管理员(注册商)的签名密钥和证书保存在wallet/admin目录中。

为了更好地说明,registerUser.js分为两个:regUser.jsenrollUser.js。背后的原因

  • 我们可以观察到用户注册和注册之间的区别。
  • 我们可以证明实际上这两个步骤应该由不同的一方完成:注册由注册服务商(admin)完成,而用户的注册由用户使用给出的机密完成。这很重要,因为只有除用户以外的任何人都不能接收签名密钥,即使注册服务商不知道该签名也应保密。
  • 我们可以取出代码中的硬编码部分(例如user1),并将其作为参数。这使代码在其他情况下更易于使用。

这是重写代码后的样子。

重写代码以更清晰地显示三个步骤

注册用户:regUser.js

regUser.js需要一个参数,即注册ID。结果是一个秘密,稍后将用于用户注册。请注意,*** regUser.js***需要存在管理员钱包。

node regUser.js <enrollmentID>

经过适当的修改,代码大部分是从原始的registerUser.js复制而来。

/*
 * SPDX-License-Identifier: Apache-2.0
 */

'use strict';

const { FileSystemWallet, Gateway, X509WalletMixin } = require('fabric-network');
const path = require('path');

const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json');

async function main() {
    try {

        // Create a new file system based wallet for managing identities.
        const walletPath = path.join(process.cwd(), 'wallet');
        const wallet = new FileSystemWallet(walletPath);
        console.log(`Wallet path: ${walletPath}`);

    const user = process.argv[2];

        // Check to see if we've already enrolled the user.
        const userExists = await wallet.exists(user);
        if (userExists) {
            console.log('An identity for the user ' + user + ' already exists in the wallet');
            return;
        }

        // Check to see if we've already enrolled the admin user.
        const adminExists = await wallet.exists('admin');
        if (!adminExists) {
            console.log('An identity for the admin user "admin" does not exist in the wallet');
            console.log('Run the enrollAdmin.js application before retrying');
            return;
        }

        // Create a new gateway for connecting to our peer node.
        const gateway = new Gateway();
        await gateway.connect(ccpPath, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: true } });

        // Get the CA client object from the gateway for interacting with the CA.
        const ca = gateway.getClient().getCertificateAuthority();
        const adminIdentity = gateway.getCurrentIdentity();

        // Register the user, enroll the user, and import the new identity into the wallet.
        const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: user, role: 'client' }, adminIdentity);
        console.log('Successfully registered user ' + user + ' and the secret is ' + secret );

    } catch (error) {
        console.error(`Failed to register user ${user}: ${error}`);
        process.exit(1);
    }
}

main();

注册用户:enrollUser.js

enrollUser.js需要两个参数,即注册ID和注册时获得的机密。结果是在wallet目录中的指定目录中创建了一个钱包。请注意,*** enrollUser.js***不需要管理钱包。它应该由用户自己执行。

node enrollUser.js <enrollmentID> <secret>

该代码引用了经过适当修改的原始enrollAdmin.js

/*
 * SPDX-License-Identifier: Apache-2.0
 */

'use strict';

const FabricCAServices = require('fabric-ca-client');
const { FileSystemWallet, X509WalletMixin } = require('fabric-network');
const fs = require('fs');
const path = require('path');

const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json');
const ccpJSON = fs.readFileSync(ccpPath, 'utf8');
const ccp = JSON.parse(ccpJSON);

async function main() {
    try {

        // Create a new CA client for interacting with the CA.
        const caInfo = ccp.certificateAuthorities['ca.org1.example.com'];
        const caTLSCACerts = caInfo.tlsCACerts.pem;
        const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);

        // Create a new file system based wallet for managing identities.
        const walletPath = path.join(process.cwd(), 'wallet');
        const wallet = new FileSystemWallet(walletPath);
        console.log(`Wallet path: ${walletPath}`);

    const user = process.argv[2];
    const secret = process.argv[3];

        // Check to see if we've already enrolled the admin user.
        const userExists = await wallet.exists(user);
        if (userExists) {
            console.log('An identity for this user already exists in the wallet');
            return;
        }

        // Enroll the admin user, and import the new identity into the wallet.
        const enrollment = await ca.enroll({ enrollmentID: user, enrollmentSecret: secret });
        const identity = X509WalletMixin.createIdentity('Org1MSP', enrollment.certificate, enrollment.key.toBytes());
        await wallet.import(user, identity);
        console.log(`Successfully enrolled user ${user} and imported it into the wallet`);

    } catch (error) {
        console.error(`Failed to enroll admin user "admin": ${error}`);
        process.exit(1);
    }
}

main();

示范

我们将展示如何运行这三个脚本来为Fabcar应用程序注册和注册user1

第1步:运行fabcar/startFabric.sh并确保钱包为空。

cd fabric-samples/fabcar
./startFabric.sh
cd javascript
rm -rf wallet
删除**钱包**目录中的所有内容

步骤2:安装所需的模块

npm install

步骤3:在org1的CA中安装sqlite3

当我们要检查CA中的数据库时,请安装sqlite3以执行检查。

打开另一个终端。

docker exec -it ca_peerOrg1 bash

ca_peerOrg1中安装sqlite3

apt-get update
apt-get install sqlite3

Fabric-CA数据库保存在中/etc/hyperledger/fabric-ca-server/fabric-ca-server.db。现在我们可以检查数据库了。

cd /etc/hyperledger/fabric-ca-server
sqlite3 fabric-ca-server.db

现在我们在sqlite的命令行外壳中。

sqlite> .tables
image.png

在这些表中,我们对users表certificates表感兴趣。要查看这些表中的内容。

sqlite> select * from users;
sqlite> select * from certificates;
image.png

我们看到数据库中已经有一个用户admin。这是在启动CA时完成的(请使用-b admin:adminpw参阅docker-compose文件中的命令)。而且这个引导管理员几乎设置了所有角色。尚未生成证书(尚未完成注册)。

现在,我们准备执行第一次注册:使用此admin的registrar的注册。

步骤4:注册管理员(注册商)

我们首先注册管理员,以获取存储在中的管理员的签名密钥和证书wallet/admin

node enrollAdmin.js
image.png

如果现在再次检查CA中的users表

image.png

我们可以看到admin中的字段从0更改为1。这是state,表示已颁发证书。现在我们可以看到已颁发证书。

image.png

如果快速将其与存储的内容进行比较wallet/admin,我们将看到这是admin的实际证书。

image.png

步骤5:将user1注册到CA

现在,我们运行regUser.jsuser1注册到CA中。

node regUser.js user1
image.png

现在,我们收到了秘密MDfRiAUccsna。在下一步的用户注册中需要这样做。我们还没有找到user1的新钱包。

如果我们检查CA数据库,将会更清楚地了解发生了什么。我们看到user1已添加到users表,而user1尚未创建新证书(尚未注册)。user1的属性与regUser.js中编码的内容匹配。同样,user1的状态为0 ,这意味着尚未颁发证书。

image.png

步骤5:注册user1并获取签名密钥和证书

运行enrollUser.js以使用密码将user1注册到CA。

node enrollUser.js user1 MDfRiAUccsna
image.png

我们看到user1现在在钱包里。我们还在CA数据库中看到为user1创建的新证书。

image.png

颁发证书后(注册了user1之后)状态更改为1 。

image.png

步骤6:最后,我们可以使用user1运行Fabcar脚本(query.js),并查看user1是否可以执行查询。请注意,在query.js中, user1是硬编码的。

node query.js
image.png

用户user1可以按预期执行链码查询。

奖励:模拟丢失user1钱包

让我们删除user1钱包以模拟损失。

rm -r wallet/user1
image.png

我们首先将尝试使用相同的秘密再次注册user1

node enrollUser.js user1 MDfRiAUccsna
image.png

注册失败。如果我们查看CA的日志,我们就会知道为什么会这样。

docker logs ca_peerOrg1
image.png

现在,我们在Fabric-CA数据库上做一个技巧。首先,在证书表中删除user1,然后在users表中将user1的状态从1 更改为0 。

sqlite> delete from certificates where id='user1';
sqlite> update users set state=0 where id='user1';
image.png

完成此技巧后,我们可以使用相同的密码再次注册user1

image.png

此新的user1钱包可再次用于链码查询。

注意:这不是正式的方式,因为我们应该避免直接修改数据库。但是,如果需要的话,这可以是一种方法。

步骤7:清理

退出CA容器

sqlite> .exit
# exit

清理Fabcar和First-Network

cd fabric-samples/first-network
./byfn.sh down
docker rm $(docker ps -aq)
docker rmi $(docker images dev-* -q)

摘要

本文重点介绍Fabric-CA,说明如何使用SDK进行注册和注册。重新编写代码后,我们将逐步了解该过程。通过研究存储在Fabric-CA数据库中的信息,我们了解了Fabric-CA如何处理用户注册和注册。我们还执行了一个小技巧,以防钱包丢失时为用户重新签发签名密钥和证书。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容