【问题标题】:Base64 and HMAC SHA-256 encoding/decoding in JavaJava 中的 Base64 和 HMAC SHA-256 编码/解码
【发布时间】:2018-02-15 21:19:27
【问题描述】:

我正在尝试获得我的 GDAX 余额,但我认为我无法在 Java 中正确处理编码/解码。 API 参考在这里:https://docs.gdax.com/#authentication,我正在尝试做的部分是在 Accounts -> List Accounts 下(只需从上面的链接向下滚动一点)即可获得余额。

这是我的代码。尽管我在谷歌和这里做了多少搜索,但我似乎无法让它工作。我不断收到来自服务器的 400 错误,意思是“错误请求 - 无效请求格式”。

    // Decode the secret key
    byte[] decodedSecret;
    try
    {
        decodedSecret = Base64.decode(SECRET_KEY);
    }
    catch (Base64DecodingException ex)
    {
        System.out.println("Failed to decode secret key.");
        return null;
    }

    // Make the header parameters
    long timestamp = (new GregorianCalendar()).getTimeInMillis() / 1000;
    String preSign = "" + timestamp + "GET" + BASE_URL + "/accounts";

    byte[] encodedhash;
    try
    {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        try
        {
            sha256_HMAC.init(new SecretKeySpec(decodedSecret, "HmacSHA256"));
        }
        catch (InvalidKeyException ex)
        {
            System.out.println("Failed due to invalid key exception.");
            System.out.println(ex.getMessage());
            return null;
        }
        encodedhash = sha256_HMAC.doFinal(preSign.getBytes());
    }
    catch (NoSuchAlgorithmException ex)
    {
        System.out.println("Failed to make SHA-256 encode because of no such algorithm.");
        return null;
    }

    HashMap<String, String> parameters = new HashMap<>();
    parameters.put("CB-ACCESS-KEY", API_KEY);
    parameters.put("CB-ACCESS-SIGN", Base64.encode(encodedhash));
    parameters.put("CB-ACCESS-TIMESTAMP", "" + timestamp);
    parameters.put("CB-ACCESS-PASSPHRASE", PASSPHRASE);

    // Send the request
    String response = sendGet(BASE_URL + "/accounts", parameters);

这也是我在 sendGet() 中的代码,以防问题出在哪里。我知道它可以在没有参数的情况下工作,但我不知道它是否正确使用了参数,因为我无法让它工作。

    // Set up the connection
    URL url = null;
    try
    {
        url = new URL(urlStr);
    }
    catch (MalformedURLException ex)
    {
        return null;
    }
    HttpURLConnection con;
    try
    {
        con = (HttpURLConnection) url.openConnection();
    }
    catch (IOException ex)
    {
        System.out.println("Returning null because of failure to open connection.");
        return null;
    }
    try
    {
        con.setRequestMethod("GET");
    }
    catch (ProtocolException ex) {}
    if (parameters != null) // if there are parameters to add to the connection
    {
        for (Map.Entry<String, String> pair : parameters.entrySet()) // for each pair in parameters
        {
            try
            {
                con.addRequestProperty(pair.getKey(), pair.getValue());
            }
            catch (Exception ex)
            {
                System.out.println("Failed to add " + pair.getKey() + ".");
            }
        }
    }

    // Get the response
    int responseCode;
    try
    {
        responseCode = con.getResponseCode();

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuilder responseBldr = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) // while we have read another line
        {
            responseBldr.append(line);
        }
        in.close();
        return responseBldr.toString();
    }
    catch (IOException ex)
    {
        System.out.println("Returning null from network IOException.");
        System.out.println(ex.getMessage());
        return null;
    }

【问题讨论】:

  • 你设置了 Content-type header 吗?
  • 我没有设置它。谢谢你。不过,它仍然给我响应 400。这就是我添加内容类型的方法: con.addRequestProperty("Content-type", contentType);
  • 另外preSign 可能不应该包含BASE_URL
  • 看起来你对 BASE_URL 的看法是对的,但它仍然给我回复 400。
  • 也许由于错误 400,您会在响应正文中收到一些文本(错误描述)?

标签: java base64 sha256 hmac


【解决方案1】:

我让这个在本地工作。看起来您正在对签名进行双重编码。

创建签名的步骤是:

  1. 创建构成签名基础的初始字符串
  2. 解码您的密钥以获得 KeySpec (new SecretKeySpec())
  3. 使用密钥规范 (sha256Hmac.init()) 初始化您的 HMAC
  4. 使用密钥对请求签名进行编码 (sha256Hmac.doFinal())
  5. base64 编码步骤 4 的结果。

您在上述 sn-p 中犯的唯一错误是在您的标头中再次对其进行 base64 编码。

HTH

【讨论】:

    猜你喜欢
    • 2017-07-18
    • 2010-10-18
    • 2016-04-29
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 2016-07-13
    • 1970-01-01
    相关资源
    最近更新 更多