使用 Bouncy Castle 的 RIPEMD160 很好,但你必须实施HMAC https://www.ietf.org/rfc/rfc2104.txt,而不仅仅是散列您的数据。 HMac 只是H(K XOR opad, H(K XOR ipad, text))
, where H
是你的哈希函数,K
是秘密,text
消息和opad
and ipad
是预定义的常数。为了演示它是如何工作的,我翻译了以下内容Python的实现 https://hg.python.org/cpython/file/2.7/Lib/hmac.py:
public static String signRequest(String uri, String secret) throws Exception {
byte[] r = uri.getBytes("US-ASCII");
// The keys must have the same block size as your hashing algorithm, in this case
// 64 bytes right-padded with zeros.
byte[] k_outer = new byte[64];
System.arraycopy(secret.getBytes("US-ASCII"), 0, k_outer, 0,
secret.getBytes("US-ASCII").length);
byte[] k_inner = new byte[64];
System.arraycopy(secret.getBytes("US-ASCII"), 0, k_inner, 0,
secret.getBytes("US-ASCII").length);
// You'll create two nested hashes. The inner one is initialized with the
// key xor 0x36 (byte-wise), the other one with the key xor 0x5c.
for(int i=0; i<k_outer.length; i++)
k_outer[i] ^= 0x5c;
for(int i=0; i<k_inner.length; i++)
k_inner[i] ^= 0x36;
// Update inner hash with the key and data you want to sign
RIPEMD160Digest d_inner = new RIPEMD160Digest();
d_inner.update(k_inner, 0, k_inner.length);
d_inner.update(r, 0, r.length);
// Update outer hash with the key and the inner hash
RIPEMD160Digest d_outer = new RIPEMD160Digest();
d_outer.update(k_outer, 0, k_outer.length);
byte[] o_inner = new byte[d_inner.getDigestSize()];
d_inner.doFinal(o_inner, 0);
d_outer.update(o_inner, 0, o_inner.length);
// Finally, return the hex-encoded hash
byte[] o_outer = new byte[d_inner.getDigestSize()];
d_outer.doFinal(o_outer, 0);
return new String((new Hex()).encode(o_outer), "US-ASCII");
}
Bouncy Castle 在其中实现了该算法HMac class https://people.eecs.berkeley.edu/~jonah/bc/org/bouncycastle/crypto/macs/HMac.html,所以这段代码的一个较短的变体是
public static String signRequest(String uri, String secret) throws Exception {
byte[] r = uri.getBytes("US-ASCII");
byte[] k = secret.getBytes("US-ASCII");
HMac hmac = new HMac(new RIPEMD160Digest());
hmac.init(new KeyParameter(k));
hmac.update(r, 0, r.length);
byte[] out = new byte[hmac.getMacSize()];
hmac.doFinal(out, 0);
return new String((new Hex()).encode(out), "US-ASCII");
}