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  }