From dfad2c17a42b79cc67df1cac853f7244865b8f0d Mon Sep 17 00:00:00 2001 From: Flamewind97 Date: Fri, 14 Apr 2023 12:08:45 +0200 Subject: [PATCH] able to save into single key --- ecc_go/chaincode/enclave_go/skvs_stub.go | 110 ++++++++++++ .../enclave_go/skvs_stub_Interface.go | 108 ++++++++++++ ecc_go/chaincode/singleKVS.go | 163 +++++++++++++++--- samples/chaincode/secret-keeper-go/main.go | 7 +- 4 files changed, 359 insertions(+), 29 deletions(-) create mode 100644 ecc_go/chaincode/enclave_go/skvs_stub.go create mode 100644 ecc_go/chaincode/enclave_go/skvs_stub_Interface.go diff --git a/ecc_go/chaincode/enclave_go/skvs_stub.go b/ecc_go/chaincode/enclave_go/skvs_stub.go new file mode 100644 index 000000000..3d68f116d --- /dev/null +++ b/ecc_go/chaincode/enclave_go/skvs_stub.go @@ -0,0 +1,110 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package enclave_go + +import ( + "crypto/sha256" + + "github.com/hyperledger/fabric-chaincode-go/shim" + "github.com/hyperledger/fabric-private-chaincode/internal/protos" + "github.com/hyperledger/fabric/protoutil" + "github.com/pkg/errors" + "google.golang.org/protobuf/proto" +) + +type skvsStub struct { + *EnclaveStub +} + +func NewSkvsStub(cc shim.Chaincode) *skvsStub { + enclaveStub := NewEnclaveStub(cc) + return &skvsStub{enclaveStub} +} + +func (e *skvsStub) ChaincodeInvoke(stub shim.ChaincodeStubInterface, chaincodeRequestMessageBytes []byte) ([]byte, error) { + logger.Error("==== SKVS ChaincodeInvoke ====") + + signedProposal, err := stub.GetSignedProposal() + if err != nil { + shim.Error(err.Error()) + } + + if err := e.verifySignedProposal(stub, chaincodeRequestMessageBytes); err != nil { + return nil, errors.Wrap(err, "signed proposal verification failed") + } + + // unmarshal chaincodeRequest + chaincodeRequestMessage := &protos.ChaincodeRequestMessage{} + err = proto.Unmarshal(chaincodeRequestMessageBytes, chaincodeRequestMessage) + if err != nil { + return nil, err + } + + // get key transport message including the encryption keys for request and response + keyTransportMessage, err := e.extractKeyTransportMessage(chaincodeRequestMessage) + if err != nil { + return nil, errors.Wrap(err, "cannot extract keyTransportMessage") + } + + // decrypt request + cleartextChaincodeRequest, err := e.extractCleartextChaincodeRequest(chaincodeRequestMessage, keyTransportMessage) + if err != nil { + return nil, errors.Wrap(err, "cannot decrypt chaincode request") + } + + // create a new instance of a FPC RWSet that we pass to the stub and later return with the response + rwset := NewReadWriteSet() + + // Invoke chaincode + // we wrap the stub with our FpcStubInterface + // ** Implement our own FpcStubInterface + skvsStub := NewSkvsStubInterface(stub, cleartextChaincodeRequest.GetInput(), rwset, e.ccKeys) + ccResponse := e.ccRef.Invoke(skvsStub) + // ** + // fpcStub := NewFpcStubInterface(stub, cleartextChaincodeRequest.GetInput(), rwset, e.ccKeys) + // ccResponse := e.ccRef.Invoke(fpcStub) + + // marshal chaincode response + ccResponseBytes, err := protoutil.Marshal(&ccResponse) + if err != nil { + return nil, err + } + + //encrypt response + encryptedResponse, err := e.csp.EncryptMessage(keyTransportMessage.GetResponseEncryptionKey(), ccResponseBytes) + if err != nil { + return nil, err + } + + chaincodeRequestMessageHash := sha256.Sum256(chaincodeRequestMessageBytes) + + response := &protos.ChaincodeResponseMessage{ + EncryptedResponse: encryptedResponse, + FpcRwSet: rwset.ToFPCKVSet(), + EnclaveId: e.identity.GetEnclaveId(), + Proposal: signedProposal, + ChaincodeRequestMessageHash: chaincodeRequestMessageHash[:], + } + + responseBytes, err := proto.Marshal(response) + if err != nil { + return nil, err + } + + // create signature + sig, err := e.identity.Sign(responseBytes) + if err != nil { + return nil, err + } + + signedResponse := &protos.SignedChaincodeResponseMessage{ + ChaincodeResponseMessage: responseBytes, + Signature: sig, + } + + return proto.Marshal(signedResponse) +} diff --git a/ecc_go/chaincode/enclave_go/skvs_stub_Interface.go b/ecc_go/chaincode/enclave_go/skvs_stub_Interface.go new file mode 100644 index 000000000..49b80f42b --- /dev/null +++ b/ecc_go/chaincode/enclave_go/skvs_stub_Interface.go @@ -0,0 +1,108 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package enclave_go + +import ( + "encoding/hex" + "encoding/json" + + "github.com/hyperledger/fabric-chaincode-go/shim" + pb "github.com/hyperledger/fabric-protos-go/peer" +) + +var SingleKey = "SingleKey" + +type SkvsStubInterface struct { + *FpcStubInterface +} + +func NewSkvsStubInterface(stub shim.ChaincodeStubInterface, input *pb.ChaincodeInput, rwset *readWriteSet, sep StateEncryptionFunctions) *SkvsStubInterface { + fpcStub := NewFpcStubInterface(stub, input, rwset, sep) + return &SkvsStubInterface{fpcStub} +} + +func (s *SkvsStubInterface) GetState(key string) ([]byte, error) { + logger.Warningf("Calling Get State (Start), key = %s", key) + encValue, err := s.GetPublicState(SingleKey) + if err != nil { + return nil, err + } + + // in case the key does not exist, return early + if len(encValue) == 0 { + logger.Warningf("Calling Get State (End), data empty return.") + return nil, nil + } + + value, err := s.sep.DecryptState(encValue) + if err != nil { + return nil, err + } + + // Create an interface{} value to hold the unmarshalled data + var allData map[string]string + + // Unmarshal the JSON data into the interface{} value + err = json.Unmarshal(value, &allData) + if err != nil { + logger.Errorf("SKVS Json unmarshal error: %s", err) + return nil, err + } + logger.Warningf("Calling Get State (Mid), key = %s, decrypted done alldata = %s", key, allData) + + targetHex := allData[key] + targetBytes, err := hex.DecodeString(targetHex) + logger.Warningf("Calling Get State (End), Target: %s, TargetBytes: %x, err: %s", targetHex, targetBytes, err) + return targetBytes, err + // return s.sep.DecryptState(encValue) +} + +func (s *SkvsStubInterface) PutState(key string, value []byte) error { + logger.Warningf("Calling Put State (Start), key = %s, value = %x", key, value) + // grab all data from the state. + encAllValue, err := s.GetPublicState(SingleKey) + if err != nil { + return err + } + var allData map[string]string + + if len(encAllValue) == 0 { + // current world state is empty + allData = map[string]string{} + } else { + allValue, err := s.sep.DecryptState(encAllValue) + if err != nil { + return err + } + // Unmarshal the JSON data into the interface{} value + err = json.Unmarshal(allValue, &allData) + if err != nil { + logger.Errorf("SKVS Json unmarshal error: %s", err) + return err + } + } + logger.Warningf("Calling Put State (Mid-1), decrypt succeed, allData = %s", allData) + + valueHex := hex.EncodeToString(value) + + allData[key] = valueHex + logger.Warningf("Calling Put State (Mid-2), add need data key = %s, valueHex = %s, allData = %s", key, valueHex, allData) + + byteAllData, err := json.Marshal(allData) + if err != nil { + return err + } + logger.Warningf("Calling Put State (Mid-3), successfull marshal allData, byteAlldata = %x", byteAllData) + + encValue, err := s.sep.EncryptState(byteAllData) + if err != nil { + return err + } + logger.Warningf("Calling Put State (End), put encValue %x", encValue) + + return s.PutPublicState(SingleKey, encValue) +} diff --git a/ecc_go/chaincode/singleKVS.go b/ecc_go/chaincode/singleKVS.go index 9ea6ab01c..e756b8cbd 100644 --- a/ecc_go/chaincode/singleKVS.go +++ b/ecc_go/chaincode/singleKVS.go @@ -7,39 +7,150 @@ SPDX-License-Identifier: Apache-2.0 package chaincode import ( - "fmt" - "github.com/hyperledger/fabric-chaincode-go/shim" "github.com/hyperledger/fabric-private-chaincode/ecc/chaincode" + "github.com/hyperledger/fabric-private-chaincode/ecc/chaincode/ercc" + "github.com/hyperledger/fabric-private-chaincode/ecc_go/chaincode/enclave_go" + "github.com/hyperledger/fabric-private-chaincode/internal/endorsement" + "github.com/hyperledger/fabric/common/flogging" ) -var SingleKey = "SingleKey" +var logger = flogging.MustGetLogger("enclave_go") -type SKVSWrapper struct { - *chaincode.EnclaveChaincode +func NewSkvsChaincode(cc shim.Chaincode) *chaincode.EnclaveChaincode { + ecc := &chaincode.EnclaveChaincode{ + Enclave: enclave_go.NewSkvsStub(cc), + Validator: endorsement.NewValidator(), + Extractor: &chaincode.ExtractorImpl{}, + Ercc: &ercc.StubImpl{}, + } + return ecc } -type skvsStub struct { - shim.ChaincodeStubInterface -} +// type skvsStub struct { +// *enclave_go.EnclaveStub +// } -func (s *skvsStub) GetState(key string) ([]byte, error) { - fmt.Printf("Inside SKVS solution, GetState, key=%s\n", key) - return s.ChaincodeStubInterface.GetState(SingleKey) - // return s.ChaincodeStubInterface.GetState(key) -} +// func NewSkvsStub(cc shim.Chaincode) *skvsStub { +// enclaveStub := enclave_go.NewEnclaveStub(cc) +// return &skvsStub{enclaveStub} +// } -func (s *skvsStub) PutState(key string, value []byte) error { - fmt.Printf("Inside SKVS solution, PutState, key=%s, value=%x\n", key, value) - return s.ChaincodeStubInterface.PutState(SingleKey, value) - // return s.ChaincodeStubInterface.PutState(key, value) -} +// func (e *skvsStub) ChaincodeInvoke(stub shim.ChaincodeStubInterface, chaincodeRequestMessageBytes []byte) ([]byte, error) { +// logger.Error("==== SKVS ChaincodeInvoke ====") -func (s *SKVSWrapper) GetStub() shim.ChaincodeStubInterface { - // get the original stub - stub := s.GetStub() - fmt.Println("Inside SKVS solution, GetStub") - // create a new stub with the overridden GetState() function - skvsStub := &skvsStub{stub} - return skvsStub -} +// signedProposal, err := stub.GetSignedProposal() +// if err != nil { +// shim.Error(err.Error()) +// } + +// if err := e.verifySignedProposal(stub, chaincodeRequestMessageBytes); err != nil { +// return nil, errors.Wrap(err, "signed proposal verification failed") +// } + +// // unmarshal chaincodeRequest +// chaincodeRequestMessage := &protos.ChaincodeRequestMessage{} +// err = proto.Unmarshal(chaincodeRequestMessageBytes, chaincodeRequestMessage) +// if err != nil { +// return nil, err +// } + +// // get key transport message including the encryption keys for request and response +// keyTransportMessage, err := e.extractKeyTransportMessage(chaincodeRequestMessage) +// if err != nil { +// return nil, errors.Wrap(err, "cannot extract keyTransportMessage") +// } + +// // decrypt request +// cleartextChaincodeRequest, err := e.extractCleartextChaincodeRequest(chaincodeRequestMessage, keyTransportMessage) +// if err != nil { +// return nil, errors.Wrap(err, "cannot decrypt chaincode request") +// } + +// // create a new instance of a FPC RWSet that we pass to the stub and later return with the response +// rwset := NewReadWriteSet() + +// // Invoke chaincode +// // we wrap the stub with our FpcStubInterface +// // ** Implement our own FpcStubInterface +// skvsStub := NewSkvsStubInterface(stub, cleartextChaincodeRequest.GetInput(), rwset, e.ccKeys) +// ccResponse := e.ccRef.Invoke(skvsStub) +// // ** +// // fpcStub := NewFpcStubInterface(stub, cleartextChaincodeRequest.GetInput(), rwset, e.ccKeys) +// // ccResponse := e.ccRef.Invoke(fpcStub) + +// // marshal chaincode response +// ccResponseBytes, err := protoutil.Marshal(&ccResponse) +// if err != nil { +// return nil, err +// } + +// //encrypt response +// encryptedResponse, err := e.csp.EncryptMessage(keyTransportMessage.GetResponseEncryptionKey(), ccResponseBytes) +// if err != nil { +// return nil, err +// } + +// chaincodeRequestMessageHash := sha256.Sum256(chaincodeRequestMessageBytes) + +// response := &protos.ChaincodeResponseMessage{ +// EncryptedResponse: encryptedResponse, +// FpcRwSet: rwset.ToFPCKVSet(), +// EnclaveId: e.identity.GetEnclaveId(), +// Proposal: signedProposal, +// ChaincodeRequestMessageHash: chaincodeRequestMessageHash[:], +// } + +// responseBytes, err := proto.Marshal(response) +// if err != nil { +// return nil, err +// } + +// // create signature +// sig, err := e.identity.Sign(responseBytes) +// if err != nil { +// return nil, err +// } + +// signedResponse := &protos.SignedChaincodeResponseMessage{ +// ChaincodeResponseMessage: responseBytes, +// Signature: sig, +// } + +// return proto.Marshal(signedResponse) +// } + +// func (e *skvsStub) verifySignedProposal(stub shim.ChaincodeStubInterface, chaincodeRequestMessageBytes []byte) error { +// return e.EnclaveStub.verifySignedProposal(stub, chaincodeRequestMessageBytes) +// } + +// type SkvsStubInterface struct { +// *enclave_go.FpcStubInterface +// } + +// func NewSkvsStubInterface(stub shim.ChaincodeStubInterface, input *pb.ChaincodeInput, rwset *readWriteSet, sep StateEncryptionFunctions) *SkvsStubInterface { +// fpcStub := enclave_go.NewFpcStubInterface(stub, input, rwset, sep) +// return &SkvsStubInterface{fpcStub} +// } + +// func (s *SkvsStubInterface) GetState(key string) ([]byte, error) { +// encValue, err := s.GetPublicState(SingleKey) +// if err != nil { +// return nil, err +// } + +// // in case the key does not exist, return early +// if len(encValue) == 0 { +// return nil, nil +// } + +// return s.sep.DecryptState(encValue) +// } + +// func (s *SkvsStubInterface) PutState(key string, value []byte) error { +// encValue, err := s.sep.EncryptState(SingleKey) +// if err != nil { +// return err +// } +// return s.PutPublicState(key, encValue) +// } diff --git a/samples/chaincode/secret-keeper-go/main.go b/samples/chaincode/secret-keeper-go/main.go index b3b1515a0..7ab8b9b07 100644 --- a/samples/chaincode/secret-keeper-go/main.go +++ b/samples/chaincode/secret-keeper-go/main.go @@ -23,10 +23,11 @@ func main() { // create chaincode secretChaincode, _ := contractapi.NewChaincode(&chaincode.SecretKeeper{}) - chaincode := fpc.NewPrivateChaincode(secretChaincode) + // chaincode := fpc.NewPrivateChaincode(secretChaincode) + skvsChaincode := fpc.NewSkvsChaincode(secretChaincode) - // single KVS - skvsChaincode := &fpc.SingleKVSWrapper{chaincode} + // // single KVS + // skvsChaincode := &fpc.SKVSWrapper{chaincode} // start chaincode as a service server := &shim.ChaincodeServer{