gpt4 book ai didi

java - 使用带有 key 的 ripemd160 在 Java 中模拟 php 函数 hash_hmac 中的字符串哈希

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:24:49 25 4
gpt4 key购买 nike

我正在尝试使用 ripemd160 对 Java 中的字符串进行哈希处理,以模拟以下 php 的输出:

$string = 'string';
$key = 'test';

hash_hmac('ripemd160', $string, $key);

// outputs: 37241f2513c60ae4d9b3b8d0d30517445f451fa5


尝试 1

最初我尝试使用以下方法来模拟它...但是我不认为可以使用 ripemd160 作为 getInstance` 算法?

或者可能是,我只是没有在本地启用它?

public String signRequest(String uri, String secret) {
try {

byte[] keyBytes = secret.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");

Mac mac = Mac.getInstance("ripemd160");
mac.init(signingKey);

// Compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(uri.getBytes());

// Convert raw bytes to Hex
byte[] hexBytes = new Hex().encode(rawHmac);

// Covert array of Hex bytes to a String
return new String(hexBytes, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}

尝试 2

这促使我寻找其他方法来完成上述任务,通过 SO 和 Google,我发现查看 BouncyCaSTLe 可能是更好的方法。

然后我发现这篇文章讨论了使用我想要的相同算法的散列以及 BouncyCaSTLe,它只是不使用 key 。 ( Cannot output correct hash in Java. What is wrong? )

public static String toRIPEMD160(String in) {
try {
byte[] addr = in.getBytes();
byte[] out = new byte[20];
RIPEMD160Digest digest = new RIPEMD160Digest();

byte[] rawSha256 = sha256(addr);
String encodedSha256 = getHexString(rawSha256);
byte[] strBytes = base64Sha256.getBytes("UTF-8");
digest.update(strBytes, 0, strBytes.length);

digest.doFinal(out, 0);
return getHexString(out);
} catch (UnsupportedEncodingException ex) {
return null;
}
}

我已经按预期工作了。

问题

您会注意到,在尝试 2 中,目前无法为散列提供 key ,我的问题是如何调整此函数以提供 key 并完成我需要做的最后阶段才能模拟原始 php 函数:hash_hmac('ripemd160', $string, $key);

最佳答案

使用 Bouncy CaSTLe 的 RIPEMD160 没问题,但您必须实现 HMAC ,而不仅仅是散列您的数据。 HMac 它只是 H(K XOR opad, H(K XOR ipad, text)),其中 H 是你的哈希函数,K 是secret、text 消息和 opadipad 是预定义的常量。为了演示它是如何工作的,我从 Python's implementation 翻译了以下内容:

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 中实现了该算法, 所以这段代码的一个较短的变体是

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");
}

关于java - 使用带有 key 的 ripemd160 在 Java 中模拟 php 函数 hash_hmac 中的字符串哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39568562/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com