github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/bccsp/sw/keys.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package sw
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"crypto/x509"
    14  	"encoding/asn1"
    15  	"encoding/pem"
    16  	"errors"
    17  	"fmt"
    18  )
    19  
    20  type pkcs8Info struct {
    21  	Version             int
    22  	PrivateKeyAlgorithm []asn1.ObjectIdentifier
    23  	PrivateKey          []byte
    24  }
    25  
    26  type ecPrivateKey struct {
    27  	Version       int
    28  	PrivateKey    []byte
    29  	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
    30  	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
    31  }
    32  
    33  var (
    34  	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
    35  	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
    36  	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
    37  	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
    38  )
    39  
    40  var oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
    41  
    42  func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
    43  	switch curve {
    44  	case elliptic.P224():
    45  		return oidNamedCurveP224, true
    46  	case elliptic.P256():
    47  		return oidNamedCurveP256, true
    48  	case elliptic.P384():
    49  		return oidNamedCurveP384, true
    50  	case elliptic.P521():
    51  		return oidNamedCurveP521, true
    52  	}
    53  	return nil, false
    54  }
    55  
    56  func privateKeyToDER(privateKey *ecdsa.PrivateKey) ([]byte, error) {
    57  	if privateKey == nil {
    58  		return nil, errors.New("invalid ecdsa private key. It must be different from nil")
    59  	}
    60  
    61  	return x509.MarshalECPrivateKey(privateKey)
    62  }
    63  
    64  func privateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
    65  	// Validate inputs
    66  	if len(pwd) != 0 {
    67  		return privateKeyToEncryptedPEM(privateKey, pwd)
    68  	}
    69  	if privateKey == nil {
    70  		return nil, errors.New("invalid key. It must be different from nil")
    71  	}
    72  
    73  	switch k := privateKey.(type) {
    74  	case *ecdsa.PrivateKey:
    75  		if k == nil {
    76  			return nil, errors.New("invalid ecdsa private key. It must be different from nil")
    77  		}
    78  
    79  		// get the oid for the curve
    80  		oidNamedCurve, ok := oidFromNamedCurve(k.Curve)
    81  		if !ok {
    82  			return nil, errors.New("unknown elliptic curve")
    83  		}
    84  
    85  		// based on https://golang.org/src/crypto/x509/sec1.go
    86  		privateKeyBytes := k.D.Bytes()
    87  		paddedPrivateKey := make([]byte, (k.Curve.Params().N.BitLen()+7)/8)
    88  		copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
    89  		// omit NamedCurveOID for compatibility as it's optional
    90  		asn1Bytes, err := asn1.Marshal(ecPrivateKey{
    91  			Version:    1,
    92  			PrivateKey: paddedPrivateKey,
    93  			PublicKey:  asn1.BitString{Bytes: elliptic.Marshal(k.Curve, k.X, k.Y)},
    94  		})
    95  
    96  		if err != nil {
    97  			return nil, fmt.Errorf("error marshaling EC key to asn1: [%s]", err)
    98  		}
    99  
   100  		var pkcs8Key pkcs8Info
   101  		pkcs8Key.Version = 0
   102  		pkcs8Key.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 2)
   103  		pkcs8Key.PrivateKeyAlgorithm[0] = oidPublicKeyECDSA
   104  		pkcs8Key.PrivateKeyAlgorithm[1] = oidNamedCurve
   105  		pkcs8Key.PrivateKey = asn1Bytes
   106  
   107  		pkcs8Bytes, err := asn1.Marshal(pkcs8Key)
   108  		if err != nil {
   109  			return nil, fmt.Errorf("error marshaling EC key to asn1: [%s]", err)
   110  		}
   111  		return pem.EncodeToMemory(
   112  			&pem.Block{
   113  				Type:  "PRIVATE KEY",
   114  				Bytes: pkcs8Bytes,
   115  			},
   116  		), nil
   117  
   118  	default:
   119  		return nil, errors.New("invalid key type. It must be *ecdsa.PrivateKey")
   120  	}
   121  }
   122  
   123  func privateKeyToEncryptedPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
   124  	if privateKey == nil {
   125  		return nil, errors.New("invalid private key. It must be different from nil")
   126  	}
   127  
   128  	switch k := privateKey.(type) {
   129  	case *ecdsa.PrivateKey:
   130  		if k == nil {
   131  			return nil, errors.New("invalid ecdsa private key. It must be different from nil")
   132  		}
   133  		raw, err := x509.MarshalECPrivateKey(k)
   134  
   135  		if err != nil {
   136  			return nil, err
   137  		}
   138  
   139  		block, err := x509.EncryptPEMBlock(
   140  			rand.Reader,
   141  			"PRIVATE KEY",
   142  			raw,
   143  			pwd,
   144  			x509.PEMCipherAES256)
   145  
   146  		if err != nil {
   147  			return nil, err
   148  		}
   149  
   150  		return pem.EncodeToMemory(block), nil
   151  
   152  	default:
   153  		return nil, errors.New("invalid key type. It must be *ecdsa.PrivateKey")
   154  	}
   155  }
   156  
   157  func derToPrivateKey(der []byte) (key interface{}, err error) {
   158  
   159  	if key, err = x509.ParsePKCS1PrivateKey(der); err == nil {
   160  		return key, nil
   161  	}
   162  
   163  	if key, err = x509.ParsePKCS8PrivateKey(der); err == nil {
   164  		switch key.(type) {
   165  		case *ecdsa.PrivateKey:
   166  			return
   167  		default:
   168  			return nil, errors.New("found unknown private key type in PKCS#8 wrapping")
   169  		}
   170  	}
   171  
   172  	if key, err = x509.ParseECPrivateKey(der); err == nil {
   173  		return
   174  	}
   175  
   176  	return nil, errors.New("invalid key type. The DER must contain an ecdsa.PrivateKey")
   177  }
   178  
   179  func pemToPrivateKey(raw []byte, pwd []byte) (interface{}, error) {
   180  	block, _ := pem.Decode(raw)
   181  	if block == nil {
   182  		return nil, fmt.Errorf("failed decoding PEM. Block must be different from nil [% x]", raw)
   183  	}
   184  
   185  	// TODO: derive from header the type of the key
   186  
   187  	if x509.IsEncryptedPEMBlock(block) {
   188  		if len(pwd) == 0 {
   189  			return nil, errors.New("encrypted Key. Need a password")
   190  		}
   191  
   192  		decrypted, err := x509.DecryptPEMBlock(block, pwd)
   193  		if err != nil {
   194  			return nil, fmt.Errorf("failed PEM decryption: [%s]", err)
   195  		}
   196  
   197  		key, err := derToPrivateKey(decrypted)
   198  		if err != nil {
   199  			return nil, err
   200  		}
   201  		return key, err
   202  	}
   203  
   204  	cert, err := derToPrivateKey(block.Bytes)
   205  	if err != nil {
   206  		return nil, err
   207  	}
   208  	return cert, err
   209  }
   210  
   211  func pemToAES(raw []byte, pwd []byte) ([]byte, error) {
   212  	if len(raw) == 0 {
   213  		return nil, errors.New("invalid PEM. It must be different from nil")
   214  	}
   215  	block, _ := pem.Decode(raw)
   216  	if block == nil {
   217  		return nil, fmt.Errorf("failed decoding PEM. Block must be different from nil [% x]", raw)
   218  	}
   219  
   220  	if x509.IsEncryptedPEMBlock(block) {
   221  		if len(pwd) == 0 {
   222  			return nil, errors.New("encrypted Key. Password must be different fom nil")
   223  		}
   224  
   225  		decrypted, err := x509.DecryptPEMBlock(block, pwd)
   226  		if err != nil {
   227  			return nil, fmt.Errorf("failed PEM decryption: [%s]", err)
   228  		}
   229  		return decrypted, nil
   230  	}
   231  
   232  	return block.Bytes, nil
   233  }
   234  
   235  func aesToPEM(raw []byte) []byte {
   236  	return pem.EncodeToMemory(&pem.Block{Type: "AES PRIVATE KEY", Bytes: raw})
   237  }
   238  
   239  func aesToEncryptedPEM(raw []byte, pwd []byte) ([]byte, error) {
   240  	if len(raw) == 0 {
   241  		return nil, errors.New("invalid aes key. It must be different from nil")
   242  	}
   243  	if len(pwd) == 0 {
   244  		return aesToPEM(raw), nil
   245  	}
   246  
   247  	block, err := x509.EncryptPEMBlock(
   248  		rand.Reader,
   249  		"AES PRIVATE KEY",
   250  		raw,
   251  		pwd,
   252  		x509.PEMCipherAES256)
   253  
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  
   258  	return pem.EncodeToMemory(block), nil
   259  }
   260  
   261  func publicKeyToPEM(publicKey interface{}, pwd []byte) ([]byte, error) {
   262  	if len(pwd) != 0 {
   263  		return publicKeyToEncryptedPEM(publicKey, pwd)
   264  	}
   265  
   266  	if publicKey == nil {
   267  		return nil, errors.New("invalid public key. It must be different from nil")
   268  	}
   269  
   270  	switch k := publicKey.(type) {
   271  	case *ecdsa.PublicKey:
   272  		if k == nil {
   273  			return nil, errors.New("invalid ecdsa public key. It must be different from nil")
   274  		}
   275  		PubASN1, err := x509.MarshalPKIXPublicKey(k)
   276  		if err != nil {
   277  			return nil, err
   278  		}
   279  
   280  		return pem.EncodeToMemory(
   281  			&pem.Block{
   282  				Type:  "PUBLIC KEY",
   283  				Bytes: PubASN1,
   284  			},
   285  		), nil
   286  
   287  	default:
   288  		return nil, errors.New("invalid key type. It must be *ecdsa.PublicKey")
   289  	}
   290  }
   291  
   292  func publicKeyToEncryptedPEM(publicKey interface{}, pwd []byte) ([]byte, error) {
   293  	switch k := publicKey.(type) {
   294  	case *ecdsa.PublicKey:
   295  		if k == nil {
   296  			return nil, errors.New("invalid ecdsa public key. It must be different from nil")
   297  		}
   298  		raw, err := x509.MarshalPKIXPublicKey(k)
   299  		if err != nil {
   300  			return nil, err
   301  		}
   302  
   303  		block, err := x509.EncryptPEMBlock(
   304  			rand.Reader,
   305  			"PUBLIC KEY",
   306  			raw,
   307  			pwd,
   308  			x509.PEMCipherAES256)
   309  
   310  		if err != nil {
   311  			return nil, err
   312  		}
   313  
   314  		return pem.EncodeToMemory(block), nil
   315  	default:
   316  		return nil, errors.New("invalid key type. It must be *ecdsa.PublicKey")
   317  	}
   318  }
   319  
   320  func pemToPublicKey(raw []byte, pwd []byte) (interface{}, error) {
   321  	if len(raw) == 0 {
   322  		return nil, errors.New("invalid PEM. It must be different from nil")
   323  	}
   324  	block, _ := pem.Decode(raw)
   325  	if block == nil {
   326  		return nil, fmt.Errorf("failed decoding. Block must be different from nil [% x]", raw)
   327  	}
   328  
   329  	// TODO: derive from header the type of the key
   330  	if x509.IsEncryptedPEMBlock(block) {
   331  		if len(pwd) == 0 {
   332  			return nil, errors.New("encrypted Key. Password must be different from nil")
   333  		}
   334  
   335  		decrypted, err := x509.DecryptPEMBlock(block, pwd)
   336  		if err != nil {
   337  			return nil, fmt.Errorf("failed PEM decryption: [%s]", err)
   338  		}
   339  
   340  		key, err := derToPublicKey(decrypted)
   341  		if err != nil {
   342  			return nil, err
   343  		}
   344  		return key, err
   345  	}
   346  
   347  	cert, err := derToPublicKey(block.Bytes)
   348  	if err != nil {
   349  		return nil, err
   350  	}
   351  	return cert, err
   352  }
   353  
   354  func derToPublicKey(raw []byte) (pub interface{}, err error) {
   355  	if len(raw) == 0 {
   356  		return nil, errors.New("invalid DER. It must be different from nil")
   357  	}
   358  
   359  	key, err := x509.ParsePKIXPublicKey(raw)
   360  
   361  	return key, err
   362  }