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 }