Fabric CA证书管理教程

Stella981
• 阅读 1170

Fabric-CA是Hyperledger Fabric自带的证书管理工具,对于开发和测试非常方便。在这个教程中我们将探索Fabric-CA的使用方法并利用它完成用户的注册/Register和登记/Enrollment。

Hyperledger Fabric是一个许可制的区块链平台,在访问Fabric网络之前必须先进行身份识别并获得访问许可。Fabric网络中的身份是使用数字证书实现的,因此需要CA来处理证书的管理。

虽然Hyperledger Fabric允许使用第三方CA软件来管理用户证书,但出于方便考虑也自带了一个Fabric CA工具可以作为Fabric网络中的CA。由于Fabric自带的应用实例都是使用Fabric CA,因此我们在这个教程中将探索Fabric CA,特别是它在用户注册登记中的应用。

在这片文章中,我们使用部署在First网络上的Fabcar应用,这个实例应用包含了链码和客户端应用,其中的enrolAdmin.js和registerUser.js实现了基于Fabric CA的注册登记。

为了让整个过程展示的更清晰,我们调整了代码。同时我们也会查看Fabric CA的数据库,以便更好的理解在登记和注册时Fabric CA的运行机制。

相关教程推荐:

1、安装

我们需要一个Fabric节点来运行Fabric CA的演示,它应当包含Hyperledger Fabric相关的所有软件。如果你还没有Fabric节点,可以参考这篇文章创建一个。

一旦准备好了Fabric节点,可以运行如下命令启动Fabcar演示:

cd fabric-samples/fabcar
./startFabric.sh

这个脚本会启动First网络,以及每个机构的CA。让我们先重点关注Org1的Fabric-CA。

我们使用Fabcar应用中的JavaScript代码,特别是enrollAdmin.js和registerUser.js,因为这两部分代码都是用SDK来访问Fabric CA和Fabric网络。

这就是First网络以及客户端应用与Fabric网络交互的示意。让我们再次关注ca_peerOrg1以及进行登记注册的代码。

Fabric CA证书管理教程

2、Fabric CA注册登记代码

访问Fabric CA涉及到两个流程。登记(enrollment)指的是用户从指定CA请求并获取数字证书,注册(registration)通常由注册员完成,他负责告诉CA签发数字证书。

给用户签发数字证书有几种不同的方式。Fabcar脚本所采用的流程类似下面这样:

  1. 在Fabric CA中登记管理员,然后管理员收到签名私钥和证书,这些资料存放在 wallet/admin目录下
  2. 管理员在Fabric CA中注册user1,CA返回一个密文
  3. CA返回的密文用于在Fabric CA中登记user1,登记后得到user1的签名私钥和证书。这些资料存放在wallet/user1目录下,将被用于后续执行链码交互(查询、交易)。

enrollAdmin.js执行步骤1,registerUser.js执行步骤2和3:

Fabric CA证书管理教程

3、修改Fabric CA示例代码

我们没有修改enrollAdmin.js,它只是简单地使用默认地管理员信息(admin:adminpw),这些信息预置在fabric-samples/first-network/目录下的docker-compose-ca.yaml。结果就是admin的签名私钥和证书,保存在wallet/admin目录。

regsiterUser.js被拆分为两个文件:regUser.js和enrollUser.js,这么做的原因在于:

  • 我们可以观察到Fabric CA用户注册和登记的差异之处。
  • 我们可以看到这两个步骤实际上是由不同的角色执行的:注册步骤 是由注册员(admin)操作,而登记步骤则是用户自己使用得到的密文 来完成,这很重要,因为只有用户自己才可以知道密钥,管理员也不应当知道。
  • 我们可以把代码中的硬编码部分抽出来作为参数,这可以让代码适应Fabric CA的其他应用场景。

下面是重写代码后的示意:

Fabric CA证书管理教程

4、Fabric CA用户注册:regUser.js

