From 44ae2fe012d640f9fa9a5e7c360ddaca10aef45a Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Thu, 8 Dec 2016 09:08:12 +0100 Subject: [PATCH] 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 --- accesscontrol/api.go | 16 + accesscontrol/crypto/attr/attr_support.go | 209 ++++++ .../crypto/attr/attr_support_test.go | 682 ++++++++++++++++++ .../crypto/attr/test_resources/prek0.dump | 1 + .../crypto/attr/test_resources/tcert.dump | 18 + .../crypto/attr/test_resources/tcert_bad.dump | 17 + .../attr/test_resources/tcert_clear.dump | 16 + accesscontrol/crypto/crypto.go | 24 + accesscontrol/crypto/ecdsa/ecdsa.go | 67 ++ accesscontrol/crypto/ecdsa/ecdsa_test.go | 191 +++++ accesscontrol/crypto/ecdsa/hash.go | 82 +++ accesscontrol/crypto/ecdsa/x509.go | 25 + 12 files changed, 1348 insertions(+) create mode 100644 accesscontrol/api.go create mode 100644 accesscontrol/crypto/attr/attr_support.go create mode 100644 accesscontrol/crypto/attr/attr_support_test.go create mode 100644 accesscontrol/crypto/attr/test_resources/prek0.dump create mode 100644 accesscontrol/crypto/attr/test_resources/tcert.dump create mode 100644 accesscontrol/crypto/attr/test_resources/tcert_bad.dump create mode 100644 accesscontrol/crypto/attr/test_resources/tcert_clear.dump create mode 100644 accesscontrol/crypto/crypto.go create mode 100644 accesscontrol/crypto/ecdsa/ecdsa.go create mode 100644 accesscontrol/crypto/ecdsa/ecdsa_test.go create mode 100644 accesscontrol/crypto/ecdsa/hash.go create mode 100644 accesscontrol/crypto/ecdsa/x509.go diff --git a/accesscontrol/api.go b/accesscontrol/api.go new file mode 100644 index 00000000000..7af80306569 --- /dev/null +++ b/accesscontrol/api.go @@ -0,0 +1,16 @@ +package accesscontrol + +// Attribute defines a name, value pair to be verified. +type Attribute struct { + Name string + Value []byte +} + +// AttributesManager can be used to verify and read attributes. +type AttributesManager interface { + ReadCertAttribute(attributeName string) ([]byte, error) + + VerifyAttribute(attributeName string, attributeValue []byte) (bool, error) + + VerifyAttributes(attrs ...*Attribute) (bool, error) +} diff --git a/accesscontrol/crypto/attr/attr_support.go b/accesscontrol/crypto/attr/attr_support.go new file mode 100644 index 00000000000..343411609c4 --- /dev/null +++ b/accesscontrol/crypto/attr/attr_support.go @@ -0,0 +1,209 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package attr + +import ( + "bytes" + "crypto/x509" + "errors" + + "github.com/hyperledger/fabric/accesscontrol" + "github.com/hyperledger/fabric/core/crypto/attributes" + "github.com/hyperledger/fabric/core/crypto/primitives" +) + +// chaincodeHolder is the struct that hold the certificate and the metadata. An implementation is ChaincodeStub +type chaincodeHolder interface { + // GetCallerCertificate returns caller certificate + GetCallerCertificate() ([]byte, error) + + // GetCallerMetadata returns caller metadata + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + GetCallerMetadata() ([]byte, error) + */ +} + +//AttributesHandler is an entity can be used to both verify and read attributes. +// 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 +// if you need multiple access create a hanlder is better: +// Multiple accesses +// 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. +// Example: +// +// AttributesHandler, err := ac.NewAttributesHandlerImpl(stub) +// if err != nil { +// return false, err +// } +// AttributesHandler.VerifyAttribute(attributeName, attributeValue) +// ... you can make other verifications and/or read attribute values by using the AttributesHandler +type AttributesHandler interface { + + //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 + // Example: + // containsAttrs, error:= handler.VerifyAttributes(&ac.Attribute{"position", "Software Engineer"}, &ac.Attribute{"company", "ACompany"}) + VerifyAttributes(attrs ...*accesscontrol.Attribute) (bool, error) + + //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. + //Example: + // containsAttr, error := handler.VerifyAttribute("position", "Software Engineer") + VerifyAttribute(attributeName string, attributeValue []byte) (bool, error) + + //GetValue is used to read an specific attribute from the transaction certificate, *attributeName* is passed as input parameter to this function. + // Example: + // attrValue,error:=handler.GetValue("position") + GetValue(attributeName string) ([]byte, error) +} + +//AttributesHandlerImpl is an implementation of AttributesHandler interface. +type AttributesHandlerImpl struct { + cert *x509.Certificate + cache map[string][]byte + keys map[string][]byte + header map[string]int + encrypted bool +} + +type chaincodeHolderImpl struct { + Certificate []byte +} + +// GetCallerCertificate returns caller certificate +func (holderImpl *chaincodeHolderImpl) GetCallerCertificate() ([]byte, error) { + return holderImpl.Certificate, nil +} + +//GetValueFrom returns the value of 'attributeName0' from a cert. +func GetValueFrom(attributeName string, cert []byte) ([]byte, error) { + handler, err := NewAttributesHandlerImpl(&chaincodeHolderImpl{Certificate: cert}) + if err != nil { + return nil, err + } + return handler.GetValue(attributeName) +} + +//NewAttributesHandlerImpl creates a new AttributesHandlerImpl from a pb.ChaincodeSecurityContext object. +func NewAttributesHandlerImpl(holder chaincodeHolder) (*AttributesHandlerImpl, error) { + // Getting certificate + certRaw, err := holder.GetCallerCertificate() + if err != nil { + return nil, err + } + if certRaw == nil { + return nil, errors.New("The certificate can't be nil.") + } + var tcert *x509.Certificate + tcert, err = primitives.DERToX509Certificate(certRaw) + if err != nil { + return nil, err + } + + keys := make(map[string][]byte) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + + //Getting Attributes Metadata from security context. + var attrsMetadata *attributespb.AttributesMetadata + var rawMetadata []byte + rawMetadata, err = holder.GetCallerMetadata() + if err != nil { + return nil, err + } + + if rawMetadata != nil { + attrsMetadata, err = attributes.GetAttributesMetadata(rawMetadata) + if err == nil { + for _, entry := range attrsMetadata.Entries { + keys[entry.AttributeName] = entry.AttributeKey + } + } + }*/ + + cache := make(map[string][]byte) + return &AttributesHandlerImpl{tcert, cache, keys, nil, false}, nil +} + +func (attributesHandler *AttributesHandlerImpl) readHeader() (map[string]int, bool, error) { + if attributesHandler.header != nil { + return attributesHandler.header, attributesHandler.encrypted, nil + } + header, encrypted, err := attributes.ReadAttributeHeader(attributesHandler.cert, attributesHandler.keys[attributes.HeaderAttributeName]) + if err != nil { + return nil, false, err + } + attributesHandler.header = header + attributesHandler.encrypted = encrypted + return header, encrypted, nil +} + +//GetValue is used to read an specific attribute from the transaction certificate, *attributeName* is passed as input parameter to this function. +// Example: +// attrValue,error:=handler.GetValue("position") +func (attributesHandler *AttributesHandlerImpl) GetValue(attributeName string) ([]byte, error) { + if attributesHandler.cache[attributeName] != nil { + return attributesHandler.cache[attributeName], nil + } + header, encrypted, err := attributesHandler.readHeader() + if err != nil { + return nil, err + } + value, err := attributes.ReadTCertAttributeByPosition(attributesHandler.cert, header[attributeName]) + if err != nil { + return nil, errors.New("Error reading attribute value '" + err.Error() + "'") + } + + if encrypted { + if attributesHandler.keys[attributeName] == nil { + return nil, errors.New("Cannot find decryption key for attribute") + } + + value, err = attributes.DecryptAttributeValue(attributesHandler.keys[attributeName], value) + if err != nil { + return nil, errors.New("Error decrypting value '" + err.Error() + "'") + } + } + attributesHandler.cache[attributeName] = value + return value, nil +} + +//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. +// Example: +// containsAttr, error := handler.VerifyAttribute("position", "Software Engineer") +func (attributesHandler *AttributesHandlerImpl) VerifyAttribute(attributeName string, attributeValue []byte) (bool, error) { + valueHash, err := attributesHandler.GetValue(attributeName) + if err != nil { + return false, err + } + return bytes.Compare(valueHash, attributeValue) == 0, nil +} + +//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 +// Example: +// containsAttrs, error:= handler.VerifyAttributes(&ac.Attribute{"position", "Software Engineer"}, &ac.Attribute{"company", "ACompany"}) +func (attributesHandler *AttributesHandlerImpl) VerifyAttributes(attrs ...*accesscontrol.Attribute) (bool, error) { + for _, attribute := range attrs { + val, err := attributesHandler.VerifyAttribute(attribute.Name, attribute.Value) + if err != nil { + return false, err + } + if !val { + return val, nil + } + } + return true, nil +} diff --git a/accesscontrol/crypto/attr/attr_support_test.go b/accesscontrol/crypto/attr/attr_support_test.go new file mode 100644 index 00000000000..268b2dfbfa1 --- /dev/null +++ b/accesscontrol/crypto/attr/attr_support_test.go @@ -0,0 +1,682 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package attr + +import ( + "bytes" + "crypto/x509" + "encoding/pem" + "errors" + "io/ioutil" + "testing" + + "github.com/hyperledger/fabric/accesscontrol" + "github.com/hyperledger/fabric/core/crypto/primitives" +) + +var ( + attributeNames = []string{"company", "position"} +) + +type chaincodeStubMock struct { + callerCert []byte + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata []byte + */ +} + +// GetCallerCertificate returns caller certificate +func (shim *chaincodeStubMock) GetCallerCertificate() ([]byte, error) { + return shim.callerCert, nil +} + +/* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. +// GetCallerMetadata returns caller metadata +func (shim *chaincodeStubMock) GetCallerMetadata() ([]byte, error) { + return shim.metadata, nil +} +*/ + +type certErrorMock struct { + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata []byte + */ +} + +// GetCallerCertificate returns caller certificate +func (shim *certErrorMock) GetCallerCertificate() ([]byte, error) { + return nil, errors.New("GetCallerCertificate error") +} + +/* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. +// GetCallerMetadata returns caller metadata +func (shim *certErrorMock) GetCallerMetadata() ([]byte, error) { + return shim.metadata, nil +}*/ + +type metadataErrorMock struct { + callerCert []byte +} + +// GetCallerCertificate returns caller certificate +func (shim *metadataErrorMock) GetCallerCertificate() ([]byte, error) { + return shim.callerCert, nil +} + +/* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. +// GetCallerMetadata returns caller metadata +func (shim *metadataErrorMock) GetCallerMetadata() ([]byte, error) { + return nil, errors.New("GetCallerCertificate error") +}*/ + +func TestVerifyAttribute(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32, 64} + + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + isOk, err := handler.VerifyAttribute("position", []byte("Software Engineer")) + if err != nil { + t.Error(err) + } + + if !isOk { + t.Fatal("Attribute not verified.") + } +} + +/* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. +func TestVerifyAttribute_InvalidAttributeMetadata(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + tcert, _, err := loadTCertAndPreK0() + if err != nil { + t.Error(err) + } + + tcertder := tcert.Raw + + attributeMetadata := []byte{123, 22, 34, 56, 78, 44} + + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + keySize := len(handler.keys) + if keySize != 0 { + t.Errorf("Test failed expected [%v] keys but found [%v]", keySize, 0) + } +}*/ + +func TestNewAttributesHandlerImpl_CertificateError(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + metadata := []byte{32, 64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &certErrorMock{metadata: attributeMetadata}*/ + stub := &certErrorMock{} + _, err := NewAttributesHandlerImpl(stub) + if err == nil { + t.Fatal("Error shouldn't be nil") + } +} + +/* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. +func TestNewAttributesHandlerImpl_MetadataError(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + tcert, _, err := loadTCertAndPreK0() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + if err != nil { + t.Error(err) + } + stub := &metadataErrorMock{callerCert: tcertder} + _, err = NewAttributesHandlerImpl(stub) + if err == nil { + t.Fatal("Error shouldn't be nil") + } +}*/ + +func TestNewAttributesHandlerImpl_InvalidCertificate(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + tcert, _, err := loadTCertAndPreK0() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + if err != nil { + t.Error(err) + } + tcertder[0] = tcertder[0] + 1 + stub := &metadataErrorMock{callerCert: tcertder} + _, err = NewAttributesHandlerImpl(stub) + if err == nil { + t.Fatal("Error shouldn't be nil") + } +} + +func TestNewAttributesHandlerImpl_NullCertificate(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + metadata := []byte{32, 64} + tcertder := tcert.Raw + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: nil, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: nil} + _, err := NewAttributesHandlerImpl(stub) + if err == nil { + t.Fatal("Error can't be nil.") + } +} + +/* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. +func TestNewAttributesHandlerImpl_NullMetadata(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + tcert, _, err := loadTCertAndPreK0() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: nil} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + keySize := len(handler.keys) + if keySize != 0 { + t.Errorf("Test failed expected [%v] keys but found [%v]", keySize, 0) + } +}*/ + +func TestVerifyAttributes(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32,64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata} */ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + isOk, err := handler.VerifyAttributes(&accesscontrol.Attribute{Name: "position", Value: []byte("Software Engineer")}) + if err != nil { + t.Error(err) + } + + if !isOk { + t.Fatal("Attribute not verified.") + } +} + +func TestVerifyAttributes_Invalid(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32,64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + isOk, err := handler.VerifyAttributes(&accesscontrol.Attribute{Name: "position", Value: []byte("Software Engineer")}, &accesscontrol.Attribute{Name: "position", Value: []byte("18")}) + if err != nil { + t.Error(err) + } + + if isOk { + t.Fatal("Attribute position=18 should have failed") + } +} + +func TestVerifyAttributes_InvalidHeader(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + + //Change header extensions + tcert.Raw[583] = tcert.Raw[583] + 124 + + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32,64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + _, err = handler.VerifyAttributes(&accesscontrol.Attribute{Name: "position", Value: []byte("Software Engineer")}) + if err == nil { + t.Fatal("Error can't be nil.") + } +} + +func TestVerifyAttributes_InvalidAttributeValue(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + + //Change header extensions + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. 337 is the offset in encrypted tcert. + tcert.Raw[371] = tcert.Raw[371] + 124*/ + tcert.Raw[558] = tcert.Raw[558] + 124 + + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32,64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata} */ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Fatalf("Error creating attribute handlder %v", err) + } + + v, err := handler.GetValue("position") + if err == nil { + t.Fatal("Error can't be nil." + string(v)) + } +} + +func TestVerifyAttributes_Null(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32,64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + isOk, err := handler.VerifyAttribute("position", nil) + if err != nil { + t.Error(err) + } + + if isOk { + t.Fatal("Attribute null is ok.") + } +} + +func TestGetValue(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32, 64} + + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + value, err := handler.GetValue("position") + if err != nil { + t.Error(err) + } + + if bytes.Compare(value, []byte("Software Engineer")) != 0 { + t.Fatalf("Value expected was [%v] and result was [%v].", []byte("Software Engineer"), value) + } + + //Second time read from cache. + value, err = handler.GetValue("position") + if err != nil { + t.Error(err) + } + + if bytes.Compare(value, []byte("Software Engineer")) != 0 { + t.Fatalf("Value expected was [%v] and result was [%v].", []byte("Software Engineer"), value) + } +} + +func TestGetValue_Clear(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + value, err := GetValueFrom("position", tcertder) + if err != nil { + t.Error(err) + } + + if bytes.Compare(value, []byte("Software Engineer")) != 0 { + t.Fatalf("Value expected was [%v] and result was [%v].", []byte("Software Engineer"), value) + } + + //Second time read from cache. + value, err = GetValueFrom("position", tcertder) + if err != nil { + t.Error(err) + } + + if bytes.Compare(value, []byte("Software Engineer")) != 0 { + t.Fatalf("Value expected was [%v] and result was [%v].", []byte("Software Engineer"), value) + } +} + +func TestGetValue_BadHeaderTCert(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + tcert, err := loadTCertFromFile("./test_resources/tcert_bad.dump") + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + _, err = GetValueFrom("position", tcertder) + if err == nil { + t.Fatal("Test should be fail due TCert has an invalid header.") + } +} + +func TestGetValue_Clear_NullTCert(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + _, err := GetValueFrom("position", nil) + if err == nil { + t.Error(err) + } +} + +func TestGetValue_InvalidAttribute(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32, 64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + _, err = handler.GetValue("age") + if err == nil { + t.Error(err) + } + + //Force invalid key + handler.keys["position"] = nil + _, err = handler.GetValue("positions") + if err == nil { + t.Error(err) + } +} + +func TestGetValue_Clear_InvalidAttribute(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32, 64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + value, err := handler.GetValue("age") + if value != nil || err == nil { + t.Fatalf("Test should fail [%v] \n", string(value)) + } +} + +func TestGetValue_InvalidAttribute_ValidAttribute(t *testing.T) { + primitives.SetSecurityLevel("SHA3", 256) + + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + tcert, prek0, err := loadTCertAndPreK0() */ + tcert, err := loadTCertClear() + if err != nil { + t.Error(err) + } + tcertder := tcert.Raw + /* + TODO: ##attributes-keys-pending This code have be redefined to avoid use of metadata field. + metadata := []byte{32, 64} + attributeMetadata, err := attributes.CreateAttributesMetadata(tcertder, metadata, prek0, attributeNames) + if err != nil { + t.Error(err) + } + stub := &chaincodeStubMock{callerCert: tcertder, metadata: attributeMetadata}*/ + stub := &chaincodeStubMock{callerCert: tcertder} + handler, err := NewAttributesHandlerImpl(stub) + if err != nil { + t.Error(err) + } + + _, err = handler.GetValue("age") + if err == nil { + t.Error(err) + } + + //Second time read a valid attribute from the TCert. + value, err := handler.GetValue("position") + if err != nil { + t.Error(err) + } + + if bytes.Compare(value, []byte("Software Engineer")) != 0 { + t.Fatalf("Value expected was [%v] and result was [%v].", []byte("Software Engineer"), value) + } +} + +func loadTCertFromFile(filepath string) (*x509.Certificate, error) { + tcertRaw, err := ioutil.ReadFile(filepath) + if err != nil { + return nil, err + } + + tcertDecoded, _ := pem.Decode(tcertRaw) + + tcert, err := x509.ParseCertificate(tcertDecoded.Bytes) + if err != nil { + return nil, err + } + + return tcert, nil +} + +func loadTCertAndPreK0() (*x509.Certificate, []byte, error) { + preKey0, err := ioutil.ReadFile("./test_resources/prek0.dump") + if err != nil { + return nil, nil, err + } + + if err != nil { + return nil, nil, err + } + + tcert, err := loadTCertFromFile("./test_resources/tcert.dump") + if err != nil { + return nil, nil, err + } + + return tcert, preKey0, nil +} + +func loadTCertClear() (*x509.Certificate, error) { + return loadTCertFromFile("./test_resources/tcert_clear.dump") +} diff --git a/accesscontrol/crypto/attr/test_resources/prek0.dump b/accesscontrol/crypto/attr/test_resources/prek0.dump new file mode 100644 index 00000000000..442dfea6ca2 --- /dev/null +++ b/accesscontrol/crypto/attr/test_resources/prek0.dump @@ -0,0 +1 @@ +ýA>ø0`ñËÕ›=)»á*¨®­g&V'ù aÅàkâJ \ No newline at end of file diff --git a/accesscontrol/crypto/attr/test_resources/tcert.dump b/accesscontrol/crypto/attr/test_resources/tcert.dump new file mode 100644 index 00000000000..95c9862125f --- /dev/null +++ b/accesscontrol/crypto/attr/test_resources/tcert.dump @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC2TCCAn+gAwIBAgIQBq019NJETm+JnM9pUFY5fDAKBggqhkjOPQQDAzAxMQsw +CQYDVQQGEwJVUzEUMBIGA1UEChMLSHlwZXJsZWRnZXIxDDAKBgNVBAMTA3RjYTAe +Fw0xNjA1MjYxODU4MjBaFw0xNjA4MjQxODU4MjBaMDMxCzAJBgNVBAYTAlVTMRQw +EgYDVQQKEwtIeXBlcmxlZGdlcjEOMAwGA1UEAxMFZGllZ28wWTATBgcqhkjOPQIB +BggqhkjOPQMBBwNCAARv37sk17/Yq6Ata16fj1CacV3uvYzCwgWx2hearwfEBbEh ++lfmQXYUEu7pcaEaPh+9dNVEeqyHWGqFu2mo5tufo4IBdTCCAXEwDgYDVR0PAQH/ +BAQDAgeAMAwGA1UdEwEB/wQCMAAwDQYDVR0OBAYEBAECAwQwDwYDVR0jBAgwBoAE +AQIDBDBKBgYqAwQFBgoEQLb0qP6OU62xQQewx5PhpJu9cnLp54+aOpSptE78GNyd +vh7xNtSHD1GTouEK2RFx1YwJZHAM7OS48JTDZoPr1L4wTQYGKgMEBQYHAQH/BEDv +kl2JEP0f8OQRch84Hd3o3oGJbOrUBA5eYP0TaQLzpbGop4Z3Uun2Iyllfhixr+Gq +2Xv1vuSDsbNDpObuQthJMEoGBioDBAUGCARALLtd0x7G/yc2WSSo6ag0nntWayud +kaIW7NOJiWGJaOFtP+fufzIUPzYvBAuQIk3nYeOLBH/948ZyKsJQWW/LtzBKBgYq +AwQFBgkEQAXgSabQSC5xHa/YXQi7nlStN81eiG/VhGfTeLvkHXPMDcULAGyKHtax +l2IaAap9QetXi6pkN78lO048IhFTFCswCgYIKoZIzj0EAwMDSAAwRQIhAMSY4g4E +hWh7Ey4sOpPYfJwfM82nZHboLEUzrWFwuZ+KAiBf2V0OoXPt2I2MaV1+2OQIaHcJ +BF8oB65Ox67VENMNUg== +-----END CERTIFICATE----- diff --git a/accesscontrol/crypto/attr/test_resources/tcert_bad.dump b/accesscontrol/crypto/attr/test_resources/tcert_bad.dump new file mode 100644 index 00000000000..ac61d3bdfa2 --- /dev/null +++ b/accesscontrol/crypto/attr/test_resources/tcert_bad.dump @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICoDCCAkagAwIBAgIRALdvx2997k0el4M6q7FoSYswCgYIKoZIzj0EAwMwMTEL +MAkGA1UEBhMCVVMxFDASBgNVBAoTC0h5cGVybGVkZ2VyMQwwCgYDVQQDEwN0Y2Ew +HhcNMTYwNjExMDI1NzIzWhcNMTYwOTA5MDI1NzIzWjAzMQswCQYDVQQGEwJVUzEU +MBIGA1UEChMLSHlwZXJsZWRnZXIxDjAMBgNVBAMTBWRpZWdvMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAETkdTO8tIQhNbm4k01RUIRV+vfqV7cCiEe/he209CoL9w +ykpkNpLWDvuuaPngwiQ3XoBpR5KkV11WLEkm6YgO/KOCATswggE3MA4GA1UdDwEB +/wQEAwIHgDAMBgNVHRMBAf8EAjAAMA0GA1UdDgQGBAQBAgMEMA8GA1UdIwQIMAaA +BAECAwQwGwYGKgMEBQYKBBFTb2Z0d2FyZSBFbmdpbmVlcjASBgYqAwQFBgsECEFD +b21wYW55ME0GBioDBAUGBwEB/wRA3Fw686SYs3vBtSGe+NhpnLjJMXNDgTrYO8qi +Q4gFvNvPZvrU+QDgBnzS/YRUSP8FS/d8NA3ur5QWyafuFeRatzBKBgYqAwQFBggE +QIb+dQuwRhrYXRvJmpVDcZMacvQtPJYRX/rI0SwC9mcylgUhypfs7bbXleskX4cW +Oi/WC2ntOW9MN4g2usDrCOMwKwYGKgMEBQYJBCEwMEhFQURwb3NpdGlvbi0+MTAw +I2NvbXBhbnktPjEwMCMwCgYIKoZIzj0EAwMDSAAwRQIhANtfRCq+wkaSDfhpASA6 +0oyUcMQWSyVaOvMfWnmRJAJAAiBcnczAputMeGMWbHdpI2aVR7yn4o+MqRVzEBy3 +odOIQw== +-----END CERTIFICATE----- diff --git a/accesscontrol/crypto/attr/test_resources/tcert_clear.dump b/accesscontrol/crypto/attr/test_resources/tcert_clear.dump new file mode 100644 index 00000000000..2c39b6df4a4 --- /dev/null +++ b/accesscontrol/crypto/attr/test_resources/tcert_clear.dump @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICnDCCAkGgAwIBAgIQDeV68dFWTbaf9Z5CElzSPjAKBggqhkjOPQQDAzAxMQsw +CQYDVQQGEwJVUzEUMBIGA1UEChMLSHlwZXJsZWRnZXIxDDAKBgNVBAMTA3RjYTAe +Fw0xNjA2MTEwMTIwNDlaFw0xNjA5MDkwMTIwNDlaMDMxCzAJBgNVBAYTAlVTMRQw +EgYDVQQKEwtIeXBlcmxlZGdlcjEOMAwGA1UEAxMFZGllZ28wWTATBgcqhkjOPQIB +BggqhkjOPQMBBwNCAAT8PV1TuE63bFhpDpStyT1oi1sQBg1mcqgAZ8VKiHdyqE/j +tihuHuMJv8fEDLB56GwfTZNGAO0NJOykou3QVLBTo4IBNzCCATMwDgYDVR0PAQH/ +BAQDAgeAMAwGA1UdEwEB/wQCMAAwDQYDVR0OBAYEBAECAwQwDwYDVR0jBAgwBoAE +AQIDBDAbBgYqAwQFBgoEEVNvZnR3YXJlIEVuZ2luZWVyMBIGBioDBAUGCwQIQUNv +bXBhbnkwTQYGKgMEBQYHAQH/BECHkB85vxvL+vE5aGVvbclE6A8hthYo15KSARz/ +ZF5wc2JJfHIMs+M4MV00kExRitvVsOXVxYqMGHZcsyzT56jaMEoGBioDBAUGCARA +9DXfVKvsohk/E4J1UUxeELM1EMhCeTpkOFPs0mLUytGyQlL9Wuj7SAKHF3GP3Pkj +AX9wZaw26RrNYRTIa0azwTAnBgYqAwQFBgkEHTAwSEVBRHBvc2l0aW9uLT4xI2Nv +bXBhbnktPjIjMAoGCCqGSM49BAMDA0kAMEYCIQCw/3c2dA3KEU9jfGkPbwYxX1UK +BuQzK2hmoD+CUEGtpgIhAPW+4/+IL+6A367zTuqpI//6e75pSdj43Wn2rKuhSbF9 +-----END CERTIFICATE----- diff --git a/accesscontrol/crypto/crypto.go b/accesscontrol/crypto/crypto.go new file mode 100644 index 00000000000..4fb850bde06 --- /dev/null +++ b/accesscontrol/crypto/crypto.go @@ -0,0 +1,24 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package crypto + +// SignatureVerifier verifies signatures +type SignatureVerifier interface { + + // Verify verifies signature sig against verification key vk and message msg. + Verify(vk, sig, msg []byte) (bool, error) +} diff --git a/accesscontrol/crypto/ecdsa/ecdsa.go b/accesscontrol/crypto/ecdsa/ecdsa.go new file mode 100644 index 00000000000..a862867f124 --- /dev/null +++ b/accesscontrol/crypto/ecdsa/ecdsa.go @@ -0,0 +1,67 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ecdsa + +import ( + "crypto/ecdsa" + "encoding/asn1" + "math/big" + + "github.com/hyperledger/fabric/core/chaincode/shim/crypto" +) + +type x509ECDSASignatureVerifierImpl struct { +} + +// ECDSASignature represents an ECDSA signature +type ECDSASignature struct { + R, S *big.Int +} + +func (sv *x509ECDSASignatureVerifierImpl) Verify(certificate, signature, message []byte) (bool, error) { + // Interpret vk as an x509 certificate + cert, err := derToX509Certificate(certificate) + if err != nil { + return false, err + } + + // TODO: verify certificate + + // Interpret signature as an ECDSA signature + vk := cert.PublicKey.(*ecdsa.PublicKey) + + return sv.verifyImpl(vk, signature, message) +} + +func (sv *x509ECDSASignatureVerifierImpl) verifyImpl(vk *ecdsa.PublicKey, signature, message []byte) (bool, error) { + ecdsaSignature := new(ECDSASignature) + _, err := asn1.Unmarshal(signature, ecdsaSignature) + if err != nil { + return false, err + } + + h, err := computeHash(message, vk.Params().BitSize) + if err != nil { + return false, err + } + + return ecdsa.Verify(vk, h, ecdsaSignature.R, ecdsaSignature.S), nil +} + +func NewX509ECDSASignatureVerifier() crypto.SignatureVerifier { + return &x509ECDSASignatureVerifierImpl{} +} diff --git a/accesscontrol/crypto/ecdsa/ecdsa_test.go b/accesscontrol/crypto/ecdsa/ecdsa_test.go new file mode 100644 index 00000000000..008367ea1f6 --- /dev/null +++ b/accesscontrol/crypto/ecdsa/ecdsa_test.go @@ -0,0 +1,191 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ecdsa + +import ( + "testing" + + "github.com/hyperledger/fabric/core/crypto/primitives" +) + +func TestSignatureVerifier(t *testing.T) { + // Create a signature + primitives.SetSecurityLevel("SHA3", 256) + + cert, key, err := primitives.NewSelfSignedCert() + if err != nil { + t.Fatal(err) + } + + message := []byte("Hello World!") + signature, err := primitives.ECDSASign(key, message) + if err != nil { + t.Fatal(err) + } + + // Instantiate a new SignatureVerifier + sv := NewX509ECDSASignatureVerifier() + + // Verify the signature + ok, err := sv.Verify(cert, signature, message) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("Signature does not verify") + } +} + +func TestSignatureVerifierSHA2(t *testing.T) { + // Create a signature + primitives.SetSecurityLevel("SHA2", 256) + + cert, key, err := primitives.NewSelfSignedCert() + if err != nil { + t.Fatal(err) + } + + message := []byte("Hello World!") + signature, err := primitives.ECDSASign(key, message) + if err != nil { + t.Fatal(err) + } + + // Instantiate a new SignatureVerifier + sv := NewX509ECDSASignatureVerifier() + + // Verify the signature + ok, err := sv.Verify(cert, signature, message) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("Signature does not verify") + } +} + +func TestSignatureVerifierSHA2_384(t *testing.T) { + // Create a signature + primitives.SetSecurityLevel("SHA2", 384) + + cert, key, err := primitives.NewSelfSignedCert() + if err != nil { + t.Fatal(err) + } + + message := []byte("Hello World!") + signature, err := primitives.ECDSASign(key, message) + if err != nil { + t.Fatal(err) + } + + // Instantiate a new SignatureVerifier + sv := NewX509ECDSASignatureVerifier() + + // Verify the signature + ok, err := sv.Verify(cert, signature, message) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("Signature does not verify") + } +} + +func TestSignatureVerifierSHA3_384(t *testing.T) { + // Create a signature + primitives.SetSecurityLevel("SHA3", 384) + + cert, key, err := primitives.NewSelfSignedCert() + if err != nil { + t.Fatal(err) + } + + message := []byte("Hello World!") + signature, err := primitives.ECDSASign(key, message) + if err != nil { + t.Fatal(err) + } + + // Instantiate a new SignatureVerifier + sv := NewX509ECDSASignatureVerifier() + + // Verify the signature + ok, err := sv.Verify(cert, signature, message) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("Signature does not verify") + } +} + +func TestSignatureVerifierSHA2_512(t *testing.T) { + // Create a signature + primitives.SetSecurityLevel("SHA2", 512) + + cert, key, err := primitives.NewSelfSignedCert() + if err != nil { + t.Fatal(err) + } + + message := []byte("Hello World!") + signature, err := primitives.ECDSASign(key, message) + if err != nil { + t.Fatal(err) + } + + // Instantiate a new SignatureVerifier + sv := NewX509ECDSASignatureVerifier() + + // Verify the signature + ok, err := sv.Verify(cert, signature, message) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("Signature does not verify") + } +} + +func TestSignatureVerifierSHA3_512(t *testing.T) { + // Create a signature + primitives.SetSecurityLevel("SHA3", 512) + + cert, key, err := primitives.NewSelfSignedCert() + if err != nil { + t.Fatal(err) + } + + message := []byte("Hello World!") + signature, err := primitives.ECDSASign(key, message) + if err != nil { + t.Fatal(err) + } + + // Instantiate a new SignatureVerifier + sv := NewX509ECDSASignatureVerifier() + + // Verify the signature + ok, err := sv.Verify(cert, signature, message) + if err != nil { + t.Fatal(err) + } + if !ok { + t.Fatal("Signature does not verify") + } +} diff --git a/accesscontrol/crypto/ecdsa/hash.go b/accesscontrol/crypto/ecdsa/hash.go new file mode 100644 index 00000000000..6317cad7c5c --- /dev/null +++ b/accesscontrol/crypto/ecdsa/hash.go @@ -0,0 +1,82 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ecdsa + +import ( + "crypto/sha256" + "crypto/sha512" + "fmt" + "hash" + + "golang.org/x/crypto/sha3" + + "github.com/hyperledger/fabric/core/crypto/primitives" +) + +func getHashSHA2(bitsize int) (hash.Hash, error) { + switch bitsize { + case 224: + return sha256.New224(), nil + case 256: + return sha256.New(), nil + case 384: + return sha512.New384(), nil + case 512: + return sha512.New(), nil + case 521: + return sha512.New(), nil + default: + return nil, fmt.Errorf("Invalid bitsize. It was [%d]. Expected [224, 256, 384, 512, 521]", bitsize) + } +} + +func getHashSHA3(bitsize int) (hash.Hash, error) { + switch bitsize { + case 224: + return sha3.New224(), nil + case 256: + return sha3.New256(), nil + case 384: + return sha3.New384(), nil + case 512: + return sha3.New512(), nil + case 521: + return sha3.New512(), nil + default: + return nil, fmt.Errorf("Invalid bitsize. It was [%d]. Expected [224, 256, 384, 512, 521]", bitsize) + } +} + +func computeHash(msg []byte, bitsize int) ([]byte, error) { + var hash hash.Hash + var err error + switch primitives.GetHashAlgorithm() { + case "SHA2": + hash, err = getHashSHA2(bitsize) + case "SHA3": + hash, err = getHashSHA3(bitsize) + default: + return nil, fmt.Errorf("Invalid hash algorithm " + primitives.GetHashAlgorithm()) + } + + if err != nil { + return nil, err + } + + hash.Write(msg) + return hash.Sum(nil), nil +} diff --git a/accesscontrol/crypto/ecdsa/x509.go b/accesscontrol/crypto/ecdsa/x509.go new file mode 100644 index 00000000000..d65f0cc6fee --- /dev/null +++ b/accesscontrol/crypto/ecdsa/x509.go @@ -0,0 +1,25 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ecdsa + +import ( + "crypto/x509" +) + +func derToX509Certificate(asn1Data []byte) (*x509.Certificate, error) { + return x509.ParseCertificate(asn1Data) +}