mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 03:07:28 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			252 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package crypto implements various cryptographic utilities used by libp2p.
 | 
						|
// This includes a Public and Private key interface and key implementations
 | 
						|
// for supported key algorithms.
 | 
						|
package crypto
 | 
						|
 | 
						|
import (
 | 
						|
	"crypto/rand"
 | 
						|
	"crypto/subtle"
 | 
						|
	"encoding/base64"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
 | 
						|
	"github.com/libp2p/go-libp2p/core/crypto/pb"
 | 
						|
 | 
						|
	"google.golang.org/protobuf/proto"
 | 
						|
)
 | 
						|
 | 
						|
//go:generate protoc --go_out=. --go_opt=Mpb/crypto.proto=./pb pb/crypto.proto
 | 
						|
 | 
						|
const (
 | 
						|
	// RSA is an enum for the supported RSA key type
 | 
						|
	RSA = iota
 | 
						|
	// Ed25519 is an enum for the supported Ed25519 key type
 | 
						|
	Ed25519
 | 
						|
	// Secp256k1 is an enum for the supported Secp256k1 key type
 | 
						|
	Secp256k1
 | 
						|
	// ECDSA is an enum for the supported ECDSA key type
 | 
						|
	ECDSA
 | 
						|
	// Ed448 is an enum for the supported Ed448 key type
 | 
						|
	Ed448
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// ErrBadKeyType is returned when a key is not supported
 | 
						|
	ErrBadKeyType = errors.New("invalid or unsupported key type")
 | 
						|
	// KeyTypes is a list of supported keys
 | 
						|
	KeyTypes = []int{
 | 
						|
		RSA,
 | 
						|
		Ed25519,
 | 
						|
		Secp256k1,
 | 
						|
		ECDSA,
 | 
						|
		Ed448,
 | 
						|
	}
 | 
						|
)
 | 
						|
 | 
						|
// PubKeyUnmarshaller is a func that creates a PubKey from a given slice of bytes
 | 
						|
type PubKeyUnmarshaller func(data []byte) (PubKey, error)
 | 
						|
 | 
						|
// PrivKeyUnmarshaller is a func that creates a PrivKey from a given slice of bytes
 | 
						|
type PrivKeyUnmarshaller func(data []byte) (PrivKey, error)
 | 
						|
 | 
						|
// PubKeyUnmarshallers is a map of unmarshallers by key type
 | 
						|
var PubKeyUnmarshallers = map[pb.KeyType]PubKeyUnmarshaller{
 | 
						|
	pb.KeyType_RSA:       UnmarshalRsaPublicKey,
 | 
						|
	pb.KeyType_Ed25519:   UnmarshalEd25519PublicKey,
 | 
						|
	pb.KeyType_Secp256k1: UnmarshalSecp256k1PublicKey,
 | 
						|
	pb.KeyType_ECDSA:     UnmarshalECDSAPublicKey,
 | 
						|
	pb.KeyType_Ed448:     UnmarshalEd448PublicKey,
 | 
						|
}
 | 
						|
 | 
						|
// PrivKeyUnmarshallers is a map of unmarshallers by key type
 | 
						|
var PrivKeyUnmarshallers = map[pb.KeyType]PrivKeyUnmarshaller{
 | 
						|
	pb.KeyType_RSA:       UnmarshalRsaPrivateKey,
 | 
						|
	pb.KeyType_Ed25519:   UnmarshalEd25519PrivateKey,
 | 
						|
	pb.KeyType_Secp256k1: UnmarshalSecp256k1PrivateKey,
 | 
						|
	pb.KeyType_ECDSA:     UnmarshalECDSAPrivateKey,
 | 
						|
	pb.KeyType_Ed448:     UnmarshalEd448PrivateKey,
 | 
						|
}
 | 
						|
 | 
						|
// Key represents a crypto key that can be compared to another key
 | 
						|
type Key interface {
 | 
						|
	// Equals checks whether two PubKeys are the same
 | 
						|
	Equals(Key) bool
 | 
						|
 | 
						|
	// Raw returns the raw bytes of the key (not wrapped in the
 | 
						|
	// libp2p-crypto protobuf).
 | 
						|
	//
 | 
						|
	// This function is the inverse of {Priv,Pub}KeyUnmarshaler.
 | 
						|
	Raw() ([]byte, error)
 | 
						|
 | 
						|
	// Type returns the protobuf key type.
 | 
						|
	Type() pb.KeyType
 | 
						|
}
 | 
						|
 | 
						|
// PrivKey represents a private key that can be used to generate a public key and sign data
 | 
						|
type PrivKey interface {
 | 
						|
	Key
 | 
						|
 | 
						|
	// Cryptographically sign the given bytes
 | 
						|
	Sign([]byte) ([]byte, error)
 | 
						|
 | 
						|
	// Return a public key paired with this private key
 | 
						|
	GetPublic() PubKey
 | 
						|
}
 | 
						|
 | 
						|
// PubKey is a public key that can be used to verify data signed with the corresponding private key
 | 
						|
type PubKey interface {
 | 
						|
	Key
 | 
						|
 | 
						|
	// Verify that 'sig' is the signed hash of 'data'
 | 
						|
	Verify(data []byte, sig []byte) (bool, error)
 | 
						|
}
 | 
						|
 | 
						|
// GenSharedKey generates the shared key from a given private key
 | 
						|
type GenSharedKey func([]byte) ([]byte, error)
 | 
						|
 | 
						|
