github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/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 "math/big" 26 "time" 27 28 "errors" 29 30 "github.com/inklabsfoundation/inkchain/bccsp/sw" 31 ) 32 33 type dsaSignature struct { 34 R, S *big.Int 35 } 36 37 type ecdsaSignature dsaSignature 38 39 type validity struct { 40 NotBefore, NotAfter time.Time 41 } 42 43 type publicKeyInfo struct { 44 Raw asn1.RawContent 45 Algorithm pkix.AlgorithmIdentifier 46 PublicKey asn1.BitString 47 } 48 49 type certificate struct { 50 Raw asn1.RawContent 51 TBSCertificate tbsCertificate 52 SignatureAlgorithm pkix.AlgorithmIdentifier 53 SignatureValue asn1.BitString 54 } 55 56 type tbsCertificate struct { 57 Raw asn1.RawContent 58 Version int `asn1:"optional,explicit,default:0,tag:0"` 59 SerialNumber *big.Int 60 SignatureAlgorithm pkix.AlgorithmIdentifier 61 Issuer asn1.RawValue 62 Validity validity 63 Subject asn1.RawValue 64 PublicKey publicKeyInfo 65 UniqueId asn1.BitString `asn1:"optional,tag:1"` 66 SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"` 67 Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"` 68 } 69 70 func isECDSASignedCert(cert *x509.Certificate) bool { 71 return cert.SignatureAlgorithm == x509.ECDSAWithSHA1 || 72 cert.SignatureAlgorithm == x509.ECDSAWithSHA256 || 73 cert.SignatureAlgorithm == x509.ECDSAWithSHA384 || 74 cert.SignatureAlgorithm == x509.ECDSAWithSHA512 75 } 76 77 // sanitizeECDSASignedCert checks that the signatures signing a cert 78 // is in low-S. This is checked against the public key of parentCert. 79 // If the signature is not in low-S, then a new certificate is generated 80 // that is equals to cert but the signature that is in low-S. 81 func sanitizeECDSASignedCert(cert *x509.Certificate, parentCert *x509.Certificate) (*x509.Certificate, error) { 82 if cert == nil { 83 return nil, errors.New("Certificate must be different from nil.") 84 } 85 if parentCert == nil { 86 return nil, errors.New("Parent certificate must be different from nil.") 87 } 88 89 expectedSig, err := sw.SignatureToLowS(parentCert.PublicKey.(*ecdsa.PublicKey), cert.Signature) 90 if err != nil { 91 return nil, err 92 } 93 94 // if sig == cert.Signature, nothing needs to be done 95 if bytes.Equal(cert.Signature, expectedSig) { 96 return cert, nil 97 } 98 // otherwise create a new certificate with the new signature 99 100 // 1. Unmarshal cert.Raw to get an instance of certificate, 101 // the lower level interface that represent an x509 certificate 102 // encoding 103 var newCert certificate 104 _, err = asn1.Unmarshal(cert.Raw, &newCert) 105 if err != nil { 106 return nil, err 107 } 108 109 // 2. Change the signature 110 newCert.SignatureValue = asn1.BitString{Bytes: expectedSig, BitLength: len(expectedSig) * 8} 111 112 // 3. marshal again newCert. Raw must be nil 113 newCert.Raw = nil 114 newRaw, err := asn1.Marshal(newCert) 115 if err != nil { 116 return nil, err 117 } 118 119 // 4. parse newRaw to get an x509 certificate 120 return x509.ParseCertificate(newRaw) 121 }