2018年12月24日月曜日

Hyperledger Fabric 暗号化機能を使ってみる

チェーンコードがワールドステートにKVS情報を登録する際、デフォルトでは平文で登録される。
Fabricが提供するチェーンコード関数(shim)において、暗号化・復号化関数を使ってKVS情報を暗号化・復号化してみる。

➀最初に、必要なパッケージをgovendorでインストールする。

# cd /opt/src/github.com/hyperledger/fabric-samples/chaincode/enccc_example
# go get github.com/kardianos/govendor
# govendor init
# govendor add +external
#  ls -l vendor/
合計 44
drwxr-xr-x. 22 root root  4096 12月 24 16:06 github.com
drwxr-xr-x.  5 root root    47 12月 24 16:06 go.uber.org
drwxr-xr-x.  3 root root    15 12月 24 16:06 golang.org
drwxr-xr-x.  4 root root    34 12月 24 16:06 google.golang.org
drwxr-xr-x.  3 root root    21 12月 24 16:06 gopkg.in
-rw-r--r--.  1 root root 39682 12月 24 16:06 vendor.json

②チェーンコードをインストールする。ここでは、Fabric付属のサンプルソースを利用する。

#peer chaincode install -n bushido -v 1.0 -l golang -p github.com/chaincode/enccc_example
#
# peer chaincode instantiate -o orderer.example.com:7050 -C bushido -n bushido -l golang -v 1.0 -c '{"Args":[]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')" --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem

③共通鍵を作成する。サポートしてる暗号アルゴリズムはAES 256bit。

# ENCKEY=`openssl rand 32 -base64` && DECKEY=$ENCKEY
#  echo $ENCKEY
hVhA7CxStLauw9/aLBnieoC9dM237fQHPvU8ibS1MyY=
#
# IV=`openssl rand 16 -base64`

➃データを暗号化してワールドステートに登録する。
transientオプションに暗号化鍵を指定する。暗号化鍵はワールドステートには登録されない。

# peer chaincode invoke -n bushido -C bushido -c '{"Args":["ENCRYPT","key2","value2"]}' --transient "{\"ENCKEY\":\"$ENCKEY\",\"IV\":\"$IV\"}" --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem

⑤復号化してワールドステートから値を取得する。
transientオプションに復号化鍵(=暗号化鍵)を指定する。

#  peer chaincode query -n bushido -C bushido -c '{"Args":["DECRYPT","key2"]}' --transient "{\"DECKEY\":\"$DECKEY\"}"
value2

ためしに、復号化鍵(DECKEY)に誤った値を指定した場合、以下のエラーが発生する。

・hogeとした場合
#  peer chaincode query -n bushido -C bushido -c '{"Args":["DECRYPT","key2"]}' --transient "{\"DECKEY\":\"hoge\"}"
failed: Failed importing key with opts [&{true}]: Invalid Key Length [3]. Must be 32 bytes"

・32バイトの適用な値を指定した場合
# peer chaincode query -n bushido -C bushido -c '{"Args":["DECRYPT","key2"]}' --transient "{\"DECKEY\":\"111222xStLauw9/aLBnieoC9dM237fQHPvU8ibS1MyY=\"}"

Error: endorsement failure during query. response: status:500 message:"getStateAndDecrypt failed, err Invalid pkcs7 padding (unpadding > aes.BlockSize || unpadding == 0)\nFailed decrypting with opts [&{[] <nil>}]\ngithub.com/chaincode/enccc_example/vendor/github.com/hyperledger/fabric/bccsp/sw.(*CSP).Decrypt\n\t/chaincode/input/src/github.com/chaincode/enccc_example/vendor/github.com/hyperledger/fabric/bccsp/sw/impl.go:303\ngithub.com/chaincode/enccc_example/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/entities.(*BCCSPEncrypterEntity).Decrypt\n\t/chaincode/input/src/github.com/chaincode/enccc_example/vendor/github.com/hyperledger/fabric/core/chaincode/shim/ext/entities/entities.go:246\nmain.getStateAndDecrypt\n\t/chaincode/input/src/github.com/chaincode/enccc_example/utils.go:40\nmain.(*EncCC).Decrypter\n\t/chaincode/input/src/github.com/chaincode/enccc_example/enccc_example.go:76\nmain.(*EncCC).Invoke\n\t/chaincode/input/src/github.com/chaincode/enccc_example/enccc_example.go:182\ngithub.com/chaincode/enccc_example/vendor/github.com/hyperledger/fabric/core/chaincode/shim.(*Handler).handleTransaction.func1\n\t/chaincode/input/src/github.com/chaincode/enccc_example/vendor/github.com/hyperledger/fabric/core/chaincode/shim/handler.go:273\nruntime.goexit\n\t/opt/go/src/runtime/asm_amd64.s:1333"



