近日,因为工作需要,对 fabric 数据防篡改机制进行了研究,这里提供了一种验证链上数据防篡改的场景以供参考
基本思路:
进入某个peer节点修改本地的 Couch DB 数据,修改完后再调用链码发送一笔交易,发现执行结果是该 peer 节点的数据重新变为修改前的数据,说明篡改数据失败,系统具有放篡改能力。
具体操作如下,为了简化操作,直接借助官方使用 couchdb 样例,链码为 mymarble
先进入 firstnetwork 目录,执行以下命令起一个使用 couchdb 的byfn网络
./byfn.sh up -c mychannel -s couchdb
然后进入客户端
docker exec -it cli bash
export CHANNEL_NAME=mychannel
执行以下命令
# peer0.org1 安装链码
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
peer chaincode install -n mymarble -v 1.0.0 -p github.com/chaincode/marbles02/go
# peer1.org1 安装链码
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer1.org1.example.com:8051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
peer chaincode install -n mymarble -v 1.0.0 -p github.com/chaincode/marbles02/go
# peer0.org2 安装链码
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:9051
CORE_PEER_LOCALMSPID="Org2MSP"
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 mymarble -v 1.0.0 -p github.com/chaincode/marbles02/go
# peer1.org2 安装链码
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer1.org2.example.com:10051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
peer chaincode install -n mymarble -v 1.0.0 -p github.com/chaincode/marbles02/go
# 实例化链链码
peer chaincode instantiate -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mymarble -v 1.0.0 -c '{"Args":["init"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mymarble --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
此时打开浏览器 http://localhost:5984/_utils/
进入 peer0.org1 (对外暴露端口为5984)的 couchdb,查看 marble1 变量:
{
"_id": "marble1",
"_rev": "1-1d12a3e8f79f5c0e40cc73c43701a6ba",
"color": "blue",
"docType": "marble",
"name": "marble1",
"owner": "tom",
"size": 35,
"~version": "\u0000CgMBBgA="
}
我们可以看到在 couchdb 中保存了 marble1 的各个字段的属性。
然后手动将其中的 35 改为25,并保存(试图通过修改peer本地的couchdb中的数据实现篡改数据的操作)。
此时在终端调用以下链码,即将 marble1 给 jerry
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mymarble --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["transferMarble","marble1","jerry"]}'
注意此时指定的背书节点为 peer0.org1 和 peer0.org2
发现调用失败,返回背书不满足
这主要是因为 peer0.org1 的 couchdb 的数据已经改变,和 peer0.org1 的数据不同,导致模拟执行失败
此时,将其中一个背书节点背书节点 peer0.org1 替换成 peer1.org1,此时再次调用链码
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mymarble --peerAddresses peer1.org1.example.com:8051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["transferMarble","marble1","jerry"]}'
链码调用成功
再次进入peer0.org1的couchdb,对外暴露端口为5984
发现此时 marble1 的owner 已经变为jerry,并且仍然是35
{
"_id": "marble1",
"_rev": "3-c2280ec7b75f7f5536b490acf10515a0",
"color": "blue",
"docType": "marble",
"name": "marble1",
"owner": "jerry",
"size": 35,
"~version": "\u0000CgMBBwA="
}
说明试图篡改数据的操作失败,系统具有防篡改能力