我正在尝试调用 Coinbase Pro API,但一直收到无效签名。我遵循了 CoinBase Pro 上的说明,在这里阅读了大量相关文章,但没有任何内容真正指出问题。我试过对时间戳 + 方法 + fullURL 进行哈希处理,我只试过文档所述的 API 端点。我已经验证了散列和 base64 函数得到了正确的结果。我曾尝试按照 CoinBase 上的文档所述解码秘密,但这会产生不可读的字符。所以我尝试使用在线工具对秘密进行 base64 解码,但这会产生不可解码的错误消息。有一篇文章提到把参数改成小写,所以我尝试了各种组合,还是不行。
需要注意的是,秘密已经是 64 字节了。文档说解码后的秘密应该是 64 字节。所以我尝试了解码和未解码的秘密。文档说对 SHA256 哈希的结果进行 base64 编码,但我使用的函数已经这样做了。所以我尝试了编码和非编码只是为了后代,但仍然产生无效签名错误消息。
有一个调用 /time 端点的 getEpochTime 函数。这是我获得 HMAC_SHA256 代码的站点,尽管我必须将 MSXML2.DOMDocument 的引用更改为 MSXML2.DOMDocument60。 https://www.excelhowto.com/macros/excel-vba-base64-hmac-sha256-and-sha1-encryption/
以下是我用来验证散列和加密的网站: https://devpal.co/base64-decode/ https://www.devglan.com/online-tools/hmac-sha256-online#/google_vignette
我目前将 api 密钥、秘密和密码存储在 Excel 工作表中,以便于测试。在创建api key时,我从屏幕上复制了数据并粘贴到Excel工作表中,以避免人为错误。我还验证了 api 密钥具有查看/交易/转移权限。
任何建设性的帮助将不胜感激。
这是我的代码。
Sub Test()
Dim oXmlHttp As MSXML2.XMLHTTP60
Set oXmlHttp = New MSXML2.XMLHTTP60
Dim URL As String
Dim appKey As String
Dim Signature As String
Dim Passphrase As String
Dim TimeStamp As String
Dim Secret As String
Dim HashText As String
Dim Hash As String
Dim API As String
Dim sBody As String
API = "/v2/accounts"
TimeStamp = GetEpochTime
URL = Sheets("Configuration").Cells(3, 2) & API
appKey = Sheets("Configuration").Cells(6, 2).Value
Secret = Sheets("Configuration").Cells(7, 2) 'Base64DecodeString( )
Passphrase = Sheets("Configuration").Cells(8, 2)
HashText = TimeStamp & "GET" & URL
Signature = Base64_HMACSHA256(HashText, Secret)
oXmlHttp.Open "GET", URL, False ', "", ""
oXmlHttp.setRequestHeader "CB-ACCESS-KEY", appKey
oXmlHttp.setRequestHeader "CB-ACCESS-TIMESTAMP", TimeStamp
oXmlHttp.setRequestHeader "CB-ACCESS-PASSPHRASE", Passphrase
oXmlHttp.setRequestHeader "CB-ACCESS-SIGN", Signature
oXmlHttp.setRequestHeader "Content-Type", "application/json"
oXmlHttp.send
While oXmlHttp.readyState <> 4
DoEvents
Wend
sBody = oXmlHttp.responseText
MsgBox sBody
End Sub
Function GetEpochTime() As Double
Dim oXmlHttp As MSXML2.XMLHTTP60
Set oXmlHttp = New MSXML2.XMLHTTP60
Dim URL As String
URL = Sheets("Configuration").Cells(3, 2) & "/time"
oXmlHttp.Open "GET", URL, False
oXmlHttp.setRequestHeader "Content-Type", "application/json"
oXmlHttp.send
GetEpochTime = GetJSON_Key(oXmlHttp.responseText, "epoch")
End Function
Function Base64_HMACSHA256(ByVal sTextToHash As String, ByVal sSharedSecretKey As String)
Dim asc As Object, enc As Object
Dim TextToHash() As Byte
Dim SharedSecretKey() As Byte
Set asc = CreateObject("System.Text.UTF8Encoding")
Set enc = CreateObject("System.Security.Cryptography.HMACSHA256")
TextToHash = asc.Getbytes_4(sTextToHash)
SharedSecretKey = asc.Getbytes_4(sSharedSecretKey)
enc.Key = SharedSecretKey
Dim bytes() As Byte
bytes = enc.ComputeHash_2((TextToHash))
Base64_HMACSHA256 = Base64EncodeFromBytes(bytes)
Set asc = Nothing
Set enc = Nothing
End Function
Function Base64EncodeString(ByVal sText As String) As String
Dim byt() As Byte
byt = VBA.StrConv(sText, VbStrConv.vbFromUnicode, 1033)
Base64EncodeString = Base64EncodeFromBytes(byt)
End Function
Function Base64EncodeFromBytes(ByRef byt() As Byte) As String
Dim oXML As MSXML2.DOMDocument60
Set oXML = New MSXML2.DOMDocument60
Dim oNode As MSXML2.IXMLDOMNode
Set oNode = oXML.createElement("base64")
oNode.DataType = "bin.base64"
oNode.nodeTypedValue = byt
Base64EncodeFromBytes = oNode.Text
Debug.Assert TypeName(Base64EncodeFromBytes) = "String"
Set oNode = Nothing
Set oXML = Nothing
End Function
Function Base64DecodeString(ByVal sText As String) As String
Dim byt() As Byte
byt = Base64DecodeToBytes(sText)
Base64DecodeString = VBA.StrConv(byt(), VbStrConv.vbUnicode)
End Function
Function Base64DecodeToBytes(ByVal sEncoded As String) As Byte()
Debug.Assert TypeName(sEncoded) = "String"
Dim oXML As MSXML2.DOMDocument60
Set oXML = New MSXML2.DOMDocument60
Dim oNode As MSXML2.IXMLDOMNode
Set oNode = oXML.createElement("base64")
oNode.DataType = "bin.base64"
oNode.Text = sEncoded
Base64DecodeToBytes = oNode.nodeTypedValue
Set oNode = Nothing
Set oXML = Nothing
End Function
答案 0 :(得分:0)
我终于弄清楚问题出在哪里了,仅仅描述我如何让它工作就需要一整页的时间。相反,这是代码。将其复制/粘贴到 Excel 工作簿中的新模块中并运行 TestAPIConnection 子例程。 Coinbase Pro 凭据位于名为“配置”的工作表中,并在名为 CBPro_Private_API 的函数中引用。还有一个公共 API 函数可用于未经身份验证的请求。希望你觉得这有用。
记得添加对“Microsoft XML, v6.0”和“Microsoft Scripting Runtime”的引用。
Option Explicit
Sub TestAPIConnection()
Dim sMethod As String
Dim API As String
Dim sBody As String
Dim sResult As String
API = "/accounts"
sMethod = "GET"
sBody = ""
sResult = CBPro_Private_API(sMethod, API, sBody)
'You will need to parse the resulting JSON string
MsgBox sResult
End Sub
Function CBPro_Public_API(sMethod As String, API As String, sBody As String) As String
Dim oXmlHttp As MSXML2.XMLHTTP60
Set oXmlHttp = New MSXML2.XMLHTTP60
Dim URL As String
URL = Sheets("Configuration").Cells(3, 2) & API
oXmlHttp.Open sMethod, URL, False ', "", ""
oXmlHttp.setRequestHeader "Content-Type", "application/json"
oXmlHttp.send sBody
'This is used when the ASync parameter on the .Open call is set to true
While oXmlHttp.readyState <> 4
DoEvents
Wend
CBPro_Public_API = oXmlHttp.responseText
End Function
Function CBPro_Private_API(sMethod As String, API As String, sBody As String) As String
Dim oXmlHttp As MSXML2.XMLHTTP60
Set oXmlHttp = New MSXML2.XMLHTTP60
Dim URL As String
Dim appKey As String
Dim sSignature As String
Dim sPassPhrase As String
Dim sTimeStamp As String
Dim sSecret As String
Dim sHashText As String
Dim Hash As String
'Get Setup data from the Configuration sheet
appKey = Sheets("Configuration").Cells(4, 2).Value
sSecret = Sheets("Configuration").Cells(5, 2)
sPassPhrase = Sheets("Configuration").Cells(6, 2)
URL = Sheets("Configuration").Cells(3, 2) & API
'Create the hashed signature for verification by the server
sTimeStamp = GetEpochTime
sHashText = sTimeStamp & sMethod & API & sBody
sSignature = GenerateSignature(sHashText, sSecret)
'Call the API endpoint
oXmlHttp.Open sMethod, URL, False
oXmlHttp.setRequestHeader "CB-ACCESS-KEY", appKey
oXmlHttp.setRequestHeader "CB-ACCESS-SIGN", sSignature
oXmlHttp.setRequestHeader "CB-ACCESS-TIMESTAMP", sTimeStamp
oXmlHttp.setRequestHeader "CB-ACCESS-PASSPHRASE", sPassPhrase
oXmlHttp.send sBody
'Wait for a response
While oXmlHttp.readyState <> 4
DoEvents
Wend
CBPro_Private_API = oXmlHttp.responseText
End Function
Function GenerateSignature(ByVal sTextToHash As String, sSharedSecretKey As String) As String
Dim asc As Object
Dim enc As Object
Dim TextToHash() As Byte
Dim bytes() As Byte
Set asc = CreateObject("System.Text.UTF8Encoding")
Set enc = CreateObject("System.Security.Cryptography.HMACSHA256")
enc.Key = Base64DecodeToBytes(sSharedSecretKey)
TextToHash = asc.GetBytes_4(sTextToHash)
bytes = enc.ComputeHash_2((TextToHash))
GenerateSignature = Base64EncodeFromBytes(bytes)
Set asc = Nothing
Set enc = Nothing
End Function
Function Base64_HMACSHA256(ByVal sTextToHash As String, sSharedSecretKey As String) As String
Dim asc As Object
Dim enc As Object
Dim TextToHash() As Byte
Dim SharedSecretKey() As Byte
Dim bytes() As Byte
Set asc = CreateObject("System.Text.UTF8Encoding")
Set enc = CreateObject("System.Security.Cryptography.HMACSHA256")
SharedSecretKey = asc.GetBytes_4(sSharedSecretKey)
enc.Key = SharedSecretKey
TextToHash = asc.GetBytes_4(sTextToHash)
bytes = enc.ComputeHash_2((TextToHash))
Base64_HMACSHA256 = Base64EncodeFromBytes(bytes)
Set asc = Nothing
Set enc = Nothing
End Function
Function Base64EncodeFromBytes(ByRef byt() As Byte) As String
Dim oXML As MSXML2.DOMDocument60
Set oXML = New MSXML2.DOMDocument60
Dim oNode As MSXML2.IXMLDOMNode
Set oNode = oXML.createElement("base64")
oNode.DataType = "bin.base64"
oNode.nodeTypedValue = byt
Base64EncodeFromBytes = oNode.Text
Debug.Assert TypeName(Base64EncodeFromBytes) = "String"
Set oNode = Nothing
Set oXML = Nothing
End Function
Function Base64DecodeToBytes(ByVal sEncoded As String) As Byte()
Dim oXML As MSXML2.DOMDocument60
Set oXML = New MSXML2.DOMDocument60
Dim oNode As MSXML2.IXMLDOMNode
Set oNode = oXML.createElement("base64")
oNode.DataType = "bin.base64"
oNode.Text = sEncoded
Base64DecodeToBytes = oNode.nodeTypedValue
Set oNode = Nothing
Set oXML = Nothing
End Function
Function GetEpochTime() As Double
'Get Epoch Time from server
Dim sResponse As String
sResponse = CBPro_Public_API("GET", "/time", "")
GetEpochTime = GetJSON_Key(sResponse, "epoch")
End Function