github.com/Finschia/finschia-sdk@v0.48.1/crypto/keys/secp256k1/secp256k1.go (about) 1 package secp256k1 2 3 import ( 4 "bytes" 5 "crypto/sha256" 6 "crypto/subtle" 7 "fmt" 8 "io" 9 "math/big" 10 11 secp256k1 "github.com/btcsuite/btcd/btcec" 12 "golang.org/x/crypto/ripemd160" //nolint: staticcheck // necessary for Bitcoin address format 13 14 "github.com/Finschia/ostracon/crypto" 15 16 "github.com/Finschia/finschia-sdk/codec" 17 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 18 "github.com/Finschia/finschia-sdk/types/errors" 19 ) 20 21 var ( 22 _ cryptotypes.PrivKey = &PrivKey{} 23 _ codec.AminoMarshaler = &PrivKey{} 24 ) 25 26 const ( 27 PrivKeySize = 32 28 keyType = "secp256k1" 29 PrivKeyName = "tendermint/PrivKeySecp256k1" 30 PubKeyName = "tendermint/PubKeySecp256k1" 31 ) 32 33 // Bytes returns the byte representation of the Private Key. 34 func (privKey *PrivKey) Bytes() []byte { 35 return privKey.Key 36 } 37 38 // PubKey performs the point-scalar multiplication from the privKey on the 39 // generator point to get the pubkey. 40 func (privKey *PrivKey) PubKey() cryptotypes.PubKey { 41 _, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key) 42 pk := pubkeyObject.SerializeCompressed() 43 return &PubKey{Key: pk} 44 } 45 46 // Equals - you probably don't need to use this. 47 // Runs in constant time based on length of the 48 func (privKey *PrivKey) Equals(other cryptotypes.LedgerPrivKey) bool { 49 return privKey.Type() == other.Type() && subtle.ConstantTimeCompare(privKey.Bytes(), other.Bytes()) == 1 50 } 51 52 func (privKey *PrivKey) Type() string { 53 return keyType 54 } 55 56 // MarshalAmino overrides Amino binary marshalling. 57 func (privKey PrivKey) MarshalAmino() ([]byte, error) { 58 return privKey.Key, nil 59 } 60 61 // UnmarshalAmino overrides Amino binary marshalling. 62 func (privKey *PrivKey) UnmarshalAmino(bz []byte) error { 63 if len(bz) != PrivKeySize { 64 return fmt.Errorf("invalid privkey size") 65 } 66 privKey.Key = bz 67 68 return nil 69 } 70 71 // MarshalAminoJSON overrides Amino JSON marshalling. 72 func (privKey PrivKey) MarshalAminoJSON() ([]byte, error) { 73 // When we marshal to Amino JSON, we don't marshal the "key" field itself, 74 // just its contents (i.e. the key bytes). 75 return privKey.MarshalAmino() 76 } 77 78 // UnmarshalAminoJSON overrides Amino JSON marshalling. 79 func (privKey *PrivKey) UnmarshalAminoJSON(bz []byte) error { 80 return privKey.UnmarshalAmino(bz) 81 } 82 83 // GenPrivKey generates a new ECDSA private key on curve secp256k1 private key. 84 // It uses OS randomness to generate the private key. 85 func GenPrivKey() *PrivKey { 86 return &PrivKey{Key: genPrivKey(crypto.CReader())} 87 } 88 89 // genPrivKey generates a new secp256k1 private key using the provided reader. 90 func genPrivKey(rand io.Reader) []byte { 91 var privKeyBytes [PrivKeySize]byte 92 d := new(big.Int) 93 for { 94 privKeyBytes = [PrivKeySize]byte{} 95 _, err := io.ReadFull(rand, privKeyBytes[:]) 96 if err != nil { 97 panic(err) 98 } 99 100 d.SetBytes(privKeyBytes[:]) 101 // break if we found a valid point (i.e. > 0 and < N == curverOrder) 102 isValidFieldElement := 0 < d.Sign() && d.Cmp(secp256k1.S256().N) < 0 103 if isValidFieldElement { 104 break 105 } 106 } 107 108 return privKeyBytes[:] 109 } 110 111 var one = new(big.Int).SetInt64(1) 112 113 // GenPrivKeyFromSecret hashes the secret with SHA2, and uses 114 // that 32 byte output to create the private key. 115 // 116 // It makes sure the private key is a valid field element by setting: 117 // 118 // c = sha256(secret) 119 // k = (c mod (n − 1)) + 1, where n = curve order. 120 // 121 // NOTE: secret should be the output of a KDF like bcrypt, 122 // if it's derived from user input. 123 func GenPrivKeyFromSecret(secret []byte) *PrivKey { 124 secHash := sha256.Sum256(secret) 125 // to guarantee that we have a valid field element, we use the approach of: 126 // "Suite B Implementer’s Guide to FIPS 186-3", A.2.1 127 // https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm 128 // see also https://github.com/golang/go/blob/0380c9ad38843d523d9c9804fe300cb7edd7cd3c/src/crypto/ecdsa/ecdsa.go#L89-L101 129 fe := new(big.Int).SetBytes(secHash[:]) 130 n := new(big.Int).Sub(secp256k1.S256().N, one) 131 fe.Mod(fe, n) 132 fe.Add(fe, one) 133 134 feB := fe.Bytes() 135 privKey32 := make([]byte, PrivKeySize) 136 // copy feB over to fixed 32 byte privKey32 and pad (if necessary) 137 copy(privKey32[32-len(feB):32], feB) 138 139 return &PrivKey{Key: privKey32} 140 } 141 142 //------------------------------------- 143 144 var ( 145 _ cryptotypes.PubKey = &PubKey{} 146 _ codec.AminoMarshaler = &PubKey{} 147 ) 148 149 // PubKeySize is comprised of 32 bytes for one field element 150 // (the x-coordinate), plus one byte for the parity of the y-coordinate. 151 const PubKeySize = 33 152 153 // Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) 154 func (pubKey *PubKey) Address() crypto.Address { 155 if len(pubKey.Key) != PubKeySize { 156 panic("length of pubkey is incorrect") 157 } 158 159 sha := sha256.Sum256(pubKey.Key) 160 hasherRIPEMD160 := ripemd160.New() 161 hasherRIPEMD160.Write(sha[:]) // does not error 162 return crypto.Address(hasherRIPEMD160.Sum(nil)) 163 } 164 165 // Bytes returns the pubkey byte format. 166 func (pubKey *PubKey) Bytes() []byte { 167 return pubKey.Key 168 } 169 170 func (pubKey *PubKey) String() string { 171 return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey.Key) 172 } 173 174 func (pubKey *PubKey) Type() string { 175 return keyType 176 } 177 178 func (pubKey *PubKey) Equals(other cryptotypes.PubKey) bool { 179 return pubKey.Type() == other.Type() && bytes.Equal(pubKey.Bytes(), other.Bytes()) 180 } 181 182 // MarshalAmino overrides Amino binary marshalling. 183 func (pubKey PubKey) MarshalAmino() ([]byte, error) { 184 return pubKey.Key, nil 185 } 186 187 // UnmarshalAmino overrides Amino binary marshalling. 188 func (pubKey *PubKey) UnmarshalAmino(bz []byte) error { 189 if len(bz) != PubKeySize { 190 return errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size") 191 } 192 pubKey.Key = bz 193 194 return nil 195 } 196 197 // MarshalAminoJSON overrides Amino JSON marshalling. 198 func (pubKey PubKey) MarshalAminoJSON() ([]byte, error) { 199 // When we marshal to Amino JSON, we don't marshal the "key" field itself, 200 // just its contents (i.e. the key bytes). 201 return pubKey.MarshalAmino() 202 } 203 204 // UnmarshalAminoJSON overrides Amino JSON marshalling. 205 func (pubKey *PubKey) UnmarshalAminoJSON(bz []byte) error { 206 return pubKey.UnmarshalAmino(bz) 207 }