github.com/diadata-org/diadata@v1.4.593/pkg/utils/keypair.go (about) 1 package utils 2 3 import ( 4 "crypto/ecdsa" 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 9 "github.com/ethereum/go-ethereum/common" 10 "github.com/ethereum/go-ethereum/common/hexutil" 11 "github.com/ethereum/go-ethereum/crypto" 12 "github.com/pkg/errors" 13 "github.com/sirupsen/logrus" 14 // "github.com/storyicon/sigverify" 15 ) 16 17 var log = logrus.New() 18 19 func NewKeyPair() (publickey, privatekey string) { 20 privateKey, err := crypto.GenerateKey() 21 if err != nil { 22 log.Fatal(err) 23 } 24 privateKeyBytes := crypto.FromECDSA(privateKey) 25 26 fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19 27 28 publicKey := privateKey.Public() 29 publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) 30 if !ok { 31 log.Fatal("error casting public key to ECDSA") 32 33 } 34 publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) 35 fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) 36 37 address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex() 38 39 return address, hexutil.Encode(privateKeyBytes)[:] 40 41 } 42 43 func GetSigner(chainID, creator, oracleaddress, message, signed string) (common.Address, error) { 44 typedatastring := `{ 45 "types": { 46 "EIP712Domain": [{ 47 "name": "name", 48 "type": "string" 49 }, { 50 "name": "version", 51 "type": "string" 52 }, { 53 "name": "chainId", 54 "type": "uint256" 55 }, { 56 "name": "verifyingContract", 57 "type": "address" 58 }], 59 "Oracle": [{ 60 "name": "contents", 61 "type": "string" 62 }, { 63 "name": "creator", 64 "type": "address" 65 }, { 66 "name": "oracleaddress", 67 "type": "address" 68 }] 69 }, 70 "primaryType": "Oracle", 71 "domain": { 72 "name": "Oracle Builder", 73 "version": "1", 74 "chainId": "` + chainID + `", 75 "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", 76 "salt": "" 77 }, 78 "message": { 79 "contents": "` + message + `", 80 "creator": "` + creator + `", 81 "oracleaddress": "` + oracleaddress + `" 82 } 83 }` 84 var typedData TypedData 85 86 if err := json.Unmarshal([]byte(typedatastring), &typedData); err != nil { 87 } 88 89 signature, _ := HexDecode(signed) 90 91 return VerifyTypedData("Oracle", typedData.Domain, typedData.Types, typedData.Message, signature) 92 93 } 94 func Has0xPrefix(str string) bool { 95 return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') 96 } 97 98 func HexDecode(s string) ([]byte, error) { 99 if Has0xPrefix(s) { 100 s = s[2:] 101 } 102 if len(s)%2 == 1 { 103 s = "0" + s 104 } 105 return hex.DecodeString(s) 106 } 107 108 func CopyBytes(data []byte) []byte { 109 ret := make([]byte, len(data)) 110 copy(ret, data) 111 return ret 112 } 113 114 func VerifyTypedData(primaryType string, domain TypedDataDomain, types Types, message TypedDataMessage, signature []byte) (common.Address, error) { 115 signature = CopyBytes(signature) 116 if len(signature) != crypto.SignatureLength { 117 return common.Address{}, errors.Errorf("invalid signature length: %d", crypto.SignatureLength) 118 } 119 120 if signature[64] == 27 || signature[64] == 28 { 121 signature[64] -= 27 // Transform V from 27/28 to 0/1 122 } 123 124 // if signature[crypto.RecoveryIDOffset] == 0 || signature[crypto.RecoveryIDOffset] == 1 { 125 // signature[crypto.RecoveryIDOffset] += 27 126 // } 127 challengeHash, err := hashTypedData(primaryType, domain, types, message) 128 if err != nil { 129 return common.Address{}, errors.Wrap(err, "hash typed data") 130 } 131 132 pubKeyRaw, err := crypto.Ecrecover(challengeHash, signature) 133 if err != nil { 134 return common.Address{}, errors.Wrap(err, "invalid signature") 135 } 136 137 pubKey, err := crypto.UnmarshalPubkey(pubKeyRaw) 138 if err != nil { 139 return common.Address{}, errors.Wrap(err, "unmarshal pubkey") 140 } 141 142 recoveredAddr := crypto.PubkeyToAddress(*pubKey) 143 return recoveredAddr, nil 144 } 145 146 func hashTypedData(primaryType string, domain TypedDataDomain, types Types, message TypedDataMessage) ([]byte, error) { 147 types["EIP712Domain"] = []Type{ 148 {Name: "name", Type: "string"}, 149 {Name: "version", Type: "string"}, 150 {Name: "chainId", Type: "uint256"}, 151 {Name: "verifyingContract", Type: "address"}, 152 } 153 154 signerData := TypedData{ 155 Types: types, 156 PrimaryType: primaryType, 157 Domain: domain, 158 Message: message, 159 } 160 161 typedDataHash, err := signerData.HashStruct(signerData.PrimaryType, signerData.Message) 162 if err != nil { 163 return nil, errors.Wrap(err, "hash typed data") 164 } 165 166 domainSeparator, err := signerData.HashStruct("EIP712Domain", signerData.Domain.Map()) 167 if err != nil { 168 return nil, errors.Wrap(err, "hash domain separator") 169 } 170 171 rawData := []byte(fmt.Sprintf("\x19\x01%s%s", string(domainSeparator), string(typedDataHash))) 172 challengeHash := crypto.Keccak256Hash(rawData) 173 174 return challengeHash.Bytes(), nil 175 }