regUser.js需要一个参数:登记ID,返回结果是一个密文,稍后该密文将用于用户登记。注意regUser.js的执行需要Fabric CA中存在admin钱包。

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();

5、Fabric CA登记用户:enrollUser.js

enrollUser.js需要两个参数,登记ID和注册时得到的密文,返回的结果是在wallet目录中创建的钱包。注意enrollUser.js的运行不需要Fabric CA中admin钱包的存在。该文件应当由用户自己执行。

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();

6、演示

现在我们看一下如何使用这三个脚本来为Fabcar应用在Fabric CA中注册登记user1用户。

第一步,运行fabcar/startFabric.sh

在运行前确保Fabric CA的钱包目录是空的。

cd fabric-samples/fabcar
./startFabric.shcd javascript
rm -rf wallet

结果如下:

Fabric CA证书管理教程

第二步,安装依赖模块。

npm install

第三步,为org1的Fabric CA安装sqlite3

因为我们要查看Fabric 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

现在已经进入了sqlite3的命令行:

sqlite> .tables

结果如下:

Fabric CA证书管理教程

我们的兴趣在于Fabric CA的users表和certificates表,用SQL语句查看其内容:

sqlite> select * from users;
sqlite> select * from certificates;

结果如下:

Fabric CA证书管理教程

我们看到用户admin已经在数据库里。这是Fabric CA启动时生成的,这个admin几乎有所有的角色,但目前还没有生成证书。

现在我们可以开始第一个登记了:登记admin。

第四步,在Fabric CA中登记admin

首先登记admin来获得其签名私钥和证书,结果存放在wallet/admin:

node enrollAdmin.js

结果:

Fabric CA证书管理教程

现在再看一下users表:

Fabric CA证书管理教程

可以看到admin的某个字段从0变成了1,这是其状态字段,表示已经签发了证书。

Fabric CA证书管理教程

如果我们快速将其与Fabric CA钱包目录wallet/admin中的文件对比,就会看到admin的真实证书:

Fabric CA证书管理教程

现在在Fabric CA中注册user1:

node regUser.js user1

结果如下:

Fabric CA证书管理教程

我们现在收到密文MDfRiAUccsna,在用户登记时需要这个密文。在Fabric CA的钱包目录,我们还没有看到user1的钱包。

这时查看Fabric CA数据库就可以清晰地看到发生的事情。我们看到users1被添加到users表中,但是其证书还未签发。user1的属性与regUser.js的信息一致。另外,user1的状态是0,表示其证书还未签发。

Fabric CA证书管理教程

第五步,在Fabric CA中登记user1,获取私钥和证书

运行enrollUser.js来登记user1:

node enrollUser.js user1 MDfRiAUccsna

结果如下:

Fabric CA证书管理教程

我们看到user1现在出现在Fabri CA的钱包里了。我们也看到在Fabric CA数据库中user1的证书已创建:

Fabric CA证书管理教程

状态从0迁移到1,表示证书已签发:

Fabric CA证书管理教程

第六步,用user1运行查询脚本,检查是否有权限

node query.js

结果如下:

Fabric CA证书管理教程


原文链接:Faric CA教程 - 汇智网

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Hyperledger Explorer官方安装文档中文版
HyperledgerExplorer是一个简单易用的开源工具,可以用于监视区块链网络中的活动。HyperledgerExplorer支持Fabric、Iroha等多种区块链,可以运行在MocOS和Ubuntu下。HyperledgerFabric区块链开发教程:Fabric区块链Node.js开发详解(https://
Stella981 Stella981
3年前
Hyperledger Caliper
在这个教程中,我们将学习如何使用HyperledgerCaliper对包含多个排序节点的Fabric网络进行基准测试,我们使用DockerSwarm作为容器编排工具。HyperledgerFabric区块链开发教程:Fabric区块链Node.js开发详解(https://www.oschina.net/action/G
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这