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-----