// GenerateKeyPair generates a private and public key
 | 
						|
func GenerateKeyPair(typ, bits int) (PrivKey, PubKey, error) {
 | 
						|
	return GenerateKeyPairWithReader(typ, bits, rand.Reader)
 | 
						|
}
 | 
						|
 | 
						|
// GenerateKeyPairWithReader returns a keypair of the given type and bit-size
 | 
						|
func GenerateKeyPairWithReader(typ, bits int, src io.Reader) (PrivKey, PubKey, error) {
 | 
						|
	switch typ {
 | 
						|
	case RSA:
 | 
						|
		return GenerateRSAKeyPair(bits, src)
 | 
						|
	case Ed25519:
 | 
						|
		return GenerateEd25519Key(src)
 | 
						|
	case Secp256k1:
 | 
						|
		return GenerateSecp256k1Key(src)
 | 
						|
	case ECDSA:
 | 
						|
		return GenerateECDSAKeyPair(src)
 | 
						|
	case Ed448:
 | 
						|
		return GenerateEd448Key(src)
 | 
						|
	default:
 | 
						|
		return nil, nil, ErrBadKeyType
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// UnmarshalPublicKey converts a protobuf serialized public key into its
 | 
						|
// representative object
 | 
						|
func UnmarshalPublicKey(data []byte) (PubKey, error) {
 | 
						|
	pmes := new(pb.PublicKey)
 | 
						|
	err := proto.Unmarshal(data, pmes)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return PublicKeyFromProto(pmes)
 | 
						|
}
 | 
						|
 | 
						|
// PublicKeyFromProto converts an unserialized protobuf PublicKey message
 | 
						|
// into its representative object.
 | 
						|
func PublicKeyFromProto(pmes *pb.PublicKey) (PubKey, error) {
 | 
						|
	um, ok := PubKeyUnmarshallers[pmes.GetType()]
 | 
						|
	if !ok {
 | 
						|
		return nil, ErrBadKeyType
 | 
						|
	}
 | 
						|
 | 
						|
	data := pmes.GetData()
 | 
						|
 | 
						|
	pk, err := um(data)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	switch tpk := pk.(type) {
 | 
						|
	case *RsaPublicKey:
 | 
						|
		tpk.cached, _ = proto.Marshal(pmes)
 | 
						|
	}
 | 
						|
 | 
						|
	return pk, nil
 | 
						|
}
 | 
						|
 | 
						|
// MarshalPublicKey converts a public key object into a protobuf serialized
 | 
						|
// public key
 | 
						|
func MarshalPublicKey(k PubKey) ([]byte, error) {
 | 
						|
	pbmes, err := PublicKeyToProto(k)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return proto.Marshal(pbmes)
 | 
						|
}
 | 
						|
 | 
						|
// PublicKeyToProto converts a public key object into an unserialized
 | 
						|
// protobuf PublicKey message.
 | 
						|
func PublicKeyToProto(k PubKey) (*pb.PublicKey, error) {
 | 
						|
	data, err := k.Raw()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return &pb.PublicKey{
 | 
						|
		Type: k.Type().Enum(),
 | 
						|
		Data: data,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
// UnmarshalPrivateKey converts a protobuf serialized private key into its
 | 
						|
// representative object
 | 
						|
func UnmarshalPrivateKey(data []byte) (PrivKey, error) {
 | 
						|
	pmes := new(pb.PrivateKey)
 | 
						|
	err := proto.Unmarshal(data, pmes)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	um, ok := PrivKeyUnmarshallers[pmes.GetType()]
 | 
						|
	if !ok {
 | 
						|
		return nil, ErrBadKeyType
 | 
						|
	}
 | 
						|
 | 
						|
	return um(pmes.GetData())
 | 
						|
}
 | 
						|
 | 
						|
// MarshalPrivateKey converts a key object into its protobuf serialized form.
 | 
						|
func MarshalPrivateKey(k PrivKey) ([]byte, error) {
 | 
						|
	data, err := k.Raw()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return proto.Marshal(&pb.PrivateKey{
 | 
						|
		Type: k.Type().Enum(),
 | 
						|
		Data: data,
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// ConfigDecodeKey decodes from b64 (for config file) to a byte array that can be unmarshalled.
 | 
						|
func ConfigDecodeKey(b string) ([]byte, error) {
 | 
						|
	return base64.StdEncoding.DecodeString(b)
 | 
						|
}
 | 
						|
 | 
						|
// ConfigEncodeKey encodes a marshalled key to b64 (for config file).
 | 
						|
func ConfigEncodeKey(b []byte) string {
 | 
						|
	return base64.StdEncoding.EncodeToString(b)
 | 
						|
}
 | 
						|
 | 
						|
// KeyEqual checks whether two Keys are equivalent (have identical byte representations).
 | 
						|
func KeyEqual(k1, k2 Key) bool {
 | 
						|
	if k1 == k2 {
 | 
						|
		return true
 | 
						|
	}
 | 
						|
 | 
						|
	return k1.Equals(k2)
 | 
						|
}
 | 
						|
 | 
						|
func basicEquals(k1, k2 Key) bool {
 | 
						|
	if k1.Type() != k2.Type() {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
 | 
						|
	a, err := k1.Raw()
 | 
						|
	if err != nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	b, err := k2.Raw()
 | 
						|
	if err != nil {
 | 
						|
		return false
 | 
						|
	}
 | 
						|
	return subtle.ConstantTimeCompare(a, b) == 1
 | 
						|
}
 |