- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在尝试用 Java 实现比特币交易所 Kraken 的 API。不幸的是,我在尝试执行身份验证以检索私有(private)用户数据时遇到了困难。
特别是,我正在使用以下实现: http://pastebin.com/nHJDAbH8Kraken API 的文档在这里:https://www.kraken.com/help/api
然而,到目前为止我只收到了 {"error":["EAPI:Invalid key"]} 。我在实现中找不到任何错误,并且尝试了几种不同的 API key 。有人可以快速查看实现并查找代码中的缺陷吗?或者有人成功实现了 Kraken API?
非常感谢!
身份验证的说明是:
HTTP-Header: API-Key = API key API-Sign = Message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data)) and base64 decoded secret API key
Post data: nonce = always increasing unsigned 64 bit integer otp = two-factor password (if two-factor enabled, otherwise not required) Note: in my case otp is disabled, so post-data consists only of nonce.
我正在试验的实现是:
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;
}
}
}
最佳答案
以下是我如何使用 Haskell 实现它:
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
所以你需要:
nonce + body
的 SHA256 哈希,即 SHA256("1487687774151000nonce=1487687774151000")
路径
(结果将无法打印,平衡方法的示例路径为"/0/private/Balance"
),secret
获取 HMAC SHA512 摘要,关于java - 海怪 API : Problems with authentication (Invalid key),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26347706/
GIT merge 引入了一个新的提交。这会导致“git blame”出现问题: merge 的行似乎是由进行 merge 的开发人员提交的。 我可以理解这是冲突更改的情况(因为他解决了冲突)。但是有
我正在尝试创建一个弹出窗口,让用户可以在单击删除按钮时选择点击“确定”或“取消”。但是,即使用户按下取消,它仍然会删除它。不知道我能做什么。使用 AngularJS 有什么奇怪的事情吗?这是我的代码:
我是一名优秀的程序员,十分优秀!