【问题标题】:Using VBA to authenticate to CoinBase Pro, invalid signature使用 VBA 对 CoinBase Pro 进行身份验证,签名无效
【发布时间】:2021-07-01 02:43:48
【问题描述】:

我正在尝试调用 Coinbase Pro API,但不断收到无效签名。我已经按照 CoinBase Pro 上的说明进行操作,在这里阅读了大量相关文章,但并没有真正指出问题所在。我试过散列时间戳+方法+ fullURL,我只尝试了文档所述的API端点。我已经验证了散列和 base64 函数得到了正确的结果。我已经尝试解码 CoinBase 文档中所述的秘密,但这会产生不可读的字符。因此,我尝试使用在线工具对秘密进行 base64 解码,但这会产生不可解码的错误消息。一篇文章提到将参数改为小写,所以我尝试了各种组合,仍然不行。

需要注意的是,secret 已经是 64 字节了。文档说解码后的秘密应该是 64 字节。所以我尝试了解码和未解码的秘密。文档说base64编码SHA256哈希的结果,但我正在使用的函数已经这样做了。所以我为了后代尝试了编码和非编码,但仍然产生无效签名错误消息。

有一个调用 /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 密钥时,我从屏幕上复制数据并将其粘贴到 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

【问题讨论】:

    标签: excel vba signature coinbase-api


    【解决方案1】:

    我终于弄清楚了问题所在,我需要一整页来描述我是如何让它工作的。相反,这里是代码。将其复制/粘贴到 Excel 工作簿中的新模块中,然后运行 ​​TestAPIConnection 子例程。 Coinbase Pro 凭证位于名为“配置”的工作表中,并在名为 CBPro_Private_API 的函数中引用。还有一个公共 API 函数可用于未经身份验证的请求。希望你觉得这很有用。

    记得添加对“Microsoft XML, v6.0”和“Microsoft Scripting Runtime”的引用。

    Configuration Sheet

    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 = CDbl(GetJSON_Key(sResponse, "epoch"))
        
    End Function
    

    【讨论】:

      猜你喜欢
      • 2019-10-30
      • 1970-01-01
      • 2020-04-09
      • 1970-01-01
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-22
      相关资源
      最近更新 更多