github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/test/tools/PTE/chaincode_sample.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "crypto/aes" 21 "crypto/cipher" 22 "crypto/rand" 23 "fmt" 24 "io" 25 26 "github.com/hyperledger/fabric/core/chaincode/shim" 27 pb "github.com/hyperledger/fabric/protos/peer" 28 ) 29 30 // cryptoChaincode is allows the following transactions 31 // "put", "key", val - returns "OK" on success 32 // "get", "key" - returns val stored previously 33 type cryptoChaincode struct { 34 } 35 36 const ( 37 AESKeyLength = 32 // AESKeyLength is the default AES key length 38 NonceSize = 24 // NonceSize is the default NonceSize 39 ) 40 41 /////////////////////////////////////////////////// 42 // GetRandomByt es returns len random looking bytes 43 /////////////////////////////////////////////////// 44 func GetRandomBytes(len int) ([]byte, error) { 45 //TODO: Should we fix the length ? 46 key := make([]byte, len) 47 48 _, err := rand.Read(key) 49 if err != nil { 50 return nil, err 51 } 52 53 return key, nil 54 } 55 56 //////////////////////////////////////////////////////////// 57 // GenAESKey returns a random AES key of length AESKeyLength 58 // 3 Functions to support Encryption and Decryption 59 // GENAESKey() - Generates AES symmetric key 60 func (t *cryptoChaincode) GenAESKey() ([]byte, error) { 61 return GetRandomBytes(AESKeyLength) 62 } 63 64 //Init implements chaincode's Init interface 65 func (t *cryptoChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { 66 return shim.Success(nil) 67 } 68 69 //Invoke implements chaincode's Invoke interface 70 func (t *cryptoChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { 71 function, args := stub.GetFunctionAndParameters() 72 if function != "invoke" { 73 return shim.Error("Unknown function call") 74 } 75 76 if len(args) < 2 { 77 return shim.Error(fmt.Sprintf("invalid number of args %d", len(args))) 78 } 79 method := args[0] 80 if method == "put" { 81 if len(args) < 3 { 82 return shim.Error(fmt.Sprintf("invalid number of args for put %d", len(args))) 83 } 84 return t.writeTransaction(stub, args) 85 } else if method == "get" { 86 return t.readTransaction(stub, args) 87 } 88 return shim.Error(fmt.Sprintf("unknown function %s", method)) 89 } 90 91 func (t *cryptoChaincode) encryptAndDecrypt(arg string) []byte { 92 AES_key, _ := t.GenAESKey() 93 AES_enc := t.Encrypt(AES_key, []byte(arg)) 94 95 value := t.Decrypt(AES_key, AES_enc) 96 return value 97 } 98 99 func (t *cryptoChaincode) Encrypt(key []byte, byteArray []byte) []byte { 100 101 // Create the AES cipher 102 block, err := aes.NewCipher(key) 103 if err != nil { 104 panic(err) 105 } 106 107 // Empty array of 16 + byteArray length 108 // Include the IV at the beginning 109 ciphertext := make([]byte, aes.BlockSize+len(byteArray)) 110 111 // Slice of first 16 bytes 112 iv := ciphertext[:aes.BlockSize] 113 114 // Write 16 rand bytes to fill iv 115 if _, err := io.ReadFull(rand.Reader, iv); err != nil { 116 panic(err) 117 } 118 119 // Return an encrypted stream 120 stream := cipher.NewCFBEncrypter(block, iv) 121 122 // Encrypt bytes from byteArray to ciphertext 123 stream.XORKeyStream(ciphertext[aes.BlockSize:], byteArray) 124 125 return ciphertext 126 } 127 128 func (t *cryptoChaincode) Decrypt(key []byte, ciphertext []byte) []byte { 129 130 // Create the AES cipher 131 block, err := aes.NewCipher(key) 132 if err != nil { 133 panic(err) 134 } 135 136 // Before even testing the decryption, 137 // if the text is too small, then it is incorrect 138 if len(ciphertext) < aes.BlockSize { 139 panic("Text is too short") 140 } 141 142 // Get the 16 byte IV 143 iv := ciphertext[:aes.BlockSize] 144 145 // Remove the IV from the ciphertext 146 ciphertext = ciphertext[aes.BlockSize:] 147 148 // Return a decrypted stream 149 stream := cipher.NewCFBDecrypter(block, iv) 150 151 // Decrypt bytes from ciphertext 152 stream.XORKeyStream(ciphertext, ciphertext) 153 154 return ciphertext 155 } 156 157 func (t *cryptoChaincode) writeTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response { 158 cryptoArg := t.encryptAndDecrypt(args[2]) 159 err := stub.PutState(args[1], cryptoArg) 160 if err != nil { 161 return shim.Error(err.Error()) 162 } 163 return shim.Success([]byte("OK")) 164 } 165 166 func (t *cryptoChaincode) readTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response { 167 // Get the state from the ledger 168 val, err := stub.GetState(args[1]) 169 if err != nil { 170 return shim.Error(err.Error()) 171 } 172 return shim.Success(val) 173 } 174 175 func main() { 176 err := shim.Start(new(cryptoChaincode)) 177 if err != nil { 178 fmt.Printf("Error starting New key per invoke: %s", err) 179 } 180 }