2018年12月9日日曜日

Fabric Javaチェーンコードをつかってみる

Hyperledger Fabric 1.3から、Java版チェーンコードが正式サポートされた。
Java版チェーンコードを使ってみる。

Javaチェーンコードを利用する際の前提条件は以下のとおり。
・JDK 1.8がインストール済みであること。
・gradle 2.12以上がインストール済みであること。

➀各PeerにJavaチェーンコードをインストールする。
※Fabricでは、Javaチェーンコードのサンプルが提供されており、今回はそれを利用する。

# peer chaincode install -n bushido -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/
#
# CORE_PEER_ADDRESS="peer0.org2.example.com:7051"
# CORE_PEER_LOCALMSPID="Org2MSP"
# CORE_PEER_MSPCONFIGPATH="/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp"
# CORE_PEER_TLS_CERT_FILE="/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt"
# CORE_PEER_TLS_KEY_FILE="/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key"
# CORE_PEER_TLS_ROOTCERT_FILE="/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
# peer chaincode install -n bushido -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/

②チェーンコードのinstantiateを行う。

# peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt  -C bushido -n bushido -l java -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

③Javaチェーンコードのコンテナが作成されていることを確認する。

# docker ps | grep bushido
84bb5c2aa994        dev-peer0.org1.example.com-bushido-1.0-92aca216667084484fba82d74149bf26ec36672612d5608a67bb2b0694ade7d7   "/root/chaincode-jav…"   5 minutes ago       Up 5 minutes                                                           dev-peer0.org1.example.com-bushido-1.0

➃QUERYやINVOKEを行うことができることを確認する。
# peer chaincode query -C bushido -n bushido -c '{"Args":["query","a"]}'
100
# peer chaincode query -C bushido -n bushido -c '{"Args":["query","b"]}'
200

<補足>
Javaチェーンコードのログを閲覧すると、以下のようなログが出力される。

[root@localhost first-network]# docker logs -f --tail 30 dev-peer0.org1.example.com-bushido-1.0
Dec 09, 2018 3:43:12 AM org.hyperledger.fabric.shim.ChaincodeBase newChannelBuilder
INFO: Configuring channel connection to peer.
Dec 09, 2018 3:43:14 AM org.hyperledger.fabric.example.SimpleChaincode init
INFO: Init java simple chaincode
Dec 09, 2018 3:43:14 AM org.hyperledger.fabric.example.SimpleChaincode init
INFO: account a, value = 100; account b, value 200
Dec 09, 2018 3:45:52 AM org.hyperledger.fabric.example.SimpleChaincode invoke
INFO: Invoke java simple chaincode
Dec 09, 2018 3:45:52 AM org.hyperledger.fabric.example.SimpleChaincode query
INFO: Query Response:
Name: a, Amount: 100

Dec 09, 2018 3:45:57 AM org.hyperledger.fabric.example.SimpleChaincode invoke
INFO: Invoke java simple chaincode
Dec 09, 2018 3:45:57 AM org.hyperledger.fabric.example.SimpleChaincode query
INFO: Query Response:
Name: a, Amount: 100

Dec 09, 2018 3:46:03 AM org.hyperledger.fabric.example.SimpleChaincode invoke
INFO: Invoke java simple chaincode
Dec 09, 2018 3:46:03 AM org.hyperledger.fabric.example.SimpleChaincode query
INFO: Query Response:
Name: a, Amount: 100

Dec 09, 2018 3:46:52 AM org.hyperledger.fabric.example.SimpleChaincode invoke
INFO: Invoke java simple chaincode
Dec 09, 2018 3:46:52 AM org.hyperledger.fabric.example.SimpleChaincode query
INFO: Query Response:
Name: b, Amount: 200

Linux gradleインストール手順

CentOS上にgradleをインストールする。

➀以下のサイトからgradleのインストール媒体をダウンロードする。

https://gradle.org/next-steps/?version=4.10.3&format=bin

②gradle用のフォルダを作成する。

