github.com/Hnampk/my-fabric@v0.0.0-20201028083322-75069da399c0/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  }