github.com/Finschia/ostracon@v1.1.5/crypto/sr25519/privkey.go (about) 1 package sr25519 2 3 import ( 4 "crypto/subtle" 5 "fmt" 6 "io" 7 8 "github.com/Finschia/ostracon/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 // VRFProve is not supported in Sr25519. 46 func (privKey PrivKey) VRFProve(seed []byte) (crypto.Proof, error) { 47 return nil, fmt.Errorf("VRF prove is not supported by the sr25519") 48 } 49 50 // PubKey gets the corresponding public key from the private key. 51 func (privKey PrivKey) PubKey() crypto.PubKey { 52 var p [PrivKeySize]byte 53 copy(p[:], privKey) 54 miniSecretKey, err := schnorrkel.NewMiniSecretKeyFromRaw(p) 55 if err != nil { 56 panic(fmt.Sprintf("Invalid private key: %v", err)) 57 } 58 secretKey := miniSecretKey.ExpandEd25519() 59 60 pubkey, err := secretKey.Public() 61 if err != nil { 62 panic(fmt.Sprintf("Could not generate public key: %v", err)) 63 } 64 key := pubkey.Encode() 65 return PubKey(key[:]) 66 } 67 68 // Equals - you probably don't need to use this. 69 // Runs in constant time based on length of the keys. 70 func (privKey PrivKey) Equals(other crypto.PrivKey) bool { 71 if otherEd, ok := other.(PrivKey); ok { 72 return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 73 } 74 return false 75 } 76 77 func (privKey PrivKey) Type() string { 78 return keyType 79 } 80 81 // GenPrivKey generates a new sr25519 private key. 82 // It uses OS randomness in conjunction with the current global random seed 83 // in libs/common to generate the private key. 84 func GenPrivKey() PrivKey { 85 return genPrivKey(crypto.CReader()) 86 } 87 88 // genPrivKey generates a new sr25519 private key using the provided reader. 89 func genPrivKey(rand io.Reader) PrivKey { 90 var seed [64]byte 91 92 out := make([]byte, 64) 93 _, err := io.ReadFull(rand, out) 94 if err != nil { 95 panic(err) 96 } 97 98 copy(seed[:], out) 99 100 key := schnorrkel.NewMiniSecretKey(seed).ExpandEd25519().Encode() 101 return key[:] 102 } 103 104 // GenPrivKeyFromSecret hashes the secret with SHA2, and uses 105 // that 32 byte output to create the private key. 106 // NOTE: secret should be the output of a KDF like bcrypt, 107 // if it's derived from user input. 108 func GenPrivKeyFromSecret(secret []byte) PrivKey { 109 seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. 110 var bz [PrivKeySize]byte 111 copy(bz[:], seed) 112 privKey, _ := schnorrkel.NewMiniSecretKeyFromRaw(bz) 113 key := privKey.ExpandEd25519().Encode() 114 return key[:] 115 }