# mkdir /opt/gradle
# mv /tmp/gradle-4.10.3-bin.zip  /opt/gradle
# cd /opt/gradle

③インストール媒体を解凍する。

# unzip -d /opt/gradle gradle-4.10.3-bin.zip

➃ 解凍後、中身を確認する。

# ls -l /opt/gradle/gradle-4.10.3
合計 216
-rw-rw-r--. 1 root root  55261 11月 29 01:04 LICENSE
-rw-rw-r--. 1 root root    802 11月 29 01:04 NOTICE
drwxr-xr-x. 2 root root     38 12月  5 01:54 bin
-rw-rw-r--. 1 root root 151483 12月  5 01:53 getting-started.html
drwxrwxr-x. 2 root root     24 11月 29 01:04 init.d
drwxr-xr-x. 3 root root   4096 12月  5 01:54 lib
drwxrwxr-x. 2 root root    263 11月 29 01:04 media

⑤gradleのパスを通す。

# export PATH=$PATH:/opt/gradle/gradle-4.10.3/bin

⑥gradleのバージョンを確認する。

# gradle -v

Welcome to Gradle 4.10.3!

Here are the highlights of this release:
 - Incremental Java compilation by default
 - Periodic Gradle caches cleanup
 - Gradle Kotlin DSL 1.0-RC6
 - Nested included builds
 - SNAPSHOT plugin versions in the `plugins {}` block

For more details see https://docs.gradle.org/4.10.3/release-notes.html


------------------------------------------------------------
Gradle 4.10.3
------------------------------------------------------------

Build time:   2018-12-05 00:50:54 UTC
Revision:     e76905e3a1034e6f724566aeb985621347ff43bc

Kotlin DSL:   1.0-rc-6
Kotlin:       1.2.61
Groovy:       2.4.15
Ant:          Apache Ant(TM) version 1.9.11 compiled on March 23 2018
JVM:          1.8.0_191 (Oracle Corporation 25.191-b12)
OS:           Linux 3.10.0-862.el7.x86_64 amd64

Hyperledger Fabric バッチサイズ変更手順

FabricのOrdererがブロックを生成する際、デフォルト設定では、以下のタイミングでブロックが作られる。

  タイムアウト時間:2秒
      または
      トランザクション数:10個

ブロックチェーンコンソーシアムを構築した後、運用中にトランザクション数を変更する手順を説明する。

➀CONFIGブロックを取得する。

# docker exec -it cli bash
# peer channel fetch config config.bc -o orderer.example.com:7050 -c bushido --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt 

②CONFIGブロック(バイナリ)をJSON形式にデコードする。このとき、Envelopeメッセージ等は除外する。

# configtxlator proto_decode --input config.bc --type common.Block | jq .data.data[0].payload.data.config > config.json

③今回はトランザクション数を10→5に変更することにする。

# jq ".channel_group.groups.Orderer.values.BatchSize.value.max_message_count" "config.json"
10
# jq ".channel_group.groups.Orderer.values.BatchSize.value.max_message_count = 5"  "config.json" > "update_config.json"
jq ".channel_group.groups.Orderer.values.BatchSize.value.max_message_count" "update_config.json"
5

➃「config.json」と「update_config.json」の差分値をシミレーションする。

#configtxlator proto_encode --input config.json --type common.Config > config.bc
#configtxlator proto_encode --input update_config.json --type common.Config > update_config.bc

#configtxlator compute_update --channel_id bushido --original config.bc --updated update_config.bc --output update_config_2.bc

⑤シミレーション結果で生成された「update_config_2.bc」をJSON形式にデコードする。

#configtxlator proto_decode --input update_config_2.bc --type common.ConfigUpdate | jq . > update_config_2.json

⑥Envelopeメッセージをラッピングする。


#echo '{"payload":{"header":{"channel_header":{"channel_id":"bushido", "type":2}},"data":{"config_update":'$(cat update_config_2.json)'}}}' | jq . > update_config_2_envelope.json

⑦「update_config_2_envelope.json」をバイナリ形式にエンコードする。

#configtxlator proto_encode --input update_config_2_envelope.json --type common.Envelope --output update_config_2_envelope.bc

⑧「update_config_2_envelope.bc」に対して、PEERの署名を行う。
(Endorsing Policyを満たす分、署名を付与する必要あり)

# peer channel signconfigtx -f update_config_2_envelope.bc

⑨チャネルを更新する。

# peer channel update -f update_config_2_envelope.bc -c bushido -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt