如何将输入字符串的 4 字节散列创建为十六进制字符串
How to create 4 byte hash of the input string as a hex string
def hash_string(s):
hsh = bytearray(hashlib.md5(s.encode(encoding="ascii")).digest())
assert len(hsh) == 16
output = \
int.from_bytes(hsh[0:4], "big") ^ \
int.from_bytes(hsh[4:8], "big") ^ \
int.from_bytes(hsh[8:12], "big") ^ \
int.from_bytes(hsh[12:16], "big")
return binascii.hexlify(output.to_bytes(4, byteorder='big')).decode("ascii")
我想在 Java 中做同样的事情。但是我被卡住了,因为我不确定在创建哈希后如何继续。
下面是我在 java
中的代码
private static String hashString(String s) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(s.getBytes());
byte[] digest = md.digest();
System.out.println("Length of hash after md5" +digest.length);
String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println("Length of the stirng" +myHash.getBytes().length);
return myHash;
}
ByteBuffer
has methods that correspond naturally to your python 代码,等效的 Java 看起来像
private static String hashString(String s)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(s.getBytes("US-ASCII"));
byte[] sub1 = Arrays.copyOfRange(digest, 0, 4);
byte[] sub2 = Arrays.copyOfRange(digest, 4, 8);
byte[] sub3 = Arrays.copyOfRange(digest, 8, 12);
byte[] sub4 = Arrays.copyOfRange(digest, 12, 16);
int x1 = java.nio.ByteBuffer.wrap(sub1).getInt();
int x2 = java.nio.ByteBuffer.wrap(sub2).getInt();
int x3 = java.nio.ByteBuffer.wrap(sub3).getInt();
int x4 = java.nio.ByteBuffer.wrap(sub4).getInt();
return DatatypeConverter.printHexBinary(java.nio.ByteBuffer.allocate(4)
.putInt(x1 ^ x2 ^ x3 ^ x4).array());
}
此站点上记录了更高效的 hex encoder;您可以添加以下内容并将上面的最后一行替换为 return bytesToHex(java.nio.ByteBuffer.allocate(4).putInt(x1 ^ x2 ^ x3 ^ x4).array());
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
如果散列是 4 个字节,您可以采用两种方法:
整数转十六进制
您可以将摘要中的字节合并为一个int。然后您可以将 int 转换为十六进制字符串。 注意如果摘要中的字节是小端顺序,那么你将不得不以相反的顺序组合字节。
int digestInt = ((int)digest[0]) & 0xFF;
digestInt = digestInt << 8 | (((int)digest[1]) & 0xFF);
digestInt = digestInt << 8 | (((int)digest[2]) & 0xFF);
digestInt = digestInt << 8 | (((int)digest[3]) & 0xFF);
现在你有了一个整数,你可以通过 Integer.toHexString(digestInt)
.
来创建一个十六进制字符串
十六进制
您可以将每个字节转换为十六进制字符串并附加字符串。
public static String encodeBytesToHex(final byte[] bytes)
{
final StringBuilder sb = new StringBuilder();
for (int byteIndex = 0; byteIndex < bytes.length; byteIndex++) {
final String hexByte = Integer.toHexString(((int)bytes[byteIndex]) & 0xFF);
sb.append(hexByte);
}
return sb.toString();
}
这样做的好处是它适用于任意字节数的散列。
这不需要ByteBuffer
或复杂的逻辑:
// Precondition: (digest.length % 4) == 0
byte[] sh = new byte[digest.length/4];
for (int i=0; i<sh.length; i++)
for (int j=0; j<digest.length; j+=4)
sh[i] ^= digest[i+j];
// Format result as hex
StringBuilder hex = new StringBuilder();
Formatter fmt = new Formatter(hex);
for (byte b : sh) fmt.format("%02x", b);
System.out.println(hex.toString());
def hash_string(s):
hsh = bytearray(hashlib.md5(s.encode(encoding="ascii")).digest())
assert len(hsh) == 16
output = \
int.from_bytes(hsh[0:4], "big") ^ \
int.from_bytes(hsh[4:8], "big") ^ \
int.from_bytes(hsh[8:12], "big") ^ \
int.from_bytes(hsh[12:16], "big")
return binascii.hexlify(output.to_bytes(4, byteorder='big')).decode("ascii")
我想在 Java 中做同样的事情。但是我被卡住了,因为我不确定在创建哈希后如何继续。 下面是我在 java
中的代码 private static String hashString(String s) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(s.getBytes());
byte[] digest = md.digest();
System.out.println("Length of hash after md5" +digest.length);
String myHash = DatatypeConverter.printHexBinary(digest).toUpperCase();
System.out.println("Length of the stirng" +myHash.getBytes().length);
return myHash;
}
ByteBuffer
has methods that correspond naturally to your python 代码,等效的 Java 看起来像
private static String hashString(String s)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(s.getBytes("US-ASCII"));
byte[] sub1 = Arrays.copyOfRange(digest, 0, 4);
byte[] sub2 = Arrays.copyOfRange(digest, 4, 8);
byte[] sub3 = Arrays.copyOfRange(digest, 8, 12);
byte[] sub4 = Arrays.copyOfRange(digest, 12, 16);
int x1 = java.nio.ByteBuffer.wrap(sub1).getInt();
int x2 = java.nio.ByteBuffer.wrap(sub2).getInt();
int x3 = java.nio.ByteBuffer.wrap(sub3).getInt();
int x4 = java.nio.ByteBuffer.wrap(sub4).getInt();
return DatatypeConverter.printHexBinary(java.nio.ByteBuffer.allocate(4)
.putInt(x1 ^ x2 ^ x3 ^ x4).array());
}
此站点上记录了更高效的 hex encoder;您可以添加以下内容并将上面的最后一行替换为 return bytesToHex(java.nio.ByteBuffer.allocate(4).putInt(x1 ^ x2 ^ x3 ^ x4).array());
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
如果散列是 4 个字节,您可以采用两种方法:
整数转十六进制
您可以将摘要中的字节合并为一个int。然后您可以将 int 转换为十六进制字符串。 注意如果摘要中的字节是小端顺序,那么你将不得不以相反的顺序组合字节。
int digestInt = ((int)digest[0]) & 0xFF;
digestInt = digestInt << 8 | (((int)digest[1]) & 0xFF);
digestInt = digestInt << 8 | (((int)digest[2]) & 0xFF);
digestInt = digestInt << 8 | (((int)digest[3]) & 0xFF);
现在你有了一个整数,你可以通过 Integer.toHexString(digestInt)
.
十六进制
您可以将每个字节转换为十六进制字符串并附加字符串。
public static String encodeBytesToHex(final byte[] bytes)
{
final StringBuilder sb = new StringBuilder();
for (int byteIndex = 0; byteIndex < bytes.length; byteIndex++) {
final String hexByte = Integer.toHexString(((int)bytes[byteIndex]) & 0xFF);
sb.append(hexByte);
}
return sb.toString();
}
这样做的好处是它适用于任意字节数的散列。
这不需要ByteBuffer
或复杂的逻辑:
// Precondition: (digest.length % 4) == 0
byte[] sh = new byte[digest.length/4];
for (int i=0; i<sh.length; i++)
for (int j=0; j<digest.length; j+=4)
sh[i] ^= digest[i+j];
// Format result as hex
StringBuilder hex = new StringBuilder();
Formatter fmt = new Formatter(hex);
for (byte b : sh) fmt.format("%02x", b);
System.out.println(hex.toString());