github.com/project-88388/tendermint-v0.34.14-terra.2@v1.0.0/crypto/sr25519/privkey.go (about) 1 package sr25519 2 3 import ( 4 "crypto/subtle" 5 "fmt" 6 "io" 7 8 "github.com/tendermint/tendermint/crypto" 9 10 schnorrkel "github.com/ChainSafe/go-schnorrkel" 11 ) 12 13 // PrivKeySize is the number of bytes in an Sr25519 private key. 14 const PrivKeySize = 32 15 16 // PrivKeySr25519 implements crypto.PrivKey. 17 type PrivKey []byte 18 19 // Bytes returns the byte representation of the PrivKey. 20 func (privKey PrivKey) Bytes() []byte { 21 return []byte(privKey) 22 } 23 24 // Sign produces a signature on the provided message. 25 func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { 26 var p [PrivKeySize]byte 27 copy(p[:], privKey) 28 miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p) 29 if err != nil { 30 return []byte{}, err 31 } 32 secretKey := miniSecretKey.ExpandEd25519() 33 34 signingContext := schnorrkel.NewSigningContext([]byte{}, msg) 35 36 sig, err := secretKey.Sign(signingContext) 37 if err != nil { 38 return []byte{}, err 39 } 40 41 sigBytes := sig.Encode() 42 return sigBytes[:], nil 43 } 44 45 // PubKey gets the corresponding public key from the private key. 46 func (privKey PrivKey) PubKey() crypto.PubKey { 47 var p [PrivKeySize]byte 48 copy(p[:], privKey) 49 miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p) 50 if err != nil { 51 panic(fmt.Sprintf("Invalid private key: %v", err)) 52 } 53 secretKey := miniSecretKey.ExpandEd25519() 54 55 pubkey, err := secretKey.Public() 56 if err != nil { 57 panic(fmt.Sprintf("Could not generate public key: %v", err)) 58 } 59 key := pubkey.Encode() 60 return PubKey(key[:]) 61 } 62 63 // Equals - you probably don't need to use this. 64 // Runs in constant time based on length of the keys. 65 func (privKey PrivKey) Equals(other crypto.PrivKey) bool { 66 if otherEd, ok := other.(PrivKey); ok { 67 return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 68 } 69 return false 70 } 71 72 func (privKey PrivKey) Type() string { 73 return keyType 74 } 75 76 // GenPrivKey generates a new sr25519 private key. 77 // It uses OS randomness in conjunction with the current global random seed 78 // in tendermint/libs/common to generate the private key. 79 func GenPrivKey() PrivKey { 80 return genPrivKey(crypto.CReader()) 81 } 82 83 // genPrivKey generates a new sr25519 private key using the provided reader. 84 func genPrivKey(rand io.Reader) PrivKey { 85 var seed [64]byte 86 87 out := make([]byte, 64) 88 _, err := io.ReadFull(rand, out) 89 if err != nil { 90 panic(err) 91 } 92 93 copy(seed[:], out) 94 95 key := schnorrkel.NewMiniSecretKey(seed).ExpandEd25519().Encode() 96 return key[:] 97 } 98 99 // GenPrivKeyFromSecret hashes the secret with SHA2, and uses 100 // that 32 byte output to create the private key. 101 // NOTE: secret should be the output of a KDF like bcrypt, 102 // if it's derived from user input. 103 func GenPrivKeyFromSecret(secret []byte) PrivKey { 104 seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. 105 var bz [PrivKeySize]byte 106 copy(bz[:], seed) 107 privKey, _ := schnorrkel.NewMiniSecretKeyFromRaw(bz) 108 key := privKey.ExpandEd25519().Encode() 109 return key[:] 110 }