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