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以及進行登記注冊的代碼。

2、Fabric CA注冊登記代碼
通路Fabric CA涉及到兩個流程。登記(enrollment)指的是使用者從指定CA請求并擷取數字證書,注冊(registration)通常由注冊員完成,他負責告訴CA簽發數字證書。
給使用者簽發數字證書有幾種不同的方式。Fabcar腳本所采用的流程類似下面這樣:
- 在Fabric CA中登記管理者,然後管理者收到簽名私鑰和證書,這些資料存放在 wallet/admin目錄下
- 管理者在Fabric CA中注冊user1,CA傳回一個密文
- CA傳回的密文用于在Fabric CA中登記user1,登記後得到user1的簽名私鑰和證書。這些資料存放在wallet/user1目錄下,将被用于後續執行鍊碼互動(查詢、交易)。
enrollAdmin.js執行步驟1,registerUser.js執行步驟2和3:
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的其他應用場景。
下面是重寫代碼後的示意:
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
結果如下:
第二步,安裝依賴子產品。
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的users表和certificates表,用SQL語句檢視其内容:
sqlite> select * from users;
sqlite> select * from certificates;
我們看到使用者admin已經在資料庫裡。這是Fabric CA啟動時生成的,這個admin幾乎有所有的角色,但目前還沒有生成證書。
現在我們可以開始第一個登記了:登記admin。
第四步,在Fabric CA中登記admin
首先登記admin來獲得其簽名私鑰和證書,結果存放在wallet/admin:
node enrollAdmin.js
結果:
現在再看一下users表:
可以看到admin的某個字段從0變成了1,這是其狀态字段,表示已經簽發了證書。
如果我們快速将其與Fabric CA錢包目錄wallet/admin中的檔案對比,就會看到admin的真實證書:
現在在Fabric CA中注冊user1:
node regUser.js user1
我們現在收到密文MDfRiAUccsna,在使用者登記時需要這個密文。在Fabric CA的錢包目錄,我們還沒有看到user1的錢包。
這時檢視Fabric CA資料庫就可以清晰地看到發生的事情。我們看到users1被添加到users表中,但是其證書還未簽發。user1的屬性與regUser.js的資訊一緻。另外,user1的狀态是0,表示其證書還未簽發。
第五步,在Fabric CA中登記user1,擷取私鑰和證書
運作enrollUser.js來登記user1:
node enrollUser.js user1 MDfRiAUccsna
我們看到user1現在出現在Fabri CA的錢包裡了。我們也看到在Fabric CA資料庫中user1的證書已建立:
狀态從0遷移到1,表示證書已簽發:
第六步,用user1運作查詢腳本,檢查是否有權限
node query.js
原文連結:
Faric CA教程 - 彙智網