forked from hyperledger/fabric-private-chaincode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrypto.go
133 lines (107 loc) · 3.59 KB
/
crypto.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
Copyright IBM Corp. All Rights Reserved.
Copyright 2020 Intel Corporation
SPDX-License-Identifier: Apache-2.0
*/
package crypto
import (
"encoding/base64"
"github.com/hyperledger-labs/fabric-private-chaincode/internal/protos"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/flogging"
"google.golang.org/protobuf/proto"
)
var logger = flogging.MustGetLogger("fpc-client-crypto")
func encrypt(input []byte, encryptionKey []byte) ([]byte, error) {
return input, nil
}
func keyGen() ([]byte, error) {
return []byte("fake key"), nil
}
func decrypt(encryptedResponse []byte, resultEncryptionKey []byte) ([]byte, error) {
return encryptedResponse, nil
}
type EncryptionProvider interface {
NewEncryptionContext() (EncryptionContext, error)
}
type EncryptionProviderImpl struct {
GetCcEncryptionKey func() ([]byte, error)
}
func (e EncryptionProviderImpl) NewEncryptionContext() (EncryptionContext, error) {
// pick response encryption key
resultEncryptionKey, err := keyGen()
if err != nil {
return nil, err
}
ccEncryptionKey, err := e.GetCcEncryptionKey()
if err != nil {
return nil, err
}
return &EncryptionContextImpl{
resultEncryptionKey: resultEncryptionKey,
chaincodeEncryptionKey: ccEncryptionKey,
}, nil
}
// EncryptionContext defines the interface of an object responsible to encrypt the contents of a transaction invocation
// and decrypt the corresponding response.
// Conceal and Reveal must be called only once during the lifetime of an object that implements this interface. That is,
// an EncryptionContext is only valid for a single transaction invocation.
type EncryptionContext interface {
Conceal(function string, args []string) (string, error)
Reveal(r []byte) ([]byte, error)
}
type EncryptionContextImpl struct {
resultEncryptionKey []byte
chaincodeEncryptionKey []byte
}
func (e *EncryptionContextImpl) Reveal(responseBytesB64 []byte) ([]byte, error) {
responseBytes, err := base64.StdEncoding.DecodeString(string(responseBytesB64))
if err != nil {
return nil, err
}
response := &protos.ChaincodeResponseMessage{}
err = proto.Unmarshal(responseBytes, response)
if err != nil {
return nil, err
}
clearResponseB64, err := decrypt(response.EncryptedResponse, e.resultEncryptionKey)
if err != nil {
return nil, err
}
// TODO: above should eventually be a (protobuf but not base64 serialized) fabric response object,
// rather than just the (base64-serialized) response string.
// so we also get fpc chaincode return-code/error-message as in for normal fabric
clearResponse, err := base64.StdEncoding.DecodeString(string(clearResponseB64))
if err != nil {
return nil, err
}
return clearResponse, nil
}
func (e *EncryptionContextImpl) Conceal(function string, args []string) (string, error) {
args = append([]string{function}, args...)
bytes := make([][]byte, len(args))
for i, v := range args {
bytes[i] = []byte(v)
}
ccRequest := &protos.CleartextChaincodeRequest{
Input: &peer.ChaincodeInput{Args: bytes},
ReturnEncryptionKey: e.resultEncryptionKey,
}
logger.Debugf("prepping chaincode params: %s", ccRequest)
serializedCcRequest, err := proto.Marshal(ccRequest)
if err != nil {
return "", err
}
encryptedParams, err := encrypt(serializedCcRequest, e.chaincodeEncryptionKey)
if err != nil {
return "", err
}
encryptedCcRequest := &protos.ChaincodeRequestMessage{
EncryptedRequest: encryptedParams,
}
serializedEncryptedCcRequest, err := proto.Marshal(encryptedCcRequest)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(serializedEncryptedCcRequest), nil
}