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