-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge Secret Keeper Application (#2)
Secret Keeper has 5 functions. InitSecretKeeper: - This function will initialize the key "AUTH_LIST_KEY" with value ["Alice", "Bob"] and key "SECRET_KEY" with value "DefaultSecret". - This function should only be called once when the application started. - Of course a malicious user can call this function to reset the value, but this we will assume this is not what an attacker would want to achieve. RevealSecret: - This function allow users that in the Authlist ("AUTH_LIST_KEY") able to reveal the value of secret stored under key "SECRET_KEY". LockSecret: - This function allow users that in the Authlist ("AUTH_LIST_KEY") able to store a new value of secret under key "SECRET_KEY". - The old value will be replaced. AddUser: - This function allow users that in the Authlist ("AUTH_LIST_KEY") able to add a new user to the Authlist. - Then the new user can now perform the following four functions (RevealSecret, LockSecret, AddUser, RemoveUser) RemoveUser: - This function allow users that in the Authlist ("AUTH_LIST_KEY") able to add remove an existing user off the Authlist. - Then the removed user can no longer able to perform the following four functions (RevealSecret, LockSecret, AddUser, RemoveUser) Example using fpc-simple-client: ./fpcclient invoke initSecretKeeper ./fpcclient query revealSecret Alice ./fpcclient invoke lockSecret Bob NewSecret ./fpcclient query revealSecret Alice ./fpcclient invoke removeUser Alice Bob ./fpcclient query revealSecret Alice ./fpcclient query revealSecret Bob // (will failed) ./fpcclient invoke addUser Alice Bob ./fpcclient query revealSecret Bob // (will success) -------- * implement secret keeper demo * debug * create unit test mock rollback attack --------- Co-authored-by: Chen Chang Lew <lew@stromness.zrl.ch.ibm.com> Co-authored-by: tester <tester@fpc> Signed-off-by: chenchanglew <chelew@student.ethz.ch> Signed-off-by: chenchanglew <lewchenchang@gmail.com>
- Loading branch information
1 parent
e0eb483
commit e345811
Showing
5 changed files
with
534 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
ecc | ||
ecc-bundle | ||
enclave.json | ||
private.pem | ||
public.pem | ||
mrenclave | ||
details.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Copyright 2019 Intel Corporation | ||
# Copyright IBM Corp. All Rights Reserved. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
TOP = ../../.. | ||
include $(TOP)/ecc_go/build.mk | ||
|
||
CC_NAME ?= fpc-secret-keeper-go |
205 changes: 205 additions & 0 deletions
205
samples/chaincode/secret-keeper-go/chaincode/secret-keeper.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package chaincode | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/hyperledger/fabric-contract-api-go/contractapi" | ||
) | ||
|
||
const OK = "OK" | ||
const AUTH_LIST_KEY = "AUTH_LIST_KEY" | ||
const SECRET_KEY = "SECRET_KEY" | ||
|
||
type SecretKeeper struct { | ||
contractapi.Contract | ||
} | ||
|
||
type AuthSet struct { | ||
Pubkey map[string]struct{} | ||
} | ||
|
||
type Secret struct { | ||
Value string `json:Value` | ||
} | ||
|
||
func (t *SecretKeeper) InitSecretKeeper(ctx contractapi.TransactionContextInterface) error { | ||
// init authSet | ||
pubkeyset := make(map[string]struct{}) | ||
pubkeyset["Alice"] = struct{}{} | ||
pubkeyset["Bob"] = struct{}{} | ||
authSet := AuthSet{ | ||
Pubkey: pubkeyset, | ||
} | ||
|
||
authSetJson, err := json.Marshal(authSet) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = ctx.GetStub().PutState(AUTH_LIST_KEY, authSetJson) | ||
if err != nil { | ||
return fmt.Errorf("failed to put %s to world state. %v", AUTH_LIST_KEY, err) | ||
} | ||
|
||
// init secret | ||
secret := Secret{ | ||
Value: "DefaultSecret", | ||
} | ||
|
||
secretJson, err := json.Marshal(secret) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = ctx.GetStub().PutState(SECRET_KEY, secretJson) | ||
if err != nil { | ||
return fmt.Errorf("failed to put %s to world state. %v", SECRET_KEY, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (t *SecretKeeper) AddUser(ctx contractapi.TransactionContextInterface, sig string, pubkey string) error { | ||
// check if the user allow to update authSet | ||
valid, err := VerifySig(ctx, sig) | ||
if err != nil { | ||
return err | ||
} | ||
if valid != true { | ||
return fmt.Errorf("User are not allowed to perform this action.") | ||
} | ||
|
||
// update the value | ||
authSet, err := GetAuthList(ctx) | ||
authSet.Pubkey[pubkey] = struct{}{} | ||
|
||
authSetJson, err := json.Marshal(authSet) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = ctx.GetStub().PutState(AUTH_LIST_KEY, authSetJson) | ||
if err != nil { | ||
return fmt.Errorf("failed to put %s to world state. %v", AUTH_LIST_KEY, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (t *SecretKeeper) RemoveUser(ctx contractapi.TransactionContextInterface, sig string, pubkey string) error { | ||
// check if the user allow to update authSet | ||
valid, err := VerifySig(ctx, sig) | ||
if err != nil { | ||
return err | ||
} | ||
if valid != true { | ||
return fmt.Errorf("User are not allowed to perform this action.") | ||
} | ||
|
||
// update the value | ||
authSet, err := GetAuthList(ctx) | ||
delete(authSet.Pubkey, pubkey) | ||
|
||
authSetJson, err := json.Marshal(authSet) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = ctx.GetStub().PutState(AUTH_LIST_KEY, authSetJson) | ||
if err != nil { | ||
return fmt.Errorf("failed to put %s to world state. %v", AUTH_LIST_KEY, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (t *SecretKeeper) LockSecret(ctx contractapi.TransactionContextInterface, sig string, value string) error { | ||
// check if the user allow to update secret | ||
valid, err := VerifySig(ctx, sig) | ||
if err != nil { | ||
return err | ||
} | ||
if valid != true { | ||
return fmt.Errorf("User are not allowed to perform this action.") | ||
} | ||
|
||
// update the value | ||
newSecret := Secret{ | ||
Value: value, | ||
} | ||
|
||
newSecretJson, err := json.Marshal(newSecret) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = ctx.GetStub().PutState(SECRET_KEY, newSecretJson) | ||
if err != nil { | ||
return fmt.Errorf("failed to put %s to world state. %v", SECRET_KEY, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (t *SecretKeeper) RevealSecret(ctx contractapi.TransactionContextInterface, sig string) (*Secret, error) { | ||
// check if the user allow to view the secret. | ||
valid, err := VerifySig(ctx, sig) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if valid != true { | ||
return nil, fmt.Errorf("User are not allowed to perform this action.") | ||
} | ||
|
||
// reveal secret | ||
secretJson, err := ctx.GetStub().GetState(SECRET_KEY) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read from world state: %v", err) | ||
} | ||
if secretJson == nil { | ||
return nil, fmt.Errorf("the asset %s does not exist", SECRET_KEY) | ||
} | ||
var secret Secret | ||
err = json.Unmarshal(secretJson, &secret) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &secret, nil | ||
} | ||
|
||
func GetAuthList(ctx contractapi.TransactionContextInterface) (*AuthSet, error) { | ||
authSetJson, err := ctx.GetStub().GetState(AUTH_LIST_KEY) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to read from world state: %v", err) | ||
} | ||
if authSetJson == nil { | ||
return nil, fmt.Errorf("the asset %s does not exist", AUTH_LIST_KEY) | ||
} | ||
|
||
var authSet AuthSet | ||
err = json.Unmarshal(authSetJson, &authSet) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &authSet, nil | ||
} | ||
|
||
func VerifySig(ctx contractapi.TransactionContextInterface, sig string) (bool, error) { | ||
authSet, err := GetAuthList(ctx) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
if _, exist := authSet.Pubkey[sig]; exist { | ||
return true, nil | ||
} | ||
|
||
return false, nil | ||
} |
Oops, something went wrong.