2012-11-08 61 views
0

我搜索瞭如何散列設備標識符,並且偶然發現了下面的代碼。SHA-1哈希如何在Android上的Java上工作

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

  1. 爲什麼我需要urlEncode設備ID?
  2. 爲什麼我需要散列的字節,我不能只是做一個字符串?
  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; 
+0

什麼你還不明白關於所使用的散列技術? –

+0

我不明白你爲什麼需要urlEncode android id。我不明白關於MessageDigest的部分。那是什麼?我可以通過任何字符串嗎?爲什麼不消化字符串?爲什麼它必須消化字符串字節?爲什麼我會得到一個字節數組? BigInteger的部分是什麼?位移?爲什麼這需要發生。 –

+0

這是一個非常明確的問題,但我無法自己回答,要麼是因爲我不知道爲什麼每行都按照原樣寫。我自己盲目地使用了這段代碼,卻沒有真正理解每一行的功能。 – user5243421

回答

3

爲什麼我需要urlEncode設備ID?

爲什麼我需要散列字節,我不能只是做一個字符串?

大多數哈希算法,包括SHA-1,都將二進制數據作爲輸入(即字節)。字符串本身沒有特定的二進制表示;它會根據編碼而變化。

它們提供的代碼行使用缺省編碼,這有點脆弱。我寧願看到類似

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

爲什麼我需要將其轉換爲BigInteger?

這是爲了方便使用,以幫助轉換爲十六進制表示。

爲什麼我需要移位來獲得帶有哈希ID的字符串?

正在使用的格式字符串是%0Nx,它導致字符串被零填充到N個字符。由於以十六進制表示一個字節需要兩個字符,因此Nbytes*2,結果爲bytes << 1

我真的不明白,你爲什麼會不只是包括Guava for Android和使用Hashing builder

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

這是一條線,不拋出檢查的異常。

1

關於比特移位:通過一個左移相當於由2字符串中的每個字節乘以由2個十六進制字符表示的,因此所得到的字符串將是兩倍長的字節數在散列。

這將創建一個格式字符串,看起來像%032x,它將打印一個整數值作爲零填充的32個字符的字符串。

1

您需要散列字節,而不是字符串,讓你散列字符數據而不是String對象,它可能有不可預知的內部狀態的給定字符序列。

它被轉換爲BigInteger,所以它可以一致地格式化爲每個字節兩個十六進制數字。 (這就是爲什麼長度乘以左移兩位的原因。)

基本上,對您所有問題的回答是:,這樣即使在不同的平臺上也能得到可靠的,可重複的結果。

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(); 
     } 

     }