gpt4 book ai didi

python - Go 和 Python HMAC 库给出不同的结果

转载 作者:IT王子 更新时间:2023-10-29 01:33:44 33 4
gpt4 key购买 nike

我正在尝试使用 HMAC/sha512 API key 方案进行身份验证。

这是示例 Python 代码,它运行良好:

import urllib, urllib2
import json
import time
import hmac, hashlib
import sys
api_key = "J88PJQEG-LKKICZLN-3H33GWIB-97OGW8I5"
secret = "b9f2e97c5c43e8e759c06219b37fce78478985ae4b0176d47182419c434567405a9386a854bca5d068135d1163d3f1cc9b877cd5d95d03c9d100be6ffcaac864"

# cmd = sys.argv[1]
# args = json.loads(sys.argv[2])

def auth_request(command, args):
args = [("command", command), ("nonce", 3000000000)]
post_data = urllib.urlencode(args)
print post_data
sign = hmac.new(secret, post_data, hashlib.sha512).hexdigest()
print sign
headers = {
'Sign': sign,
'Key': api_key
}

ret = urllib2.urlopen(urllib2.Request('https://poloniex.com/tradingApi', post_data, headers))
return ret.read()

print auth_request("returnBalances", {})

现在我的 Go 实现:

const (
public_api_url = "https://poloniex.com/public"
private_api_url = "https://poloniex.com/tradingApi"
pubkey := "J88PJQEG-LKKICZLN-3H33GWIB-97OGW8I5"
privkey := "b9f2e97c5c43e8e759c06219b37fce78478985ae4b0176d47182419c434567405a9386a854bca5d068135d1163d3f1cc9b877cd5d95d03c9d100be6ffcaac864"
)
func CallPrivate(method string, args map[string]string) dynjson.DynNode {

if args == nil {
args = make(map[string]string)
}
v := make(url.Values)
v.Set("nonce", "3000000000") //strconv.Itoa(int((time.Now().Unix()))*1000))
v.Set("command", method)
for k, val := range args {
v.Set(k, val)
}
final_url := private_api_url + "?" + v.Encode()
log.Println(final_url)
client := &http.Client{}
post_data := v.Encode()
secret_bytes, err := hex.DecodeString(privkey)
check(err)
sighash := hmac.New(sha512.New, secret_bytes)
sighash.Write([]byte(post_data))
sigstr := hex.EncodeToString(sighash.Sum(nil))
log.Println(sigstr)
j, err := json.Marshal(args)
check(err)
buf := bytes.NewBuffer(j)
req, err := http.NewRequest("POST", final_url, buf)
check(err)
req.Header.Set("Key", pubkey)
req.Header.Set("Sign", sigstr)
res, err := client.Do(req)
check(err)
defer res.Body.Close()
if res.StatusCode != 200 {
log.Println("bad status code")
log.Printf("%s", res)
panic(errors.New(res.Status))
}
res_body, err := ioutil.ReadAll(res.Body)
check(err)
//log.Printf("%v", res_body)
return dynjson.NewFromBytes(res_body)

}

CallPrivate("returnBalances", nil)

现在我一直在调用 python 实现,这不是一个很好的解决方案。

最佳答案

Python dict 是一种无序映射类型。

>>> args = {}
>>> args['command'] = 'command'
>>> args['nonce'] = 10000
>>> list(args)
['nonce', 'command'] # <--- Iterating dictionary will yield in different order
# with item insertion order

urllib.urlencode不仅接受字典,而且还接受一系列键值对序列。你可以用它来保证输出的顺序:

>>> import urllib
>>> urllib.urlencode({'command': 'command', 'nonce': 10000})
'nonce=10000&command=command'
>>> urllib.urlencode([('command', 'command'), ('nonce', 10000)])
'command=command&nonce=10000'

或者,您可以使用 collections.OrderedDict 而不是 dict ({})它会记住 key 插入顺序。

更新

在 Go 代码中,command post 数据是通过 method 而不是 command 参数设置的。

v.Set("command", method)
^^^^^^

更新 2

Python 代码按原样使用十六进制字符串 secret:

sign = hmac.new(secret, post_data, hashlib.sha512).hexdigest()

Go 代码在使用前对其进行解码:

secret_bytes, _ := hex.DecodeString(privkey)
sighash := hmac.New(sha512.New, secret_bytes)

和Python代码一样做:

sighash := hmac.New(sha512.New, []byte(privkey))

更新 3

  • Go 代码会为 post_data 进行 json 编码,但 Python 代码不会。
  • 您需要在 Go 代码中设置 header :"Content-Type=application/x-www-form-urlencoded"

这里是可以工作的修改后的 Go 代码:

func CallPrivate(method string, args map[string]string) {
if args == nil {
args = make(map[string]string)
}
v := make(url.Values)
v.Set("nonce", "3000000000") //strconv.Itoa(int((time.Now().Unix()))*1000))
v.Set("command", method)
for k, val := range args {
v.Set(k, val)
}
final_url := private_api_url
post_data := v.Encode()
sighash := hmac.New(sha512.New, []byte(privkey))
sighash.Write([]byte(post_data))
sigstr := hex.EncodeToString(sighash.Sum(nil))

client := &http.Client{}
buf := bytes.NewBuffer([]byte(post_data))
req, _ := http.NewRequest("POST", final_url, buf)
req.Header.Set("Key", pubkey)
req.Header.Set("Sign", sigstr)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
res, _ := client.Do(req)
defer res.Body.Close()

res_body, _ := ioutil.ReadAll(res.Body)
log.Printf("%s", string(res_body))
}

关于python - Go 和 Python HMAC 库给出不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27715162/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com