如何在 Swift 中获得与 Python 中相同的 HMAC-SHA512 签名?

问题描述 投票:0回答:1

我的目标是使用 Swift 与(经过验证的)Kraken API 进行交互。 Kraken API 网站上有一个使用 Python 的示例,我正在尝试在 Swift 中复制它。然而,我得到的最终加密签名与 Python 中的不同。我究竟做错了什么?任何帮助将非常感激。 顺便说一句,我正在使用 Swift CryptoKit 库。

Python 代码(从 Kraken API 文档复制):

import urllib.parse
import hashlib
import hmac
import base64

def get_kraken_signature(urlpath, data, secret):

    postdata = urllib.parse.urlencode(data)
    encoded = (str(data['nonce']) + postdata).encode()
    message = urlpath.encode() + hashlib.sha256(encoded).digest()

    mac = hmac.new(base64.b64decode(secret), message, hashlib.sha512)
    sigdigest = base64.b64encode(mac.digest())
    return sigdigest.decode()

api_sec = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg=="

data = {
    "nonce": "1616492376594",
    "ordertype": "limit",
    "pair": "XBTUSD",
    "price": 37500,
    "type": "buy",
    "volume": 1.25
}

signature = get_kraken_signature("/0/private/AddOrder", data, api_sec)
print("API-Sign: {}".format(signature))
#Output: 4/dpxb3iT4tp/ZCVEwSnEsLxx0bqyhLpdfOpc6fn7OR8+UClSV5n9E6aSS8MPtnRfp32bAb0nmbRn6H8ndwLUQ==
#This output is the expected output, as Kraken states on their website

我的 Swift 代码:

import CryptoKit
func encryptMsg() -> String {
    let privateKey = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg=="
    let payload = "1616492376594nonce=1616492376594&ordertype=limit&pair=XBTUSD&price=37500&type=buy&volume=1.25"
    let apiPath = "/0/private/AddOrder"
    var payload2 = apiPath
    
    // Sha256Digest
    let sha256Digest: SHA256Digest = SHA256.hash(data: Data(payload.utf8))
    debugPrint(sha256Digest)
    // Output: 23a1c1b34c6a11d641af0f24684896cb90f66fb991125c83dc357bdc3dc146f1
    
    // Convert sha256Digest from hex to ascii
    for element in sha256Digest {
        payload2.append(Character(UnicodeScalar(Int(element.description)!)!))
    }
    debugPrint(payload2)
    // Swift : /0/private/AddOrder#¡Á³Lj\u{11}ÖA¯\u{0F}$hHËöo¹\u{12}\\Ü5{Ü=ÁFñ
    // Python: /0/private/AddOrder#\xa1\xc1\xb3Lj\x11\xd6A\xaf\x0f$hH\x96\xcb\x90\xf6o\xb9\x91\x12\\\x83\xdc5{\xdc=\xc1F\xf1
    // Swift output identical to Python output
    
    // Private key
    debugPrint(Data(base64Encoded: privateKey)!.map { String(format: "%02x", $0) }.joined())
    // Swift : 9101f91d6ffca75b863958db81603b16e9c09863bc96c4945cdb2eddea30efab33f38435f1f5b19f247304709dde97799c4f6a6bdf47019b6e66e8fa17586e5e
    // Python: \x91\x01\xf9\x1do\xfc\xa7[\x869X\xdb\x81`;\x16\xe9\xc0\x98c\xbc\x96\xc4\x94\\\xdb.\xdd\xea0\xef\xab3\xf3\x845\xf1\xf5\xb1\x9f$s\x04p\x9d\xde\x97y\x9cOjk\xdfG\x01\x9bnf\xe8\xfa\x17Xn^
    // Swift output identical to Python output
    let key = SymmetricKey(data: Data(base64Encoded: privateKey)!)
    
    // SHA512 digest and Hmac construction
    var hmacSHA512 = HMAC<SHA512>.authenticationCode(for: Data(payload2.utf8), using: key)
    debugPrint(hmacSHA512)
    // Swift : e82d03bb76af28c9bb55dfc460bf8a0f64d30d0e55307bc5236f5d0581bf8864bce237238d4b7cc3c832a7e2545b1d0f70794545ce76d1bd656c13b054ea54da
    // Python: \xe3\xf7i\xc5\xbd\xe2O\x8bi\xfd\x90\x95\x13\x04\xa7\x12\xc2\xf1\xc7F\xea\xca\x12\xe9u\xf3\xa9s\xa7\xe7\xec\xe4|\xf9@\xa5I^g\xf4N\x9aI/\x0c>\xd9\xd1~\x9d\xf6l\x06\xf4\x9ef\xd1\x9f\xa1\xfc\x9d\xdc\x0bQ
    // Swift output different from Python output
    
    let finalSignature = Data(hmacSHA512).base64EncodedString()
    debugPrint(finalSignature)
    // Swift : 6C0Du3avKMm7Vd/EYL+KD2TTDQ5VMHvFI29dBYG/iGS84jcjjUt8w8gyp+JUWx0PcHlFRc520b1lbBOwVOpU2g==
    // Python: 4/dpxb3iT4tp/ZCVEwSnEsLxx0bqyhLpdfOpc6fn7OR8+UClSV5n9E6aSS8MPtnRfp32bAb0nmbRn6H8ndwLUQ==
    // Final result: Swift output different from Python output
    
    return finalSignature
}
swift encryption hmac sha apple-cryptokit
1个回答
0
投票

要在 Swift 中实现与 Python 中相同的 HMAC-SHA512 签名,您需要确保两种语言遵循相同的步骤并使用相同的输入。

import CryptoKit

func getKrakenSignature() -> String {
    let privateKey = "kQH5HW/8p1uGOVjbgWA7FunAmGO8lsSUXNsu3eow76sz84Q18fWxnyRzBHCd3pd5nE9qa99HAZtuZuj6F1huXg=="
    let payload = "nonce=1616492376594&ordertype=limit&pair=XBTUSD&price=37500&type=buy&volume=1.25"
    let apiPath = "/0/private/AddOrder"
    let nonce = "1616492376594"
    
    // Constructing the message
    let message = (apiPath + SHA256.hash(data: Data(payload.utf8)).compactMap { String(format: "%02x", $0) }.joined()).data(using: .utf8)!
    
    // Creating HMAC-SHA512 signature
    let key = SymmetricKey(data: Data(base64Encoded: privateKey)!)
    let hmacSHA512 = HMAC<SHA512>.authenticationCode(for: message, using: key)
    
    // Converting HMAC to base64-encoded string
    let finalSignature = Data(hmacSHA512).base64EncodedString()
    
    return finalSignature
}

print("API-Sign: \(getKrakenSignature())")

用于 HMAC 的消息应在 Python 和 Swift 中以相同的方式构造。确保消息包含 URL 路径,后跟编码有效负载的 SHA256 摘要。

© www.soinside.com 2019 - 2024. All rights reserved.