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  }