/* * Copyright IBM Corp All Rights Reserved * * SPDX-License-Identifier: Apache-2.0 */ package main import ( //"bytes" //"crypto/rand" "encoding/base64" "fmt" "math/big" "paillier" "github.com/hyperledger/fabric/core/chaincode/shim" "github.com/hyperledger/fabric/protos/peer" ) const pkSuffix = ".pk" const skSuffix = ".sk" // SimpleAsset implements a simple chaincode to manage an asset type SimpleAsset struct { } // Init is called during chaincode instantiation to initialize any // data. Note that chaincode upgrade also calls this function to reset // or to migrate data. func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response { // Get the args from the transaction proposal args := stub.GetStringArgs() if len(args) != 0 { return shim.Error("Incorrect arguments. No argument is needed") } /* length, err := strconv.Atoi(args[0]) if err != nil { return shim.Error("invalid length") } */ return shim.Success(nil) } // Invoke is called per transaction on the chaincode. Each transaction is // either a 'get' or a 'set' on the asset created by Init function. The Set // method may create a new asset by specifying a new key-value pair. func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { // Extract the function and args from the transaction proposal fn, args := stub.GetFunctionAndParameters() var result string var err error switch fn { case "set": { // set user account value result, err = set(stub, args) } case "get": { // get user account value result, err = get(stub, args) } case "negate": { // compute negation of user account value result, err = negate(stub, args) } case "addCipher": { // add user account ciphertext with another ciphertext result, err = addCipher(stub, args) } case "addNumber": { // add user account ciphertext with a number plaintext result, err = addNumber(stub, args) } case "subCipher": { // subtract user account ciphertext with another ciphertext result, err = subCipher(stub, args) } case "subNumber": { // subtract user account ciphertext with a number plaintext result, err = subNumber(stub, args) } case "mulNumber": { // multiply user account ciphertext with a number plaintext result, err = mulNumber(stub, args) } default: { shim.Error("invalid function") } } if err != nil { return shim.Error(err.Error()) } // Return the result as success payload return shim.Success([]byte(result)) } // Set stores the asset (both key and value) on the ledger. If the key exists, // it will override the value with the new one func set(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 2 { return "", fmt.Errorf("Incorrect arguments. Expecting a user name and a value") } userName := args[0] value := args[1] err := stub.PutState(userName, []byte(value)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return value, nil } // Get returns the value of the specified asset key func get(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 2 { return "", fmt.Errorf("Incorrect arguments. Expecting a user name and a secret key") } userName := args[0] sktext, err := base64.StdEncoding.DecodeString(args[1]) if err != nil { return "", err } sk, err := paillier.GetPrivateKeyFromHex(string(sktext)) if err != nil { return "", fmt.Errorf("invalid secret key") } value, err := stub.GetState(userName) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if value == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } cipher, err := paillier.GetCiphertextFromHex(string(value)) if err != nil { return "", err } plain, err := paillier.Decrypt(sk, cipher) if err != nil { return "", err } fmt.Println(plain) return plain, nil } func negate(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 2 { return "", fmt.Errorf("Incorrect arguments. Expecting a user name and a public key") } userName := args[0] pkPem, err := base64.StdEncoding.DecodeString(args[1]) if err != nil { return "", err } pk, err := paillier.GetPublicKeyFromHex(string(pkPem)) if err != nil { return "", fmt.Errorf("invalid public key") } value, err := stub.GetState(userName) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if value == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } cipher, err := paillier.GetCiphertextFromHex(string(value)) if err != nil { return "", err } newValue, err := paillier.Neg(pk, cipher) newCipher, err := paillier.GetCiphertextHex(newValue) if err != nil { return "", err } err = stub.PutState(userName, []byte(newCipher)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return newValue, nil } func addCipher(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 3 { return "", fmt.Errorf("Incorrect arguments. Expecting two user names and a public key") } c1, err := stub.GetState(args[0]) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if c1 == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } c2, err := stub.GetState(args[1]) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if c2 == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } pkPem, err := base64.StdEncoding.DecodeString(args[2]) if err != nil { return "", err } pk, err := paillier.GetPublicKeyFromHex(string(pkPem)) if err != nil { return "", fmt.Errorf("invalid public key") } cipher1, err := paillier.GetCiphertextFromHex(string(c1)) if err != nil { return "", err } cipher2, err := paillier.GetCiphertextFromHex(string(c2)) if err != nil { return "", err } cNew, err := paillier.AddCipher(pk, cipher1, cipher2) if err != nil { return "", fmt.Errorf("failed to add ciphertexts") } newCipher, err := paillier.GetCiphertextHex(cNew) if err != nil { return "", err } err = stub.PutState(args[0], []byte(newCipher)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return cNew, nil } func addNumber(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 3 { return "", fmt.Errorf("Incorrect arguments. Expecting a user name and a number and a public key") } userName := args[0] num, isOK := new(big.Int).SetString(args[1], 10) if !isOK { return "", fmt.Errorf("invalid number") } pkPem, err := base64.StdEncoding.DecodeString(args[2]) if err != nil { return "", err } pk, err := paillier.GetPublicKeyFromHex(string(pkPem)) if err != nil { return "", fmt.Errorf("invalid public key") } c1, err := stub.GetState(userName) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if c1 == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } cipher1, err := paillier.GetCiphertextFromHex(string(c1)) if err != nil { return "", err } cNew, err := paillier.Add(pk, cipher1, num.Text(10)) if err != nil { return "", fmt.Errorf("failed to add ciphertexts") } newCipher, err := paillier.GetCiphertextHex(cNew) if err != nil { return "", err } err = stub.PutState(userName, []byte(newCipher)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return cNew, nil } func subCipher(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 3 { return "", fmt.Errorf("Incorrect arguments. Expecting two user name and a public key") } pkPem, err := base64.StdEncoding.DecodeString(args[2]) if err != nil { return "", err } pk, err := paillier.GetPublicKeyFromHex(string(pkPem)) if err != nil { return "", fmt.Errorf("invalid public key") } c1, err := stub.GetState(args[0]) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if c1 == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } c2, err := stub.GetState(args[1]) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[1], err) } if c2 == nil { return "", fmt.Errorf("Asset not found: %s", args[1]) } cipher1, err := paillier.GetCiphertextFromHex(string(c1)) if err != nil { return "", err } cipher2, err := paillier.GetCiphertextFromHex(string(c2)) if err != nil { return "", err } cNew, err := paillier.SubCipher(pk, cipher1, cipher2) if err != nil { return "", fmt.Errorf("failed to subtract ciphertexts") } newCipher, err := paillier.GetCiphertextHex(cNew) if err != nil { return "", err } err = stub.PutState(args[0], []byte(newCipher)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return cNew, nil } func subNumber(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 3 { return "", fmt.Errorf("Incorrect arguments. Expecting a user name and a number and a public key") } userName := args[0] num, isOK := new(big.Int).SetString(args[1], 10) if !isOK { return "", fmt.Errorf("invalid number") } pkPem, err := base64.StdEncoding.DecodeString(args[2]) if err != nil { return "", err } pk, err := paillier.GetPublicKeyFromHex(string(pkPem)) if err != nil { return "", fmt.Errorf("invalid public key") } c1, err := stub.GetState(userName) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if c1 == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } cipher1, err := paillier.GetCiphertextFromHex(string(c1)) if err != nil { return "", err } cNew, err := paillier.Sub(pk, cipher1, num.Text(10)) if err != nil { return "", fmt.Errorf("failed to subtract ciphertexts") } newCipher, err := paillier.GetCiphertextHex(cNew) if err != nil { return "", err } err = stub.PutState(userName, []byte(newCipher)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return cNew, nil } func mulNumber(stub shim.ChaincodeStubInterface, args []string) (string, error) { if len(args) != 3 { return "", fmt.Errorf("Incorrect arguments. Expecting a user name and a number and a public key") } userName := args[0] num, isOK := new(big.Int).SetString(args[1], 10) if !isOK { return "", fmt.Errorf("invalid number") } pkPem, err := base64.StdEncoding.DecodeString(args[2]) if err != nil { return "", err } pk, err := paillier.GetPublicKeyFromHex(string(pkPem)) if err != nil { return "", fmt.Errorf("invalid public key") } c1, err := stub.GetState(userName) if err != nil { return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err) } if c1 == nil { return "", fmt.Errorf("Asset not found: %s", args[0]) } cipher1, err := paillier.GetCiphertextFromHex(string(c1)) if err != nil { return "", err } cNew, err := paillier.Mul(pk, cipher1, num.Text(10)) if err != nil { return "", fmt.Errorf("failed to multiply ciphertexts") } newCipher, err := paillier.GetCiphertextHex(cNew) if err != nil { return "", err } err = stub.PutState(userName, []byte(newCipher)) if err != nil { return "", fmt.Errorf("Failed to set asset: %s", args[0]) } return cNew, nil } // main function starts up the chaincode in the container during instantiate func main() { if err := shim.Start(new(SimpleAsset)); err != nil { fmt.Printf("Error starting SimpleAsset chaincode: %s", err) } }