gitee.com/lh-her-team/common@v1.5.1/helper/libp2pcrypto/key.go (about)

     1  // Package crypto implements various cryptographic utilities used by libp2p.
     2  // This includes a Public and Private key interface and key implementations
     3  // for supported key algorithms.
     4  package libp2pcrypto
     5  
     6  // nolint: gosec
     7  import (
     8  	"crypto/elliptic"
     9  	"crypto/hmac"
    10  	"crypto/rand"
    11  	"crypto/sha1"
    12  	"crypto/sha512"
    13  	"crypto/subtle"
    14  	"encoding/base64"
    15  	"errors"
    16  	"fmt"
    17  	"hash"
    18  	"io"
    19  
    20  	"gitee.com/lh-her-team/common/helper/libp2pcrypto/pb"
    21  
    22  	"github.com/gogo/protobuf/proto"
    23  	sha256 "github.com/minio/sha256-simd"
    24  )
    25  
    26  const (
    27  	// RSA is an enum for the supported RSA key type
    28  	RSA = iota
    29  	// Ed25519 is an enum for the supported Ed25519 key type
    30  	Ed25519
    31  	// Secp256k1 is an enum for the supported Secp256k1 key type
    32  	Secp256k1
    33  	// ECDSA is an enum for the supported ECDSA key type
    34  	ECDSA
    35  	// SM2 is an enum for the supported SM2 key type
    36  	SM2
    37  )
    38  
    39  var (
    40  	// ErrBadKeyType is returned when a key is not supported
    41  	ErrBadKeyType = errors.New("invalid or unsupported key type")
    42  	// KeyTypes is a list of supported keys
    43  	KeyTypes = []int{
    44  		RSA,
    45  		Ed25519,
    46  		Secp256k1,
    47  		ECDSA,
    48  		SM2,
    49  	}
    50  )
    51  
    52  // PubKeyUnmarshaller is a func that creates a PubKey from a given slice of bytes
    53  type PubKeyUnmarshaller func(data []byte) (PubKey, error)
    54  
    55  // PrivKeyUnmarshaller is a func that creates a PrivKey from a given slice of bytes
    56  type PrivKeyUnmarshaller func(data []byte) (PrivKey, error)
    57  
    58  // PubKeyUnmarshallers is a map of unmarshallers by key type
    59  var PubKeyUnmarshallers = map[pb.KeyType]PubKeyUnmarshaller{
    60  	pb.KeyType_RSA:       UnmarshalRsaPublicKey,
    61  	pb.KeyType_Ed25519:   UnmarshalEd25519PublicKey,
    62  	pb.KeyType_Secp256k1: UnmarshalSecp256k1PublicKey,
    63  	pb.KeyType_ECDSA:     UnmarshalECDSAPublicKey,
    64  	pb.KeyType_SM2:       UnmarshalSM2PublicKey,
    65  }
    66  
    67  // PrivKeyUnmarshallers is a map of unmarshallers by key type
    68  var PrivKeyUnmarshallers = map[pb.KeyType]PrivKeyUnmarshaller{
    69  	pb.KeyType_RSA:       UnmarshalRsaPrivateKey,
    70  	pb.KeyType_Ed25519:   UnmarshalEd25519PrivateKey,
    71  	pb.KeyType_Secp256k1: UnmarshalSecp256k1PrivateKey,
    72  	pb.KeyType_ECDSA:     UnmarshalECDSAPrivateKey,
    73  	pb.KeyType_SM2:       UnmarshalSM2PrivateKey,
    74  }
    75  
    76  // Key represents a crypto key that can be compared to another key
    77  type Key interface {
    78  	// Bytes returns a serialized, storeable representation of this key
    79  	// DEPRECATED in favor of Marshal / Unmarshal
    80  	Bytes() ([]byte, error)
    81  	// Equals checks whether two PubKeys are the same
    82  	Equals(Key) bool
    83  	// Raw returns the raw bytes of the key (not wrapped in the
    84  	// libp2p-crypto protobuf).
    85  	//
    86  	// This function is the inverse of {Priv,Pub}KeyUnmarshaler.
    87  	Raw() ([]byte, error)
    88  	// Type returns the protobof key type.
    89  	Type() pb.KeyType
    90  }
    91  
    92  // PrivKey represents a private key that can be used to generate a public key and sign data
    93  type PrivKey interface {
    94  	Key
    95  	// Cryptographically sign the given bytes
    96  	Sign([]byte) ([]byte, error)
    97  	// Return a public key paired with this private key
    98  	GetPublic() PubKey
    99  }
   100  
   101  // PubKey is a public key that can be used to verifiy data signed with the corresponding private key
   102  type PubKey interface {
   103  	Key
   104  	// Verify that 'sig' is the signed hash of 'data'
   105  	Verify(data []byte, sig []byte) (bool, error)
   106  }
   107  
   108  // GenSharedKey generates the shared key from a given private key
   109  type GenSharedKey func([]byte) ([]byte, error)
   110  
   111  // GenerateKeyPair generates a private and public key
   112  func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
   113  	return GenerateKeyPairWithReader(typ, bits, rand.Reader)
   114  }
   115  
   116  // GenerateKeyPairWithReader returns a keypair of the given type and bitsize
   117  func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) {
   118  	switch typ {
   119  	case RSA:
   120  		return GenerateRSAKeyPair(bits, src)
   121  	case Ed25519:
   122  		return GenerateEd25519Key(src)
   123  	case Secp256k1:
   124  		return GenerateSecp256k1Key(src)
   125  	case ECDSA:
   126  		return GenerateECDSAKeyPair(src)
   127  	default:
   128  		return nil, nil, ErrBadKeyType
   129  	}
   130  }
   131  
   132  // GenerateEKeyPair returns an ephemeral public key and returns a function that will compute
   133  // the shared secret key.  Used in the identify module.
   134  //
   135  // Focuses only on ECDH now, but can be made more general in the future.
   136  func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) {
   137  	var curve elliptic.Curve
   138  	switch curveName {
   139  	case "P-256":
   140  		curve = elliptic.P256()
   141  	case "P-384":
   142  		curve = elliptic.P384()
   143  	case "P-521":
   144  		curve = elliptic.P521()
   145  	default:
   146  		return nil, nil, fmt.Errorf("unknown curve name")
   147  	}
   148  	priv, x, y, err := elliptic.GenerateKey(curve, rand.Reader)
   149  	if err != nil {
   150  		return nil, nil, err
   151  	}
   152  	pubKey := elliptic.Marshal(curve, x, y)
   153  	done := func(theirPub []byte) ([]byte, error) {
   154  		// Verify and unpack node's public key.
   155  		x, y := elliptic.Unmarshal(curve, theirPub)
   156  		if x == nil {
   157  			return nil, fmt.Errorf("malformed public key: %d %v", len(theirPub), theirPub)
   158  		}
   159  		if !curve.IsOnCurve(x, y) {
   160  			return nil, errors.New("invalid public key")
   161  		}
   162  		// Generate shared secret.
   163  		secret, _ := curve.ScalarMult(x, y, priv)
   164  		return secret.Bytes(), nil
   165  	}
   166  	return pubKey, done, nil
   167  }
   168  
   169  // StretchedKeys ...
   170  type StretchedKeys struct {
   171  	IV        []byte
   172  	MacKey    []byte
   173  	CipherKey []byte
   174  }
   175  
   176  // PENDING DEPRECATION:  KeyStretcher() will be deprecated with secio; for new
   177  // code, please use PBKDF2 (golang.org/x/crypto/pbkdf2) instead.
   178  // KeyStretcher returns a set of keys for each party by stretching the shared key.
   179  // (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey).
   180  // This function accepts the following cipher types:
   181  // - AES-128
   182  // - AES-256
   183  // The function will panic upon receiving an unknown cipherType
   184  func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) {
   185  	var cipherKeySize int
   186  	var ivSize int
   187  	switch cipherType {
   188  	case "AES-128":
   189  		ivSize = 16
   190  		cipherKeySize = 16
   191  	case "AES-256":
   192  		ivSize = 16
   193  		cipherKeySize = 32
   194  	default:
   195  		panic("Unrecognized cipher, programmer error?")
   196  	}
   197  	hmacKeySize := 20
   198  	seed := []byte("key expansion")
   199  	result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize))
   200  	var h func() hash.Hash
   201  	switch hashType {
   202  	case "SHA1":
   203  		h = sha1.New
   204  	case "SHA256":
   205  		h = sha256.New
   206  	case "SHA512":
   207  		h = sha512.New
   208  	default:
   209  		panic("Unrecognized hash function, programmer error?")
   210  	}
   211  	m := hmac.New(h, secret)
   212  	// note: guaranteed to never return an error
   213  	m.Write(seed)
   214  	a := m.Sum(nil)
   215  	j := 0
   216  	for j < len(result) {
   217  		m.Reset()
   218  		// note: guaranteed to never return an error.
   219  		m.Write(a)
   220  		m.Write(seed)
   221  		b := m.Sum(nil)
   222  		todo := len(b)
   223  		if j+todo > len(result) {
   224  			todo = len(result) - j
   225  		}
   226  		copy(result[j:j+todo], b)
   227  		j += todo
   228  		m.Reset()
   229  		// note: guaranteed to never return an error.
   230  		m.Write(a)
   231  		a = m.Sum(nil)
   232  	}
   233  	half := len(result) / 2
   234  	r1 := result[:half]
   235  	r2 := result[half:]
   236  	var k1 StretchedKeys
   237  	var k2 StretchedKeys
   238  	k1.IV = r1[0:ivSize]
   239  	k1.CipherKey = r1[ivSize : ivSize+cipherKeySize]
   240  	k1.MacKey = r1[ivSize+cipherKeySize:]
   241  	k2.IV = r2[0:ivSize]
   242  	k2.CipherKey = r2[ivSize : ivSize+cipherKeySize]
   243  	k2.MacKey = r2[ivSize+cipherKeySize:]
   244  	return k1, k2
   245  }
   246  
   247  // UnmarshalPublicKey converts a protobuf serialized public key into its
   248  // representative object
   249  func UnmarshalPublicKey(data []byte) (PubKey, error) {
   250  	pmes := new(pb.PublicKey)
   251  	err := proto.Unmarshal(data, pmes)
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  	return PublicKeyFromProto(pmes)
   256  }
   257  
   258  // PublicKeyFromProto converts an unserialized protobuf PublicKey message
   259  // into its representative object.
   260  func PublicKeyFromProto(pmes *pb.PublicKey) (PubKey, error) {
   261  	um, ok := PubKeyUnmarshallers[pmes.GetType()]
   262  	if !ok {
   263  		return nil, ErrBadKeyType
   264  	}
   265  	data := pmes.GetData()
   266  	pk, err := um(data)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  	switch tpk := pk.(type) {
   271  	case *RsaPublicKey:
   272  		tpk.cached, _ = pmes.Marshal()
   273  	}
   274  	return pk, nil
   275  }
   276  
   277  // MarshalPublicKey converts a public key object into a protobuf serialized
   278  // public key
   279  func MarshalPublicKey(k PubKey) ([]byte, error) {
   280  	pbmes, err := PublicKeyToProto(k)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	return proto.Marshal(pbmes)
   285  }
   286  
   287  // PublicKeyToProto converts a public key object into an unserialized
   288  // protobuf PublicKey message.
   289  func PublicKeyToProto(k PubKey) (*pb.PublicKey, error) {
   290  	pbmes := new(pb.PublicKey)
   291  	pbmes.Type = k.Type()
   292  	data, err := k.Raw()
   293  	if err != nil {
   294  		return nil, err
   295  	}
   296  	pbmes.Data = data
   297  	return pbmes, nil
   298  }
   299  
   300  // UnmarshalPrivateKey converts a protobuf serialized private key into its
   301  // representative object
   302  func UnmarshalPrivateKey(data []byte) (PrivKey, error) {
   303  	pmes := new(pb.PrivateKey)
   304  	err := proto.Unmarshal(data, pmes)
   305  	if err != nil {
   306  		return nil, err
   307  	}
   308  	um, ok := PrivKeyUnmarshallers[pmes.GetType()]
   309  	if !ok {
   310  		return nil, ErrBadKeyType
   311  	}
   312  	return um(pmes.GetData())
   313  }
   314  
   315  // MarshalPrivateKey converts a key object into its protobuf serialized form.
   316  func MarshalPrivateKey(k PrivKey) ([]byte, error) {
   317  	pbmes := new(pb.PrivateKey)
   318  	pbmes.Type = k.Type()
   319  	data, err := k.Raw()
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  	pbmes.Data = data
   324  	return proto.Marshal(pbmes)
   325  }
   326  
   327  // ConfigDecodeKey decodes from b64 (for config file) to a byte array that can be unmarshalled.
   328  func ConfigDecodeKey(b string) ([]byte, error) {
   329  	return base64.StdEncoding.DecodeString(b)
   330  }
   331  
   332  // ConfigEncodeKey encodes a marshalled key to b64 (for config file).
   333  func ConfigEncodeKey(b []byte) string {
   334  	return base64.StdEncoding.EncodeToString(b)
   335  }
   336  
   337  // KeyEqual checks whether two Keys are equivalent (have identical byte representations).
   338  func KeyEqual(k1, k2 Key) bool {
   339  	if k1 == k2 {
   340  		return true
   341  	}
   342  
   343  	return k1.Equals(k2)
   344  }
   345  
   346  func basicEquals(k1, k2 Key) bool {
   347  	if k1.Type() != k2.Type() {
   348  		return false
   349  	}
   350  	a, err := k1.Raw()
   351  	if err != nil {
   352  		return false
   353  	}
   354  	b, err := k2.Raw()
   355  	if err != nil {
   356  		return false
   357  	}
   358  	return subtle.ConstantTimeCompare(a, b) == 1
   359  }