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