0

good Morning to everyone, I have this problem: I need to do a API auth with java, i have this example in C#:

protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    HttpResponseMessage response = null;
    string requestContentBase64String = string.Empty;

    string requestUri = HttpUtility.UrlEncode(request.RequestUri.AbsoluteUri.ToLower());

    string requestHttpMethod = request.Method.Method;

    DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
    TimeSpan timeSpan = DateTime.UtcNow - epochStart;
    string requestTimeStamp = Convert.ToUInt64(timeSpan.TotalSeconds).ToString();

    ASCIIEncoding encoder = new ASCIIEncoding();
    Byte[] code = encoder.GetBytes(APIKey);

    HMACSHA256 hmSha1 = new HMACSHA256(code);
    Byte[] hashMe = encoder.GetBytes(requestTimeStamp);

    Byte[] hmBytes = hmSha1.ComputeHash(hashMe);

    request.Headers.Add("APIKey", APPId);
    request.Headers.Add("Nonce", requestTimeStamp);
    request.Headers.Add("Signature", ToHexString(hmBytes));

    response = await base.SendAsync(request, cancellationToken);

    return response;
}

And my example in java is:

public String amx_authorization_header(String funcao) throws UnsupportedEncodingException, IOException, InvalidKeyException, NoSuchAlgorithmException {
    //Definições de funcao, ID e password para acessar a API
    String endereco = "https://broker.negociecoins.com.br/tradeapi/v1/" + funcao;
    String urlString = URLEncoder.encode(endereco, "UTF-8").toLowerCase();
    String ID = "youID";
    String pass = "Youpass";
    String result = "";
    URL url;
    BufferedReader reader = null;
    String requestContentBase64String = "";
    HttpsURLConnection urlConnection = null;

    //Configurações para acesso a URL
    System.out.println("URL: " + urlString);
    url = new URL(endereco);
    urlConnection = (HttpsURLConnection) url.openConnection();
    urlConnection.setRequestMethod("GET");
    urlConnection.setConnectTimeout(5000);

    //Calculando UNIX Time: Gerando um requestTimeStamp
    Date epochStart = new Date(1970 - 1900, 01, 01, 01, 01, 01);
    //epochStart.set(1970 + 1900, 01, 01, 01, 01, 01);
    //epochStart.setTimeZone(TimeZone.getTimeZone("UTC"));
    System.out.println("epochStart: " + epochStart.toString());
    String requestTimeStamp = "" + ((new Date().getTime() - epochStart.getTime()) / 1000);
    System.out.println("TimeStamp: " + requestTimeStamp);

    //Gerando um Nonce
    Integer n = new Random().nextInt(10000000);
    String nonce = n.toString();
    System.out.println("Nonce: " + nonce.toString());
    String signatureRawData = String.format("%s%s%s%s%s%s", ID, urlConnection.getRequestMethod(),
            urlString, requestTimeStamp, nonce, "");
    System.out.println("SignatureRawData: " + signatureRawData);
    //Tratamento do password para SHA256
    //BASE64Decoder decoder = new BASE64Decoder();
    //pass.getBytes(StandardCharsets.UTF_8);
    byte[] secretKeyByteArray = Base64.getDecoder().decode(pass.getBytes(StandardCharsets.UTF_8));

    //ArrayList<byte> teste = new ArrayList();
    int semsinal[] = new int[secretKeyByteArray.length];
    for(int i = 0; i<secretKeyByteArray.length;i++){
    //System.out.println("Unsigned byte: " + (secretKeyByteArray[i] & 0xFF));
    semsinal[i] = secretKeyByteArray[i] & 0xFF;
    }
    byte[] signature = signatureRawData.getBytes("UTF-8");

    Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secret_key = new SecretKeySpec(secretKeyByteArray, "HmacSHA256");
    sha256_HMAC.init(secret_key);
    byte[] signatureBytes = sha256_HMAC.doFinal(signature);
    String requestSignatureBase64String = Base64.getEncoder().encodeToString(signatureBytes);
    System.out.println("requestSignatureBase64String: " + requestSignatureBase64String);
    //Preparando HEADER para ser enviado na autenticação
    String header = String.format("amx %s:%s:%s:%s", ID, requestSignatureBase64String, nonce, requestTimeStamp); //Formato Header
    System.out.println("Formato HEADER: " + header);
    //Envio da autenticação para a Conexão
    urlConnection.setRequestProperty("Authorization", header);
    urlConnection.setRequestProperty("User-Agent", "");
    //urlConnection.connect();

    //Leitura do retorno da API
    reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
    StringBuffer buffer = new StringBuffer();
    int read;
    char[] chars = new char[1024];
    while ((read = reader.read(chars)) != -1) {
        buffer.append(chars, 0, read);
    }

    return buffer.toString();

}

But, the return of authentication in java is: Exception in thread "main" java.io.IOException: Server returned HTTP response code: 401 for URL: https://.......

Someone have one idea of this problem?

SkyWorker
  • 21
  • 5
  • There is no problem. Bytes are bytes, until you want to choose a representation for it. For example binary is the same, hex is the same, it's when you get to decimal representation you can decide if you want to represent them as signed or unsigned. – Kayaman Nov 14 '17 at 11:51
  • Hello Kayaman, thanks for help, but, the problem is on SecretKeySpec method, i need to encrypt using it, but byte in java use signed byte... – SkyWorker Nov 14 '17 at 11:55
  • I told you there's no problem. `0xFF` == `-1` == `255` == `11111111`. You don't need to do anything, the code shown in your question works. If it doesn't work, the reason is not with signed vs. unsigned bytes. – Kayaman Nov 14 '17 at 12:01
  • I trying make this code in Java: https://developer.allscripts.com/Content/fhir/content/amx_auth_header/index.html – SkyWorker Nov 14 '17 at 14:05

0 Answers0