From 5a65700cf173664f9ca27a29fb3ab9b1fd1e27d4 Mon Sep 17 00:00:00 2001 From: Angelo De Caro Date: Wed, 26 Jul 2017 12:14:32 +0800 Subject: [PATCH] [FAB-5350] Compute MSP-ID afert cert sanitisation This change-set does the following: - It enforces that the MSP Identity Identifier, whose value depends on the identity's certificate, is computed after certificate sanitisation. This way, we are sure that the ID is unique. Tests have been added. Change-Id: I67090be70625a9d0c3bd18a78fd8e16db89b0dae Signed-off-by: Angelo De Caro --- msp/identities.go | 26 ++++++-- msp/msp_test.go | 61 +++++++++++++++++++ msp/mspimpl.go | 51 +--------------- msp/testdata/mspid/admincerts/peer0-cert.pem | 13 ++++ .../mspid/cacerts/ca.example.com-cert.pem | 14 +++++ ...553e1f3ba12b141892d966617731380189d3f4e_sk | 5 ++ msp/testdata/mspid/signcerts/peer0-cert.pem | 13 ++++ .../mspid/tlscacerts/ca.example.com-cert.pem | 14 +++++ 8 files changed, 145 insertions(+), 52 deletions(-) create mode 100644 msp/testdata/mspid/admincerts/peer0-cert.pem create mode 100644 msp/testdata/mspid/cacerts/ca.example.com-cert.pem create mode 100755 msp/testdata/mspid/keystore/7c73fd300a90b41c79ace8ee5553e1f3ba12b141892d966617731380189d3f4e_sk create mode 100644 msp/testdata/mspid/signcerts/peer0-cert.pem create mode 100644 msp/testdata/mspid/tlscacerts/ca.example.com-cert.pem diff --git a/msp/identities.go b/msp/identities.go index dd11f49baa6..6033a445a54 100644 --- a/msp/identities.go +++ b/msp/identities.go @@ -48,14 +48,32 @@ type identity struct { msp *bccspmsp } -func newIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, msp *bccspmsp) (Identity, error) { - mspIdentityLogger.Debugf("Creating identity instance for ID %s", id) +func newIdentity(cert *x509.Certificate, pk bccsp.Key, msp *bccspmsp) (Identity, error) { + mspIdentityLogger.Debugf("Creating identity instance for cert %s", cert) // Sanitize first the certificate cert, err := msp.sanitizeCert(cert) if err != nil { return nil, err } + + // Compute identity identifier + + // Use the hash of the identity's certificate as id in the IdentityIdentifier + hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction) + if err != nil { + return nil, fmt.Errorf("Failed getting hash function options [%s]", err) + } + + digest, err := msp.bccsp.Hash(cert.Raw, hashOpt) + if err != nil { + return nil, fmt.Errorf("Failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err) + } + + id := &IdentityIdentifier{ + Mspid: msp.name, + Id: hex.EncodeToString(digest)} + return &identity{id: id, cert: cert, pk: pk, msp: msp}, nil } @@ -188,9 +206,9 @@ type signingidentity struct { signer crypto.Signer } -func newSigningIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, signer crypto.Signer, msp *bccspmsp) (SigningIdentity, error) { +func newSigningIdentity(cert *x509.Certificate, pk bccsp.Key, signer crypto.Signer, msp *bccspmsp) (SigningIdentity, error) { //mspIdentityLogger.Infof("Creating signing identity instance for ID %s", id) - mspId, err := newIdentity(id, cert, pk, msp) + mspId, err := newIdentity(cert, pk, msp) if err != nil { return nil, err } diff --git a/msp/msp_test.go b/msp/msp_test.go index 8df71fbb5c9..3f7a231f67e 100644 --- a/msp/msp_test.go +++ b/msp/msp_test.go @@ -17,6 +17,10 @@ limitations under the License. package msp import ( + "crypto/ecdsa" + "crypto/x509" + "encoding/hex" + "encoding/pem" "errors" "fmt" "os" @@ -933,3 +937,60 @@ func getLocalMSP(t *testing.T, dir string) MSP { return thisMSP } + +func TestMSPIdentityIdentifier(t *testing.T) { + // testdata/mspid + // 1) a key and a signcert (used to populate the default signing identity) with the cert having a HighS signature + thisMSP := getLocalMSP(t, "testdata/mspid") + + id, err := thisMSP.GetDefaultSigningIdentity() + assert.NoError(t, err) + err = id.Validate() + assert.NoError(t, err) + + // Check that the identity identifier is computed with the respect to the lowS signature + + idid := id.GetIdentifier() + assert.NotNil(t, idid) + + // Load and parse cacaert and signcert from folder + pems, err := getPemMaterialFromDir("testdata/mspid/cacerts") + assert.NoError(t, err) + bl, _ := pem.Decode(pems[0]) + assert.NotNil(t, bl) + caCertFromFile, err := x509.ParseCertificate(bl.Bytes) + assert.NoError(t, err) + + pems, err = getPemMaterialFromDir("testdata/mspid/signcerts") + assert.NoError(t, err) + bl, _ = pem.Decode(pems[0]) + assert.NotNil(t, bl) + certFromFile, err := x509.ParseCertificate(bl.Bytes) + assert.NoError(t, err) + // Check that the certificates' raws are different, meaning that the identity has been sanitised + assert.NotEqual(t, certFromFile.Raw, id.(*signingidentity).cert) + + // Check that certFromFile is in HighS + _, S, err := sw.UnmarshalECDSASignature(certFromFile.Signature) + assert.NoError(t, err) + lowS, err := sw.IsLowS(caCertFromFile.PublicKey.(*ecdsa.PublicKey), S) + assert.NoError(t, err) + assert.False(t, lowS) + + // Check that id.(*signingidentity).cert is in LoswS + _, S, err = sw.UnmarshalECDSASignature(id.(*signingidentity).cert.Signature) + assert.NoError(t, err) + lowS, err = sw.IsLowS(caCertFromFile.PublicKey.(*ecdsa.PublicKey), S) + assert.NoError(t, err) + assert.True(t, lowS) + + // Compute the digest for certFromFile + thisBCCSPMsp := thisMSP.(*bccspmsp) + hashOpt, err := bccsp.GetHashOpt(thisBCCSPMsp.cryptoConfig.IdentityIdentifierHashFunction) + assert.NoError(t, err) + digest, err := thisBCCSPMsp.bccsp.Hash(certFromFile.Raw, hashOpt) + assert.NoError(t, err) + + // Compare with the digest computed from the sanitised cert + assert.NotEqual(t, idid.Id, hex.EncodeToString(digest)) +} diff --git a/msp/mspimpl.go b/msp/mspimpl.go index 4781d5c9f2a..ec08aae4db3 100644 --- a/msp/mspimpl.go +++ b/msp/mspimpl.go @@ -117,22 +117,7 @@ func (msp *bccspmsp) getIdentityFromConf(idBytes []byte) (Identity, bccsp.Key, e // get the public key in the right format certPubK, err := msp.bccsp.KeyImport(cert, &bccsp.X509PublicKeyImportOpts{Temporary: true}) - // Use the hash of the identity's certificate as id in the IdentityIdentifier - hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction) - if err != nil { - return nil, nil, fmt.Errorf("getIdentityFromConf failed getting hash function options [%s]", err) - } - - digest, err := msp.bccsp.Hash(cert.Raw, hashOpt) - if err != nil { - return nil, nil, fmt.Errorf("getIdentityFromConf failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err) - } - - id := &IdentityIdentifier{ - Mspid: msp.name, - Id: hex.EncodeToString(digest)} - - mspId, err := newIdentity(id, cert, certPubK, msp) + mspId, err := newIdentity(cert, certPubK, msp) if err != nil { return nil, nil, err } @@ -173,22 +158,7 @@ func (msp *bccspmsp) getSigningIdentityFromConf(sidInfo *m.SigningIdentityInfo) return nil, fmt.Errorf("getIdentityFromBytes error: Failed initializing bccspCryptoSigner, err %s", err) } - // Use the hash of the identity's certificate as id in the IdentityIdentifier - hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction) - if err != nil { - return nil, fmt.Errorf("getIdentityFromBytes failed getting hash function options [%s]", err) - } - - digest, err := msp.bccsp.Hash(idPub.(*identity).cert.Raw, hashOpt) - if err != nil { - return nil, fmt.Errorf("Failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err) - } - - id := &IdentityIdentifier{ - Mspid: msp.name, - Id: hex.EncodeToString(digest)} - - return newSigningIdentity(id, idPub.(*identity).cert, idPub.(*identity).pk, peerSigner, msp) + return newSigningIdentity(idPub.(*identity).cert, idPub.(*identity).pk, peerSigner, msp) } /* @@ -439,27 +409,12 @@ func (msp *bccspmsp) deserializeIdentityInternal(serializedIdentity []byte) (Ide // We can't do it yet because there is no standardized way // (yet) to encode the MSP ID into the x.509 body of a cert - // Use the hash of the identity's certificate as id in the IdentityIdentifier - hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction) - if err != nil { - return nil, fmt.Errorf("Failed getting hash function options [%s]", err) - } - - digest, err := msp.bccsp.Hash(cert.Raw, hashOpt) - if err != nil { - return nil, fmt.Errorf("Failed hashing raw certificate to compute the id of the IdentityIdentifier [%s]", err) - } - - id := &IdentityIdentifier{ - Mspid: msp.name, - Id: hex.EncodeToString(digest)} - pub, err := msp.bccsp.KeyImport(cert, &bccsp.X509PublicKeyImportOpts{Temporary: true}) if err != nil { return nil, fmt.Errorf("Failed to import certitifacate's public key [%s]", err) } - return newIdentity(id, cert, pub, msp) + return newIdentity(cert, pub, msp) } // SatisfiesPrincipal returns null if the identity matches the principal or an error otherwise diff --git a/msp/testdata/mspid/admincerts/peer0-cert.pem b/msp/testdata/mspid/admincerts/peer0-cert.pem new file mode 100644 index 00000000000..cd4aa723c86 --- /dev/null +++ b/msp/testdata/mspid/admincerts/peer0-cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB/zCCAaWgAwIBAgIRAKaex32sim4PQR6kDPEPVnwwCgYIKoZIzj0EAwIwaTEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt +cGxlLmNvbTAeFw0xNzA3MjYwNDM1MDJaFw0yNzA3MjQwNDM1MDJaMEoxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMQ4wDAYDVQQDEwVwZWVyMDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPzs +BSdIIB0GrKmKWn0N8mMfxWs2s1D6K+xvTvVJ3wUj3znNBxj+k2j2tpPuJUExt61s +KbpP3GF9/crEahpXXRajTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA +MCsGA1UdIwQkMCKAIEvLfQX685pz+rh2q5yCA7e0a/a5IGDuJVHRWfp++HThMAoG +CCqGSM49BAMCA0gAMEUCIH5H9W3tsCrti6tsN9UfY1eeTKtExf/abXhfqfVeRChk +AiEA0GxTPOXVHo0gJpMbHc9B73TL5ZfDhujoDyjb8DToWPQ= +-----END CERTIFICATE----- diff --git a/msp/testdata/mspid/cacerts/ca.example.com-cert.pem b/msp/testdata/mspid/cacerts/ca.example.com-cert.pem new file mode 100644 index 00000000000..cc8869c9b57 --- /dev/null +++ b/msp/testdata/mspid/cacerts/ca.example.com-cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMDCCAdagAwIBAgIRANSZuFNkGJoaE5SrI6DW43wwCgYIKoZIzj0EAwIwaTEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt +cGxlLmNvbTAeFw0xNzA3MjYwNDM1MDJaFw0yNzA3MjQwNDM1MDJaMGkxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEXMBUGA1UEAxMOY2EuZXhhbXBsZS5j +b20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQEuWtLHAvuPjAXo4P6BNHsD+HF +8Ly3ZlKwI4XAl39RPgoqb/zEKx4kNII4jTEvure9x8SFPwnZIAgfWMix3sgPo18w +XTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTAD +AQH/MCkGA1UdDgQiBCBLy30F+vOac/q4dqucggO3tGv2uSBg7iVR0Vn6fvh04TAK +BggqhkjOPQQDAgNIADBFAiBrFIVo3QTOqxc8ojUkK5JDtwF+u+FX1k72WbNazxJf +uAIhAO3JrGN3lwrLrADY1l+A/imYum/0xynPAUPuBG+5TI1/ +-----END CERTIFICATE----- diff --git a/msp/testdata/mspid/keystore/7c73fd300a90b41c79ace8ee5553e1f3ba12b141892d966617731380189d3f4e_sk b/msp/testdata/mspid/keystore/7c73fd300a90b41c79ace8ee5553e1f3ba12b141892d966617731380189d3f4e_sk new file mode 100755 index 00000000000..a71e011ca59 --- /dev/null +++ b/msp/testdata/mspid/keystore/7c73fd300a90b41c79ace8ee5553e1f3ba12b141892d966617731380189d3f4e_sk @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyA3kupzpQJ5OKG2+ +dVb3d01tHlqO0rlDcrkxXa3a5ZqhRANCAAT87AUnSCAdBqypilp9DfJjH8VrNrNQ ++ivsb071Sd8FI985zQcY/pNo9raT7iVBMbetbCm6T9xhff3KxGoaV10W +-----END PRIVATE KEY----- diff --git a/msp/testdata/mspid/signcerts/peer0-cert.pem b/msp/testdata/mspid/signcerts/peer0-cert.pem new file mode 100644 index 00000000000..cd4aa723c86 --- /dev/null +++ b/msp/testdata/mspid/signcerts/peer0-cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB/zCCAaWgAwIBAgIRAKaex32sim4PQR6kDPEPVnwwCgYIKoZIzj0EAwIwaTEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG +cmFuY2lzY28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFt +cGxlLmNvbTAeFw0xNzA3MjYwNDM1MDJaFw0yNzA3MjQwNDM1MDJaMEoxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMQ4wDAYDVQQDEwVwZWVyMDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPzs +BSdIIB0GrKmKWn0N8mMfxWs2s1D6K+xvTvVJ3wUj3znNBxj+k2j2tpPuJUExt61s +KbpP3GF9/crEahpXXRajTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA +MCsGA1UdIwQkMCKAIEvLfQX685pz+rh2q5yCA7e0a/a5IGDuJVHRWfp++HThMAoG +CCqGSM49BAMCA0gAMEUCIH5H9W3tsCrti6tsN9UfY1eeTKtExf/abXhfqfVeRChk +AiEA0GxTPOXVHo0gJpMbHc9B73TL5ZfDhujoDyjb8DToWPQ= +-----END CERTIFICATE----- diff --git a/msp/testdata/mspid/tlscacerts/ca.example.com-cert.pem b/msp/testdata/mspid/tlscacerts/ca.example.com-cert.pem new file mode 100644 index 00000000000..d845df38255 --- /dev/null +++ b/msp/testdata/mspid/tlscacerts/ca.example.com-cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICMDCCAdWgAwIBAgIQWoNSU41CWlCJJTrXFyzzKzAKBggqhkjOPQQDAjBpMQsw +CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy +YW5jaXNjbzEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1w +bGUuY29tMB4XDTE3MDcyNjA0MzUwMloXDTI3MDcyNDA0MzUwMlowaTELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lz +Y28xFDASBgNVBAoTC2V4YW1wbGUuY29tMRcwFQYDVQQDEw5jYS5leGFtcGxlLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGBCZG9VRTIsWXlMBA7YQzYzuZHz +TaEvsGtcAtpdtpdvOTYa10Tm2EdUbfeadyYdIMTyMp9JnjHntm21+cORphWjXzBd +MA4GA1UdDwEB/wQEAwIBpjAPBgNVHSUECDAGBgRVHSUAMA8GA1UdEwEB/wQFMAMB +Af8wKQYDVR0OBCIEIDhvAhEY4NU7AI1PN8pJEp1s7WoWCjoJ/CgZ/loJ+rxYMAoG +CCqGSM49BAMCA0kAMEYCIQDGl5bN8g54ttrvkT0sSnZyCLFpPaaKjAfDR36FsB6k +oAIhAIKnO8mcocALwvao07Ll7FvLVQJp97+VU8/MwM3H44oL +-----END CERTIFICATE-----