【问题标题】:How can I calculate the SHA-256 hash of a string in Android?如何在 Android 中计算字符串的 SHA-256 哈希?
【发布时间】:2011-11-02 05:27:46
【问题描述】:

我正在尝试在 Android 中获取字符串的 SHA256。

这是我要匹配的 PHP 代码:

echo bin2hex(mhash(MHASH_SHA256,"asdf"));
//outputs "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b"

现在,在 Java 中,我正在尝试执行以下操作:

            String password="asdf"
            MessageDigest digest=null;
    try {
        digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
       digest.reset();
       try {
        Log.i("Eamorr",digest.digest(password.getBytes("UTF-8")).toString());
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

但打印出来的是:“a42yzk3axdv3k4yh98g8”

我在这里做错了什么?


感谢埃里克森的解决方案:

 Log.i("Eamorr",bin2hex(getHash("asdf")));

 public byte[] getHash(String password) {
       MessageDigest digest=null;
    try {
        digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
       digest.reset();
       return digest.digest(password.getBytes());
 }
static String bin2hex(byte[] data) {
    return String.format("%0" + (data.length*2) + "X", new BigInteger(1, data));
}

【问题讨论】:

  • 我认为您的问题可能是 getBytes(UTF-8)。试试 getBytes()。
  • 为什么任何人都应该在不指定编码的情况下使用getBytes()
  • @Eamorr:你能把解决方案放在答案而不是问题中吗?
  • 作为解决方案的代码不起作用...有什么帮助吗?
  • 一个干净的答案写在这里:stackoverflow.com/questions/9661008/…

标签: java php android digest sha


【解决方案1】:

PHP 函数bin2hex 表示它接受一串字节并将其编码为十六进制数。

在 Java 代码中,您尝试获取一堆随机字节并使用您平台的默认字符编码将它们解码为字符串。那是行不通的,如果这样做了,也不会产生相同的结果。

这是一个用于 Java 的快速而简单的二进制到十六进制转换:

static String bin2hex(byte[] data) {
    StringBuilder hex = new StringBuilder(data.length * 2);
    for (byte b : data)
        hex.append(String.format("%02x", b & 0xFF));
    return hex.toString();
}

编写很快,执行起来不一定很快。如果你做了很多这些,你应该用更快的实现重写函数。

【讨论】:

  • @Eamorr:实际上,埃里克森还没有“传奇”徽章:-p
  • 实际上,new BigInteger(1, data).toString(16) 是您在摘要函数数据的情况下所需要的,因为它保证没有半字节会充满 0。跨度>
  • @ClassStacker 0x35326b9705d136d0d1b5efa92d440f3171f1b711 的 SHA-1 哈希是多少?
  • @erickson 我肯定会因为声称没有任何 nibble 永远不会是零而受到指责,但是你去吧;根据 python 它是 \x00P\xd5\rv\xc8\x15u\x84*\xf3\x1d\xc3L\x9b\x14{\xedX?我站在这里有罪。感谢您指出这一点。
  • @ClassStacker 没问题。 SHA-1 和 SHA-2 哈希,我假设任何加密摘要,可以产生零 nybbles 和字节,包括前导零。我没想到会这样,但是当你说不可能时,没过多久就验证了我的假设。
【解决方案2】:

您的思路是正确的,但是转换字节有点复杂。这适用于我的设备:

// utility function
    private static String bytesToHexString(byte[] bytes) {
        // http://stackoverflow.com/questions/332079
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

// generate a hash

    String password="asdf";
    MessageDigest digest=null;
    String hash;
    try {
        digest = MessageDigest.getInstance("SHA-256");
        digest.update(password.getBytes());

        hash = bytesToHexString(digest.digest());

        Log.i("Eamorr", "result is " + hash);
    } catch (NoSuchAlgorithmException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

来源:bytesToHexString 函数来自IOSched 项目。

【讨论】:

  • 小心:您从 IOSched 项目中获取的 bytesToHexString 函数以小写格式返回字符串。当通过执行 SHA256(SHA256...(SHA256(input)...) 链接它时,您会从以大写格式返回字符串的实现中获得不同的结果。这可以通过将负责的行链接到 @987654323 来轻松解决@
【解决方案3】:

使用示例的完整答案,感谢埃里克森。

把它放到你的“Utils”类中。

public static String getSha256Hash(String password) {
    try {
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e1) {
            e1.printStackTrace();
        }
        digest.reset();
        return bin2hex(digest.digest(password.getBytes()));
    } catch (Exception ignored) {
        return null;
    }
}

private static String bin2hex(byte[] data) {
    StringBuilder hex = new StringBuilder(data.length * 2);
    for (byte b : data)
        hex.append(String.format("%02x", b & 0xFF));
    return hex.toString();
}

使用示例:

Toast.makeText(this, Utils.getSha256Hash("123456_MY_PASSWORD"), Toast.LENGTH_SHORT).show();

【讨论】:

    【解决方案4】:

    我知道这个问题已经得到解答,但我在android arsenal 找到了一个哈希库,它非常简单,只需一行代码。可以散列 MD5、SHA-1、SHA-256、SHA-384 或 SHA-512。

    1. 首先将其添加到您的 gradle 并同步

      implementation 'com.github.1AboveAll:Hasher:1.2'

    2. 开始拥有

      Hasher.Companion.hash("Hello",HashType.SHA_1);

    【讨论】:

      猜你喜欢
      • 2012-08-16
      • 2011-03-07
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2015-08-21
      • 2014-08-29
      • 2019-07-21
      相关资源
      最近更新 更多