0

我四处搜索如何对设备标识符进行哈希处理,并偶然发现了以下代码。

我真的不明白它在做什么。

  1. 为什么我需要对设备 ID 进行 urlEncode 编码?
  2. 为什么我需要散列字节,我不能只在 String 上这样做吗?
  3. 为什么我需要将其转换为 BigInteger ?
  4. 为什么我需要移动位以获取带有散列 id 的字符串?

谁能逐行解释发生了什么?我希望这也能帮助其他人理解这个在博客和论坛中传播的片段。

String hashedId = "";

String deviceId = urlEncode(Secure.getString(context.getContentResolver(), Secure.ANDROID_ID));

try {
    MessageDigest digest = MessageDigest.getInstance("SHA-1");

    byte bytes[] = digest.digest(deviceId.getBytes());

    BigInteger b = new BigInteger(1, bytes);
    hashedId = String.format("%0" + (bytes.length << 1) + "x", b);

} catch (NoSuchAlgorithmException e) {
    //ignored
}

return hashedId;
4

4 回答 4

3

为什么我需要对设备 ID 进行 urlEncode 编码?

为什么我需要散列字节,我不能只在 String 上这样做吗?

大多数散列算法,包括 SHA-1,都使用二进制数据作为输入(即字节)。字符串本身没有特定的二进制表示;它根据编码而变化。

他们提供的代码行使用默认编码,这有点脆弱。我希望看到类似的东西

byte bytes[] = digest.digest(deviceId.getBytes(Charset.forName("UTF-8")));

为什么我需要将其转换为 BigInteger ?

这是为了方便帮助转换为十六进制表示。

为什么我需要移动位以获取带有散列 id 的字符串?

正在使用的格式 String 是%0Nx,这会导致字符串被零填充到N字符。由于十六进制表示一个字节需要两个字符,因此Nbytes*2,结果为bytes << 1

我真的不明白你为什么不只包含适用于 Android 的 Guava并使用Hashing构建器

String hash = Hashing.sha1().hashString(deviceId, Charsets.UTF_8).toString();

这是一行,不会抛出检查异常。

于 2012-11-08T17:34:38.210 回答
1

关于位移:左移1相当于乘以2。字符串中的每个字节由2个十六进制字符表示,因此生成的字符串将是哈希中字节数的两倍。

这将创建一个类似于 的格式字符串,%032x它将一个整数值打印为一个零填充的 32 个字符的字符串。

于 2012-11-08T17:27:19.323 回答
1

您需要散列字节而不是字符串,以便散列字符数据而不是String对象,这对于给定的字符序列可能具有不可预测的内部状态。

它被转换为 BigInteger,因此它可以一致地格式化为每字节两个十六进制数字。(这就是为什么左移时长度乘以 2。)

基本上,您所有问题的答案都是:即使在不同的平台上,您也可以获得可靠、可重复的结果

于 2012-11-08T17:31:44.310 回答
0

您也可以使用此代码:

         public class sha1Calculate {

        public static void main(String[] args)throws Exception
        {
             File file = new File("D:\\Android Links.txt");
            String outputTxt= "";
            String hashcode = null;

            try {

                FileInputStream input = new FileInputStream(file);

                ByteArrayOutputStream output = new ByteArrayOutputStream ();
                byte [] buffer = new byte [65536];
                int l;

                while ((l = input.read (buffer)) > 0)
                    output.write (buffer, 0, l);

                input.close ();
                output.close ();

                byte [] data = output.toByteArray ();


                    MessageDigest digest = MessageDigest.getInstance( "SHA-1" ); 

                byte[] bytes = data;

                digest.update(bytes, 0, bytes.length);
                bytes = digest.digest();

                StringBuilder sb = new StringBuilder();

                for( byte b : bytes )
                {
                    sb.append( String.format("%02X", b) );
                }

                    System.out.println("Digest(in hex format):: " + sb.toString());


            }catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        }
于 2014-01-27T09:12:24.710 回答