Skip to content

Commit 44ae2fe

Browse files
committed
Copying shim/crypto to new a package
This change-set is the first step in the process of removing shim/crypto and the dependencies from the ChaincodeStubInterface. The change-set introduces a new top-level folder called accesscontrol that has the same content of shim/crypto plus a file containing some API. Subsequent change-sets will remove shim/crypto and ensure that the chaincode example can still work. Change-Id: I8b1c701fd708e497dc6d95dbada5619979d05964 Signed-off-by: Angelo De Caro <[email protected]>
1 parent 5c9fcc3 commit 44ae2fe

12 files changed

+1348
-0
lines changed

accesscontrol/api.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package accesscontrol
2+
3+
// Attribute defines a name, value pair to be verified.
4+
type Attribute struct {
5+
Name string
6+
Value []byte
7+
}
8+
9+
// AttributesManager can be used to verify and read attributes.
10+
type AttributesManager interface {
11+
ReadCertAttribute(attributeName string) ([]byte, error)
12+
13+
VerifyAttribute(attributeName string, attributeValue []byte) (bool, error)
14+
15+
VerifyAttributes(attrs ...*Attribute) (bool, error)
16+
}
+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
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 attr
18+
19+
import (
20+
"bytes"
21+
"crypto/x509"
22+
"errors"
23+
24+
"github.com/hyperledger/fabric/accesscontrol"
25+
"github.com/hyperledger/fabric/core/crypto/attributes"
26+
"github.com/hyperledger/fabric/core/crypto/primitives"
27+
)
28+
29+
// chaincodeHolder is the struct that hold the certificate and the metadata. An implementation is ChaincodeStub
30+
type chaincodeHolder interface {
31+
// GetCallerCertificate returns caller certificate
32+
GetCallerCertificate() ([]byte, error)
33+
34+
// GetCallerMetadata returns caller metadata
35+
/*
36+
TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field.
37+
GetCallerMetadata() ([]byte, error)
38+
*/
39+
}
40+
41+
//AttributesHandler is an entity can be used to both verify and read attributes.
42+
// The functions declared can be used to access the attributes stored in the transaction certificates from the application layer. Can be used directly from the ChaincodeStub API but
43+
// if you need multiple access create a hanlder is better:
44+
// Multiple accesses
45+
// If multiple calls to the functions above are required, a best practice is to create an AttributesHandler instead of calling the functions multiple times, this practice will avoid creating a new AttributesHandler for each of these calls thus eliminating an unnecessary overhead.
46+
// Example:
47+
//
48+
// AttributesHandler, err := ac.NewAttributesHandlerImpl(stub)
49+
// if err != nil {
50+
// return false, err
51+
// }
52+
// AttributesHandler.VerifyAttribute(attributeName, attributeValue)
53+
// ... you can make other verifications and/or read attribute values by using the AttributesHandler
54+
type AttributesHandler interface {
55+
56+
//VerifyAttributes does the same as VerifyAttribute but it checks for a list of attributes and their respective values instead of a single attribute/value pair
57+
// Example:
58+
// containsAttrs, error:= handler.VerifyAttributes(&ac.Attribute{"position", "Software Engineer"}, &ac.Attribute{"company", "ACompany"})
59+
VerifyAttributes(attrs ...*accesscontrol.Attribute) (bool, error)
60+
61+
//VerifyAttribute is used to verify if the transaction certificate has an attribute with name *attributeName* and value *attributeValue* which are the input parameters received by this function.
62+
//Example:
63+
// containsAttr, error := handler.VerifyAttribute("position", "Software Engineer")
64+
VerifyAttribute(attributeName string, attributeValue []byte) (bool, error)
65+
66+
//GetValue is used to read an specific attribute from the transaction certificate, *attributeName* is passed as input parameter to this function.
67+
// Example:
68+
// attrValue,error:=handler.GetValue("position")
69+
GetValue(attributeName string) ([]byte, error)
70+
}
71+
72+
//AttributesHandlerImpl is an implementation of AttributesHandler interface.
73+
type AttributesHandlerImpl struct {
74+
cert *x509.Certificate
75+
cache map[string][]byte
76+
keys map[string][]byte
77+
header map[string]int
78+
encrypted bool
79+
}
80+
81+
type chaincodeHolderImpl struct {
82+
Certificate []byte
83+
}
84+
85+
// GetCallerCertificate returns caller certificate
86+
func (holderImpl *chaincodeHolderImpl) GetCallerCertificate() ([]byte, error) {
87+
return holderImpl.Certificate, nil
88+
}
89+
90+
//GetValueFrom returns the value of 'attributeName0' from a cert.
91+
func GetValueFrom(attributeName string, cert []byte) ([]byte, error) {
92+
handler, err := NewAttributesHandlerImpl(&chaincodeHolderImpl{Certificate: cert})
93+
if err != nil {
94+
return nil, err
95+
}
96+
return handler.GetValue(attributeName)
97+
}
98+
99+
//NewAttributesHandlerImpl creates a new AttributesHandlerImpl from a pb.ChaincodeSecurityContext object.
100+
func NewAttributesHandlerImpl(holder chaincodeHolder) (*AttributesHandlerImpl, error) {
101+
// Getting certificate
102+
certRaw, err := holder.GetCallerCertificate()
103+
if err != nil {
104+
return nil, err
105+
}
106+
if certRaw == nil {
107+
return nil, errors.New("The certificate can't be nil.")
108+
}
109+
var tcert *x509.Certificate
110+
tcert, err = primitives.DERToX509Certificate(certRaw)
111+
if err != nil {
112+
return nil, err
113+
}
114+
115+
keys := make(map[string][]byte)
116+
117+
/*
118+
TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field.
119+
120+
//Getting Attributes Metadata from security context.
121+
var attrsMetadata *attributespb.AttributesMetadata
122+
var rawMetadata []byte
123+
rawMetadata, err = holder.GetCallerMetadata()
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
if rawMetadata != nil {
129+
attrsMetadata, err = attributes.GetAttributesMetadata(rawMetadata)
130+
if err == nil {
131+
for _, entry := range attrsMetadata.Entries {
132+
keys[entry.AttributeName] = entry.AttributeKey
133+
}
134+
}
135+
}*/
136+
137+
cache := make(map[string][]byte)
138+
return &AttributesHandlerImpl{tcert, cache, keys, nil, false}, nil
139+
}
140+
141+
func (attributesHandler *AttributesHandlerImpl) readHeader() (map[string]int, bool, error) {
142+
if attributesHandler.header != nil {
143+
return attributesHandler.header, attributesHandler.encrypted, nil
144+
}
145+
header, encrypted, err := attributes.ReadAttributeHeader(attributesHandler.cert, attributesHandler.keys[attributes.HeaderAttributeName])
146+
if err != nil {
147+
return nil, false, err
148+
}
149+
attributesHandler.header = header
150+
attributesHandler.encrypted = encrypted
151+
return header, encrypted, nil
152+
}
153+
154+
//GetValue is used to read an specific attribute from the transaction certificate, *attributeName* is passed as input parameter to this function.
155+
// Example:
156+
// attrValue,error:=handler.GetValue("position")
157+
func (attributesHandler *AttributesHandlerImpl) GetValue(attributeName string) ([]byte, error) {
158+
if attributesHandler.cache[attributeName] != nil {
159+
return attributesHandler.cache[attributeName], nil
160+
}
161+
header, encrypted, err := attributesHandler.readHeader()
162+
if err != nil {
163+
return nil, err
164+
}
165+
value, err := attributes.ReadTCertAttributeByPosition(attributesHandler.cert, header[attributeName])
166+
if err != nil {
167+
return nil, errors.New("Error reading attribute value '" + err.Error() + "'")
168+
}
169+
170+
if encrypted {
171+
if attributesHandler.keys[attributeName] == nil {
172+
return nil, errors.New("Cannot find decryption key for attribute")
173+
}
174+
175+
value, err = attributes.DecryptAttributeValue(attributesHandler.keys[attributeName], value)
176+
if err != nil {
177+
return nil, errors.New("Error decrypting value '" + err.Error() + "'")
178+
}
179+
}
180+
attributesHandler.cache[attributeName] = value
181+
return value, nil
182+
}
183+
184+
//VerifyAttribute is used to verify if the transaction certificate has an attribute with name *attributeName* and value *attributeValue* which are the input parameters received by this function.
185+
// Example:
186+
// containsAttr, error := handler.VerifyAttribute("position", "Software Engineer")
187+
func (attributesHandler *AttributesHandlerImpl) VerifyAttribute(attributeName string, attributeValue []byte) (bool, error) {
188+
valueHash, err := attributesHandler.GetValue(attributeName)
189+
if err != nil {
190+
return false, err
191+
}
192+
return bytes.Compare(valueHash, attributeValue) == 0, nil
193+
}
194+
195+
//VerifyAttributes does the same as VerifyAttribute but it checks for a list of attributes and their respective values instead of a single attribute/value pair
196+
// Example:
197+
// containsAttrs, error:= handler.VerifyAttributes(&ac.Attribute{"position", "Software Engineer"}, &ac.Attribute{"company", "ACompany"})
198+
func (attributesHandler *AttributesHandlerImpl) VerifyAttributes(attrs ...*accesscontrol.Attribute) (bool, error) {
199+
for _, attribute := range attrs {
200+
val, err := attributesHandler.VerifyAttribute(attribute.Name, attribute.Value)
201+
if err != nil {
202+
return false, err
203+
}
204+
if !val {
205+
return val, nil
206+
}
207+
}
208+
return true, nil
209+
}

0 commit comments

Comments
 (0)