github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/msp/cert.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package msp 8 9 import ( 10 "bytes" 11 "crypto/ecdsa" 12 "crypto/x509" 13 "crypto/x509/pkix" 14 "encoding/asn1" 15 "encoding/pem" 16 "errors" 17 "fmt" 18 "math/big" 19 "time" 20 21 "github.com/hyperledger/fabric/bccsp/sw" 22 ) 23 24 type dsaSignature struct { 25 R, S *big.Int 26 } 27 28 type ecdsaSignature dsaSignature 29 30 type validity struct { 31 NotBefore, NotAfter time.Time 32 } 33 34 type publicKeyInfo struct { 35 Raw asn1.RawContent 36 Algorithm pkix.AlgorithmIdentifier 37 PublicKey asn1.BitString 38 } 39 40 type certificate struct { 41 Raw asn1.RawContent 42 TBSCertificate tbsCertificate 43 SignatureAlgorithm pkix.AlgorithmIdentifier 44 SignatureValue asn1.BitString 45 } 46 47 type tbsCertificate struct { 48 Raw asn1.RawContent 49 Version int `asn1:"optional,explicit,default:0,tag:0"` 50 SerialNumber *big.Int 51 SignatureAlgorithm pkix.AlgorithmIdentifier 52 Issuer asn1.RawValue 53 Validity validity 54 Subject asn1.RawValue 55 PublicKey publicKeyInfo 56 UniqueId asn1.BitString `asn1:"optional,tag:1"` 57 SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"` 58 Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"` 59 } 60 61 func isECDSASignedCert(cert *x509.Certificate) bool { 62 return cert.SignatureAlgorithm == x509.ECDSAWithSHA1 || 63 cert.SignatureAlgorithm == x509.ECDSAWithSHA256 || 64 cert.SignatureAlgorithm == x509.ECDSAWithSHA384 || 65 cert.SignatureAlgorithm == x509.ECDSAWithSHA512 66 } 67 68 // sanitizeECDSASignedCert checks that the signatures signing a cert 69 // is in low-S. This is checked against the public key of parentCert. 70 // If the signature is not in low-S, then a new certificate is generated 71 // that is equals to cert but the signature that is in low-S. 72 func sanitizeECDSASignedCert(cert *x509.Certificate, parentCert *x509.Certificate) (*x509.Certificate, error) { 73 if cert == nil { 74 return nil, errors.New("Certificate must be different from nil.") 75 } 76 if parentCert == nil { 77 return nil, errors.New("Parent certificate must be different from nil.") 78 } 79 80 expectedSig, err := sw.SignatureToLowS(parentCert.PublicKey.(*ecdsa.PublicKey), cert.Signature) 81 if err != nil { 82 return nil, err 83 } 84 85 // if sig == cert.Signature, nothing needs to be done 86 if bytes.Equal(cert.Signature, expectedSig) { 87 return cert, nil 88 } 89 // otherwise create a new certificate with the new signature 90 91 // 1. Unmarshal cert.Raw to get an instance of certificate, 92 // the lower level interface that represent an x509 certificate 93 // encoding 94 var newCert certificate 95 newCert, err = certFromX509Cert(cert) 96 if err != nil { 97 return nil, err 98 } 99 100 // 2. Change the signature 101 newCert.SignatureValue = asn1.BitString{Bytes: expectedSig, BitLength: len(expectedSig) * 8} 102 103 // 3. marshal again newCert. Raw must be nil 104 newCert.Raw = nil 105 newRaw, err := asn1.Marshal(newCert) 106 if err != nil { 107 return nil, err 108 } 109 110 // 4. parse newRaw to get an x509 certificate 111 return x509.ParseCertificate(newRaw) 112 } 113 114 func certFromX509Cert(cert *x509.Certificate) (certificate, error) { 115 var newCert certificate 116 _, err := asn1.Unmarshal(cert.Raw, &newCert) 117 if err != nil { 118 return certificate{}, err 119 } 120 return newCert, nil 121 } 122 123 // String returns a PEM representation of a certificate 124 func (c certificate) String() string { 125 b, err := asn1.Marshal(c) 126 if err != nil { 127 return fmt.Sprintf("Failed marshaling cert: %v", err) 128 } 129 block := &pem.Block{ 130 Bytes: b, 131 Type: "CERTIFICATE", 132 } 133 b = pem.EncodeToMemory(block) 134 return string(b) 135 } 136 137 // certToPEM converts the given x509.Certificate to a PEM 138 // encoded string 139 func certToPEM(certificate *x509.Certificate) string { 140 cert, err := certFromX509Cert(certificate) 141 if err != nil { 142 mspIdentityLogger.Warning("Failed converting certificate to asn1", err) 143 return "" 144 } 145 return cert.String() 146 }