github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/accesscontrol/crypto/attr/attr_support.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 attr 18 19 import ( 20 "bytes" 21 "crypto/x509" 22 "errors" 23 24 "github.com/hyperledger/fabric/accesscontrol" 25 "github.com/hyperledger/fabric/accesscontrol/attributes" 26 "github.com/hyperledger/fabric/accesscontrol/crypto/utils" 27 ) 28 29 // chaincodeHolder is the struct that hold the certificate and the metadata. An implementation is ChaincodeStub 30 type chaincodeHolder interface { 31 // GetCreator returns caller certificate 32 GetCreator() ([]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 // GetCreator returns caller certificate 86 func (holderImpl *chaincodeHolderImpl) GetCreator() ([]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.GetCreator() 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 = utils.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 }