应用示例
为了说明同态加密库的具体使用方法,提供一个应用示例代码和对应的链码示例代码。该应用的主要功能是实现用户间相互转账,同时使用同态加密库保护用户的转账交易信息。
该应用的使用包括三个步骤:注册用户(同时会初始化用户余额),用户间转账,查询用户余额。
应用使用命令行的方式进行业务操作,具体过程如下。
注意事项
在下载的sdk.yaml文件中查询orderer和peer的域名信息,将EIP+orderer域名和EIP+peer域名补充进“/etc/hosts”文件中。使用Fabric1.1版本时,peer域名中的EIP需要配置为公网IP,使用Fabric1.4版本时,peer域名中的EIP需要配置为私网IP,否则网络不通将会导致交易验证失败。
在“/etc/hosts”文件中增加orderer节点和peer节点的域名映射时,操作方法如下:
X.X.X.X orderer-e5ad7831affbe8e6e2e7984b098f92406930a688-0.orderer-e5ad7831affbe8e6e2e7984b098f92406930a688.default.svc.cluster.local X.X.X.X peer-d524b0817aaed85490368776cb88042a149a56b5-0.peer-d524b0817aaed85490368776cb88042a149a56b5.default.svc.cluster.local X.X.X.X peer-d524b0817aaed85490368776cb88042a149a56b5-1.peer-d524b0817aaed85490368776cb88042a149a56b5.default.svc.cluster.local
X.X.X.X为示例EIP,请替换为实际EIP。
注册
Usage: appdemo register [flags] Flags: -C, --channel string channel id (default "mychannel") -c, --config string configuration file path (default "./config_test.yaml") -I, --idcc string idendity chaincode name (default "IDChaincode") -i, --initbalance string init initbalance -o, --orgid string organization id (default "org1") -p, --protectpwd string protect pwd -T, --txcc string transaction chaincode name (default "TxChaincode") -u, --userid string user id ./appdemo register -u A -p test -i 100
部分参数不配置时使用的为默认值,见Flags中的描述。如果用户配置的与默认值不同,需要在参数中显示指定。
- 为用户生成一对同态公私钥
这里假设有个用户表示userid,用于区分用户,新用户注册的时候为这个用户生成一对公私钥,这里demo为每个用户将密钥对写到了本地的${userid}.data文件。
privKeyStr, pubKeyStr, err := pswapi_sdk.GenerateKey(propwd) check(err) fmt.Println("key is nil") userdata.PubKey = pubKeyStr userdata.PriKey = privKeyStr
- 注册公钥
使用fabric SDK的接口向IDChaincode 注册,参数为生成的公钥。
注册公钥是为了使大家的同态公钥共享,这里利用了区块链本身链码特性完成该功能。主要作用是在转账的时候,使用转账者的公钥加密交易信息,保护交易隐私,只有私钥持有者才可以解密交易内容。
res, err := sdk_client.Invoke(setup, "Register", [][]byte{[]byte(userdata.PubKey), []byte(senderAddr)}) if err != nil { fmt.Println("Fail to register user pk ", err.Error()) } else { addrByte := res[0].ProposalResponse.GetResponse().Payload fmt.Println("Register addr: ", string(addrByte)) }
- 注册初始余额
- 使用sdk.InitBalance来初始余额,进行加密生成初始化balanceinfo。
- 发送balanceinfo到交易Chaincode。
balanceInfo, err := pswapi_sdk.InitBalance(initbalance, userdata.PubKey) check(err) setup.ChainCodeID = txchaincode _, err = sdk_client.Invoke(setup, "init", [][]byte{[]byte(userdata.PubKey), []byte(balanceInfo)}) if err != nil { fmt.Println("Initbalance error for user: ", senderAddr, err.Error()) } else { fmt.Println("init balance successfully: ", senderAddr) } check(err)
交易
Usage: appdemo transaction [flags] Flags: -b, --AddrB string B' addr -t, --Tx string Transaction Num -C, --channel string channel id (default "mychannel") -c, --config string configuration file path (default "./config_test.yaml") -I, --idcc string idendity chaincode name (default "IDChaincode") -o, --orgid string organization id (default "org1") -p, --protectpwd string protect pwd -T, --txcc string transaction chaincode name (default "TxChaincode") -u, --userid string user id ./appdemo transaction -u A -p test -b a0760184f7ed24e0d86f5b2df40a973a9e1b5da9a1ae886532ac9cd634b59d59 -t 10 //说明:其中-b后的字符串为B的账户地址(B注册成功时回显的地址)。
查询
Usage: appdemo querybalance [flags] Flags: -C, --channel string channel id (default "mychannel") -c, --config string configuration file path (default "./config_test.yaml") -I, --idcc string idendity chaincode name (default "IDChaincode") -o, --orgid string organization id (default "org1") -p, --protectpwd string protect pwd -T, --txcc string transaction chaincode name (default "TxChaincode") -u, --userid string user id ./appdemo querybalance -p test -u A
查询代码:
- 调用sdk提供的InitBalance接口初始化余额。
- 调用fabirc sdk发送交易。
get balance setup.ChainCodeID = txchaincode transRec := sdk_client.TransRecord{} fmt.Println("query balance") resps, err := sdk_client.Query(setup, "QueryBalance", [][]byte{[]byte(addrA)}) if err != nil { fmt.Println("Fail to query balance :", err.Error()) return err } err = json.Unmarshal(resps[0].ProposalResponse.GetResponse().Payload, &transRec) if err != nil { fmt.Println("unmarshal query result error: ", err.Error()) return err }
decrypt balance curbalance, err := pswapi_sdk.Decrypt(transRec.Balance, userdata.PriKey, propwd) if err != nil { fmt.Println("sdk Decrypt error: ", err.Error()) return err } fmt.Println("current balance:" + curbalance.String())