github.com/datachainlab/burrow@v0.25.0/crypto/private_key.go (about)

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	cryptoRand "crypto/rand"
     6  	"crypto/sha256"
     7  	"fmt"
     8  	"io"
     9  
    10  	"github.com/btcsuite/btcd/btcec"
    11  	"golang.org/x/crypto/ed25519"
    12  )
    13  
    14  // Currently this is a stub that reads the raw bytes returned by key_client and returns
    15  // an ed25519 public key.
    16  func PublicKeyFromBytes(bs []byte, curveType CurveType) (PublicKey, error) {
    17  	switch curveType {
    18  	case CurveTypeEd25519:
    19  		if len(bs) != ed25519.PublicKeySize {
    20  			return PublicKey{}, fmt.Errorf("bytes passed have length %v but ed25519 public keys have %v bytes",
    21  				len(bs), ed25519.PublicKeySize)
    22  		}
    23  	case CurveTypeSecp256k1:
    24  		if len(bs) != btcec.PubKeyBytesLenCompressed {
    25  			return PublicKey{}, fmt.Errorf("bytes passed have length %v but secp256k1 public keys have %v bytes",
    26  				len(bs), btcec.PubKeyBytesLenCompressed)
    27  		}
    28  	case CurveTypeUnset:
    29  		if len(bs) > 0 {
    30  			return PublicKey{}, fmt.Errorf("attempting to create an 'unset' PublicKey but passed non-empty key bytes: %X", bs)
    31  		}
    32  		return PublicKey{}, nil
    33  	default:
    34  		return PublicKey{}, ErrInvalidCurve(curveType)
    35  	}
    36  
    37  	return PublicKey{PublicKey: bs, CurveType: curveType}, nil
    38  }
    39  
    40  func (p PrivateKey) RawBytes() []byte {
    41  	return p.PrivateKey
    42  }
    43  
    44  func (p PrivateKey) Sign(msg []byte) (*Signature, error) {
    45  	switch p.CurveType {
    46  	case CurveTypeEd25519:
    47  		if len(p.PrivateKey) != ed25519.PrivateKeySize {
    48  			return nil, fmt.Errorf("bytes passed have length %v but ed25519 private keys have %v bytes",
    49  				len(p.PrivateKey), ed25519.PrivateKeySize)
    50  		}
    51  		privKey := ed25519.PrivateKey(p.PrivateKey)
    52  		return &Signature{CurveType: CurveTypeEd25519, Signature: ed25519.Sign(privKey, msg)}, nil
    53  	case CurveTypeSecp256k1:
    54  		if len(p.PrivateKey) != btcec.PrivKeyBytesLen {
    55  			return nil, fmt.Errorf("bytes passed have length %v but secp256k1 private keys have %v bytes",
    56  				len(p.PrivateKey), btcec.PrivKeyBytesLen)
    57  		}
    58  		privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), p.PrivateKey)
    59  		sig, err := privKey.Sign(msg)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  		return &Signature{CurveType: CurveTypeSecp256k1, Signature: sig.Serialize()}, nil
    64  	default:
    65  		return nil, ErrInvalidCurve(p.CurveType)
    66  	}
    67  }
    68  
    69  func (p PrivateKey) GetPublicKey() PublicKey {
    70  	return PublicKey{CurveType: p.CurveType, PublicKey: p.PublicKey}
    71  }
    72  
    73  // Reinitialise after serialisation
    74  func (p *PrivateKey) Reinitialise() error {
    75  	initP, err := PrivateKeyFromRawBytes(p.RawBytes(), p.CurveType)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	*p = initP
    80  	return nil
    81  }
    82  
    83  func (p PrivateKey) String() string {
    84  	return fmt.Sprintf("PrivateKey<PublicKey:%X>", p.PublicKey)
    85  }
    86  
    87  func PrivateKeyFromRawBytes(privKeyBytes []byte, curveType CurveType) (PrivateKey, error) {
    88  	switch curveType {
    89  	case CurveTypeEd25519:
    90  		if len(privKeyBytes) != ed25519.PrivateKeySize {
    91  			return PrivateKey{}, fmt.Errorf("bytes passed have length %v but ed25519 private keys have %v bytes",
    92  				len(privKeyBytes), ed25519.PrivateKeySize)
    93  		}
    94  		return PrivateKey{PrivateKey: privKeyBytes, PublicKey: privKeyBytes[32:], CurveType: CurveTypeEd25519}, nil
    95  	case CurveTypeSecp256k1:
    96  		if len(privKeyBytes) != btcec.PrivKeyBytesLen {
    97  			return PrivateKey{}, fmt.Errorf("bytes passed have length %v but secp256k1 private keys have %v bytes",
    98  				len(privKeyBytes), btcec.PrivKeyBytesLen)
    99  		}
   100  		privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
   101  		if !bytes.Equal(privKey.Serialize(), privKeyBytes) {
   102  			return PrivateKey{}, fmt.Errorf("serialisation of Secp256k1 private key bytes does not equal")
   103  		}
   104  		return PrivateKey{PrivateKey: privKeyBytes, PublicKey: pubKey.SerializeCompressed(), CurveType: CurveTypeSecp256k1}, nil
   105  	default:
   106  		return PrivateKey{}, ErrInvalidCurve(curveType)
   107  	}
   108  }
   109  
   110  func GeneratePrivateKey(random io.Reader, curveType CurveType) (PrivateKey, error) {
   111  	if random == nil {
   112  		random = cryptoRand.Reader
   113  	}
   114  	switch curveType {
   115  	case CurveTypeEd25519:
   116  		_, priv, err := ed25519.GenerateKey(random)
   117  		if err != nil {
   118  			return PrivateKey{}, err
   119  		}
   120  		return PrivateKeyFromRawBytes(priv, CurveTypeEd25519)
   121  	case CurveTypeSecp256k1:
   122  		privKeyBytes := make([]byte, 32)
   123  		_, err := random.Read(privKeyBytes)
   124  		if err != nil {
   125  			return PrivateKey{}, err
   126  		}
   127  		return PrivateKeyFromRawBytes(privKeyBytes, CurveTypeSecp256k1)
   128  	default:
   129  		return PrivateKey{}, ErrInvalidCurve(curveType)
   130  	}
   131  }
   132  
   133  func PrivateKeyFromSecret(secret string, curveType CurveType) PrivateKey {
   134  	hasher := sha256.New()
   135  	hasher.Write(([]byte)(secret))
   136  	// No error from a buffer
   137  	privateKey, _ := GeneratePrivateKey(bytes.NewBuffer(hasher.Sum(nil)), curveType)
   138  	return privateKey
   139  }
   140  
   141  // Ensures the last 32 bytes of the ed25519 private key is the public key derived from the first 32 private bytes
   142  func EnsureEd25519PrivateKeyCorrect(candidatePrivateKey ed25519.PrivateKey) error {
   143  	if len(candidatePrivateKey) != ed25519.PrivateKeySize {
   144  		return fmt.Errorf("ed25519 key has size %v but %v bytes passed as key", ed25519.PrivateKeySize,
   145  			len(candidatePrivateKey))
   146  	}
   147  	_, derivedPrivateKey, err := ed25519.GenerateKey(bytes.NewBuffer(candidatePrivateKey))
   148  	if err != nil {
   149  		return err
   150  	}
   151  	if !bytes.Equal(derivedPrivateKey, candidatePrivateKey) {
   152  		return fmt.Errorf("ed25519 key generated from prefix of %X should equal %X, but is %X",
   153  			candidatePrivateKey, candidatePrivateKey, derivedPrivateKey)
   154  	}
   155  	return nil
   156  }