2014-10-13 8 views
10

Ich versuche, die API des Bitcoin Exchange Kraken in Java zu implementieren. Leider bin ich bei dem Versuch, eine Authentifizierung auszuführen, um private Benutzerdaten abzurufen, festgefahren.Kraken API: Probleme mit der Authentifizierung (ungültiger Schlüssel)

Insbesondere ich wurde mit der folgenden Umsetzung spielen: http://pastebin.com/nHJDAbH8 Die Dokumentation der API Krakens hier: https://www.kraken.com/help/api

jedoch bisher erhielt ich nur { „Fehler“: [ „EAPI: ungültige Schlüssel“ ]}. Ich konnte bei der Implementierung keinen Fehler finden und habe verschiedene API-Schlüssel ausprobiert. Könnte sich jemand vielleicht kurz die Implementierung ansehen und nach Fehlern im Code suchen? Oder hat jemand die Kraken API erfolgreich implementiert?

Vielen Dank!

Die Anweisungen zur Authentifizierung sind:

HTTP-Header-: API-Key = API Schlüssel API-Sign = Nachrichtensignatur HMAC-SHA512 von (URI Pfad + SHA256 (Nonce + POST-Daten)) unter Verwendung von und base64 decodiert geheimen API-Schlüssel

Post-Daten: nonce = immer steigende unsigned 64-Bit-integer-oTP = zwei-Faktor-Passwort (falls zwei-Faktor aktiviert, sonst nicht erforderlich) Hinweis: in meinem Fall oTP deaktiviert ist, Post-Daten bestehen also nur aus Nonce.

Die Umsetzung ich mit experimentiert ist:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.io.UnsupportedEncodingException; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.security.InvalidKeyException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 

import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 

import org.apache.commons.codec.binary.Base64; 

public class KrakenClient { 

    protected static String key = "myAPIKey";  // API key 
    protected static String secret = "MySecret===="; // API secret 
    protected static String url = "api.kraken.com";  // API base URL 
    protected static String version = "0"; // API version 


    public static void main(String[] args) throws Exception { 
     queryPrivateMethod("Balance"); 
    } 

    public static void queryPrivateMethod(String method) throws NoSuchAlgorithmException, IOException{ 

     long nonce = System.currentTimeMillis(); 

     String path = "/" + version + "/private/" + method; // The path like "/0/private/Balance" 

     String urlComp = "https://"+url+path; // The complete url like "https://api.kraken.com/0/private/Balance" 

     String postdata = "nonce="+nonce; 

     String sign = createSignature(nonce, path, postdata); 

     postConnection(urlComp, sign, postdata); 
    } 

    /** 
    * @param nonce 
    * @param path 
    * @param postdata 
    * @return 
    * @throws NoSuchAlgorithmException 
    * @throws IOException 
    */ 
    private static String createSignature(long nonce, String path, 
      String postdata) throws NoSuchAlgorithmException, IOException { 

     return hmac(path+sha256(nonce + postdata), new String(Base64.decodeBase64(secret))); 
    } 

    public static String sha256Hex(String text) throws NoSuchAlgorithmException, IOException{ 
     return org.apache.commons.codec.digest.DigestUtils.sha256Hex(text); 
    } 

    public static byte[] sha256(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException{ 
     MessageDigest md = MessageDigest.getInstance("SHA-256"); 

     md.update(text.getBytes()); 
     byte[] digest = md.digest(); 

     return digest; 
    } 

    public static void postConnection(String url1, String sign, String postData) throws IOException{ 

     URL url = new URL(url1); 
     HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 

     connection.addRequestProperty("API-Key", key); 
     connection.addRequestProperty("API-Sign", Base64.encodeBase64String(sign.getBytes())); 
     //  connection.addRequestProperty("API-Sign", sign); 
     connection.addRequestProperty("User-Agent", "Mozilla/4.0"); 
     connection.setRequestMethod("POST"); 
     connection.setDoInput(true); 
     connection.setDoOutput(true); 
     connection.setUseCaches(false); 
     //  connection.setRequestProperty("Content-Type", 
     //    "application/x-www-form-urlencoded"); 
     connection.setRequestProperty("Content-Length", String.valueOf(postData.length())); 

     OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); 
     writer.write(postData); 
     writer.flush(); 


     BufferedReader reader = new BufferedReader(
       new InputStreamReader(connection.getInputStream())); 

     for (String line; (line = reader.readLine()) != null;) 
     { 
      System.out.println(line); 
     } 

     writer.close(); 
     reader.close(); 
    } 


    public static String hmac(String text, String secret){ 

     Mac mac =null; 
     SecretKeySpec key = null; 

     // Create a new secret key 
     try { 
      key = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA512"); 
     } catch(UnsupportedEncodingException uee) { 
      System.err.println("Unsupported encoding exception: " + uee.toString()); 
      return null; 
     } 
     // Create a new mac 
     try { 
      mac = Mac.getInstance("HmacSHA512"); 
     } catch(NoSuchAlgorithmException nsae) { 
      System.err.println("No such algorithm exception: " + nsae.toString()); 
      return null; 
     } 

     // Init mac with key. 
     try { 
      mac.init(key); 
     } catch(InvalidKeyException ike) { 
      System.err.println("Invalid key exception: " + ike.toString()); 
      return null; 
     } 


     // Encode the text with the secret 
     try { 

      return new String(mac.doFinal(text.getBytes("UTF-8"))); 
     } catch(UnsupportedEncodingException uee) { 
      System.err.println("Unsupported encoding exception: " + uee.toString()); 
      return null; 
     } 
    } 
} 

Antwort

-4

Entfernen Sie die "/" Präfix des Pfadvariablen.

String path = version + "/private/" + method; // The path like "0/private/Balance" 
2

Hier ist, wie ich habe es mit Haskell arbeiten:

signature body nonce path secret = convertToBase Base64 hmacsha512 
    where 
    sha256 = convert (hash $ nonce `append` body :: Digest SHA256) 
    hmacsha512 = hmac secretd (path `append` sha256) :: HMAC SHA512 
    secretd = fromRight $ convertFromBase Base64 secret :: ByteString 

Also Sie brauchen:

  • erhalten SHA256 Hash nonce + body, dh SHA256("1487687774151000nonce=1487687774151000")
  • roh anhängen Bytes von Digest zu path (Ergebnis wäre nicht druckbar, Beispielpfad für Balance-Methode ist "/0/private/Balance"),
  • erhalten HMAC SHA512 Digest mit Base64-decodierten secret,
  • codieren zu Base64.
Verwandte Themen