从消息摘要中获取MD5字符串

38

我知道它的工作原理,但如果我想将MD5打印为字符串,我该如何做?

public static void getMD5(String fileName) throws Exception{
    InputStream input =  new FileInputStream(fileName);
    byte[] buffer = new byte[1024];

    MessageDigest hash = MessageDigest.getInstance("MD5");
    int read;
    do {
        read = input.read(buffer);
        if (read > 0) {
            hash.update(buffer, 0, read);
        }
    } while (read != -1);
    input.close();
}
11个回答

79

写得更少也能获得它:

String hex = (new HexBinaryAdapter()).marshal(md5.digest(YOUR_STRING.getBytes()))

1
你知道这里是否有任何性能考虑吗?假设我们重用一个单独的HexBinaryAdapter,与自己执行位操作相比,是否会引入任何显着的开销?我们需要经常使用此代码,因为我们将MD5用作URL的键,以进入图像缓存。 - Dan J
14
Java的源代码是公开的。HexBinaryAdapter.marshal()只调用了DatatypeConverter.printHexBinary()(如果您想避免实例化HexBinaryAdapter,实际上可以直接使用它),然后DatatypeConverter.printHexBinary()在第一次调用时实例化一个单例的DatatypeConverterImpl。之后,就是对DatatypeConverterImplprintHexBinary方法的直接调用。它使用的方法与WhiteFang34的答案非常相似。 - mpontes
5
HexBinaryAdapter在JDK9中不存在。 - user1133275

29
    String input = "168";
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] md5sum = md.digest(input.getBytes());
    String output = String.format("%032X", new BigInteger(1, md5sum));
或者
DatatypeConverter.printHexBinary( MessageDigest.getInstance("MD5").digest("a".getBytes("UTF-8")))

2
DatatypeConverter不在JDK9中。 - user1133275
@user1133275 请查看 https://dev59.com/TFcP5IYBdhLWcg3w8uhi - stacker
是的,我刚刚看了一下那个库的临时解决方案,但对于这个问题,不依赖于已弃用代码的答案更好。 - user1133275
1
当前 BigInteger 在十六进制表示中,若最高位是 0 则存在问题。 - harley

23

试试这个

StringBuffer hexString = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest();

for (int i = 0; i < hash.length; i++) {
    if ((0xff & hash[i]) < 0x10) {
        hexString.append("0"
                + Integer.toHexString((0xFF & hash[i])));
    } else {
        hexString.append(Integer.toHexString(0xFF & hash[i]));
    }
}

2
请注意,现在可以使用StringBuilder代替StringBuffer,在这个问题中讨论了每个的优缺点:https://dev59.com/dnRC5IYBdhLWcg3wROzk - FanaticD

23

您还可以使用Apache Commons Codec库。该库包含在DigestUtils类中的方法public static String md5Hex(InputStream data)public static String md5Hex(byte[] data)

无需自行编写此功能;)


9

首先你需要获取MessageDigestbyte[]输出:

byte[] bytes = hash.digest();

然而,你无法轻松地打印这个内容(例如使用new String(bytes)),因为它将包含二进制数据,没有很好的输出表示。但是,你可以将其转换为十六进制以便显示,如下所示:

StringBuilder sb = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
    sb.append("0123456789ABCDEF".charAt((b & 0xF0) >> 4));
    sb.append("0123456789ABCDEF".charAt((b & 0x0F)));
}
String hex = sb.toString();

感谢提到实际问题,对于字节字符串的第一个想法就是使用字符串构造函数。此外,我很惊讶没有人建议使用Base64。Base64与这些HexToBinary答案相比如何? - Teddy
找到了这个:https://dev59.com/7XA75IYBdhLWcg3wo6vx#3183880 - Teddy

7

最短的方法:

String toMD5(String input) {
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] raw = md.digest(input.getBytes());
    return DatatypeConverter.printHexBinary(raw);
}

请记得处理异常。


4

使用消息摘要的字节数组结果:

...
byte hashgerado[] = md.digest(entrada);
...

for(byte b : hashgerado)
    System.out.printf("%02x", Byte.toUnsignedInt(b));

结果(例如):
89e8a9f68ad3c4bba9b9d3581cf5201d


2

提供信息...

在某些情况下,这对我不起作用

md5 = new java.math.BigInteger(1, digest.digest()).toString(16);

但是这样做

StringBuilder sb = new StringBuilder();

for (int i = 0; i < digest.length; i++) {
    if ((0xff & digest[i]) < 0x10) {
        sb.append("0").append(Integer.toHexString((0xFF & digest[i])));
    } else {
        sb.append(Integer.toHexString(0xFF & digest[i]));
    }
}

String result = sb.toString();

1
欢迎来到 Stack Overflow,@WillBerger!虽然这段代码可能回答了问题,但提供有关它如何解决问题以及为什么解决问题的额外上下文会提高答案的长期价值。 - mech

2
/**
 * hashes:
 * e7cfa2be5969e235138356a54bad7fc4
 * 3c9ec110aa171b57bb41fc761130822c
 *
 * compiled with java 8 - 12 Dec 2015
 */
public static String generateHash() {
    long r = new java.util.Random().nextLong();
    String input = String.valueOf(r);
    String md5 = null;

    try {
        java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
        //Update input string in message digest
        digest.update(input.getBytes(), 0, input.length());
        //Converts message digest value in base 16 (hex)
        md5 = new java.math.BigInteger(1, digest.digest()).toString(16);
    }
    catch (java.security.NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return md5;
}

-1

调用hash.digest()来完成该过程。它将返回一个字节数组。

您可以使用String构造函数从byte[]创建一个字符串,但是如果您想要一个十六进制字符串,则必须手动遍历字节数组并计算字符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接