简体   繁体   English

如何在Android中散列字符串?

[英]How to hash a string in Android?

I am working on an Android app and have a couple strings that I would like to encrypt before sending to a database. 我正在开发一个Android应用程序,并且在发送到数据库之前有一些我想要加密的字符串。 I'd like something that's secure, easy to implement, will generate the same thing every time it's passed the same data, and preferably will result in a string that stays a constant length no matter how large the string being passed to it is. 我想要一些安全,易于实现的东西,每次传递相同的数据时都会生成相同的东西,并且最好会产生一个字符串,无论传递给它的字符串有多大,它都会保持不变。 Maybe I'm looking for a hash. 也许我正在寻找哈希。

This snippet calculate md5 for any given string 此代码段为任何给定字符串计算md5

public String md5(String s) {
    try {
        // Create MD5 Hash
        MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
        digest.update(s.getBytes());
        byte messageDigest[] = digest.digest();

        // Create Hex String
        StringBuffer hexString = new StringBuffer();
        for (int i=0; i<messageDigest.length; i++)
            hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
        return hexString.toString();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

Source: http://www.androidsnippets.com/snippets/52/index.html 资料来源: http//www.androidsnippets.com/snippets/52/index.html

Hope this is useful for you 希望这对你有用

That function above from ( http://www.androidsnippets.org/snippets/52/index.html ) is flawed. 来自( http://www.androidsnippets.org/snippets/52/index.html )的上述功能存在缺陷。 If one of the digits in the messageDigest is not a two character hex value (ie 0x09), it doesn't work properly because it doesn't pad with a 0. If you search around you'll find that function and complaints about it not working. 如果messageDigest中的一个数字不是两个字符的十六进制值(即0x09),则它无法正常工作,因为它没有填0。如果你四处搜索,你会发现它的功能和抱怨不工作 Here a better one found in the comment section of this page , which I slightly modified: 这是一个更好的在本页的评论部分找到 ,我稍作修改:

public static String md5(String s) 
{
    MessageDigest digest;
    try
    {
        digest = MessageDigest.getInstance("MD5");
        digest.update(s.getBytes(Charset.forName("US-ASCII")),0,s.length());
        byte[] magnitude = digest.digest();
        BigInteger bi = new BigInteger(1, magnitude);
        String hash = String.format("%0" + (magnitude.length << 1) + "x", bi);
        return hash;
    }
    catch (NoSuchAlgorithmException e)
    {
        e.printStackTrace();
    }
    return "";
}

not working method: 不工作的方法:

public static String md5(String s) {
    try {
        // Create MD5 Hash
        MessageDigest digest = java.security.MessageDigest
                .getInstance("MD5");
        digest.update(s.getBytes());
        byte messageDigest[] = digest.digest();

        // Create Hex String
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < messageDigest.length; i++)
            hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
        return hexString.toString();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

result: 1865e62e7129927f6e4cd9bff104f0 (length 30) 结果: 1865e62e7129927f6e4cd9bff104f0 (长度30)

working method: 工作方式:

public static final String md5(final String toEncrypt) {
    try {
        final MessageDigest digest = MessageDigest.getInstance("md5");
        digest.update(toEncrypt.getBytes());
        final byte[] bytes = digest.digest();
        final StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(String.format("%02X", bytes[i]));
        }
        return sb.toString().toLowerCase();
    } catch (Exception exc) {
        return ""; // Impossibru!
    }
}

result: 1865e62e7129927f6e4c0d9bff1004f0 (length 32) 结果: 1865e62e7129927f6e4c0d9bff1004f0 (长度32)

private static char[] hextable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

public static String byteArrayToHex(byte[] array) {
    String s = "";
    for (int i = 0; i < array.length; ++i) {
        int di = (array[i] + 256) & 0xFF; // Make it unsigned
        s = s + hextable[(di >> 4) & 0xF] + hextable[di & 0xF];
    }
    return s;
}

public static String digest(String s, String algorithm) {
    MessageDigest m = null;
    try {
        m = MessageDigest.getInstance(algorithm);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return s;
    }

    m.update(s.getBytes(), 0, s.length());
    return byteArrayToHex(m.digest());
}

public static String md5(String s) {
    return digest(s, "MD5");
}

With @Donut solution, with UTF-8 encoded characters (eg: é) you have to use getBytes("UTF-8") . 使用@Donut解决方案,使用UTF-8编码字符(例如:é),您必须使用getBytes("UTF-8") Here is my correction of the digest method: 这是我对摘要方法的更正:

private static char[] hextable = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};


public static String byteArrayToHex(byte[] array) {
    String s = "";
    for (int i = 0; i < array.length; ++i) {
        int di = (array[i] + 256) & 0xFF; // Make it unsigned
        s = s + hextable[(di >> 4) & 0xF] + hextable[di & 0xF];
    }
    return s;
}

public static String digest(String s, String algorithm) {
    MessageDigest m = null;
    try {
        m = MessageDigest.getInstance(algorithm);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return s;
    }

    try {
        m.update(s.getBytes("UTF-8"));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        m.update(s.getBytes());
    }
    return byteArrayToHex(m.digest());
}

public static String md5(String s) {
    return digest(s, "MD5");
}

The answer above is almost 100% correct. 上面的答案几乎100%正确。 It will fail with unicode. 它会因unicode而失败。

    MessageDigest digest;
    try {
        digest = MessageDigest.getInstance("MD5");
        byte utf8_bytes[] = tag_xml.getBytes();
        digest.update(utf8_bytes,0,utf8_bytes.length);
        hash = new BigInteger(1, digest.digest()).toString(16);
    } 
    catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

Need the length from the byte array not the string. 需要字节数组的长度而不是字符串。

Donut's solution in a single function: 甜甜圈的单一功能解决方案:

private static char[] hextable = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

private static String md5(String s)
{
    MessageDigest digest;
    try
    {
        digest = MessageDigest.getInstance("MD5");
        digest.update(s.getBytes(), 0, s.length());
        byte[] bytes = digest.digest();

        String hash = "";
        for (int i = 0; i < bytes.length; ++i)
        {
            int di = (bytes[i] + 256) & 0xFF;
            hash = hash + hextable[(di >> 4) & 0xF] + hextable[di & 0xF];
        }

        return hash;
    }
    catch (NoSuchAlgorithmException e)
    {
    }

    return "";
}

The following worked for me on Android without truncating any 0's infront: 以下在Android上为我工作,没有截断任何0的前面:

MessageDigest md = null;
String digest = null;
    try {
        md = MessageDigest.getInstance("MD5");

        byte[] hash = md.digest(myStringToEncode.getBytes("UTF-8")); //converting byte array to Hexadecimal String
        StringBuilder sb = new StringBuilder(2*hash.length);

        for(byte b : hash){
            sb.append(String.format("%02x", b&0xff));
        }

        digest = sb.toString();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

return digest;

If you didn't have security constraints and just wanted to convert String to a unique int. 如果您没有安全约束,只想将String转换为唯一的int。 I'm writing it because that what I looked for and reached here. 我正在写它,因为我在这里找到并到达了。

String my_key
int my_key.hashCode()

if you have up to 10 chars it will even be unique See also https://stackoverflow.com/a/17583653/1984636 如果你有多达10个字符,它甚至是唯一的参见https://stackoverflow.com/a/17583653/1984636

This not missing '0' 这不会错过'0'

  public static String md5(String string) {
        if (TextUtils.isEmpty(string)) {
            return "";
        }
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(string.getBytes());
            String result = "";
            for (byte b : bytes) {
                String temp = Integer.toHexString(b & 0xff);
                if (temp.length() == 1) {
                    temp = "0" + temp;
                }
                result += temp;
            }
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
MessageDigest md = MessageDigest.getInstance("MD5"); 
md.update('yourstring');
byte[] digest = md.digest();
StringBuffer sb = new StringBuffer();
for (byte b : digest) {
    sb.append(String.format("%02x", (0xFF & b)));
}

It's late for the author, but before this, I get Integer.toHexString(0xff&b) , which strips leading 0s from the hex string. 对于作者来说已经晚了,但在此之前,我得到了Integer.toHexString(0xff&b) ,它从十六进制字符串中删除前导0。 It makes me struggled for a long time. 这让我挣扎了很长时间。 Hope useful for some guys. 希望对一些人有用。

if you are using guava: 如果你使用番石榴:

public String generateMd5(String input) {
    HashFunction hf = Hashing.md5();
    Hasher hasher = hf.newHasher();

    HashCode hc = hasher.putString(input, StandardCharsets.UTF_8).hash();

    return hc.toString();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM