2011-08-14 104 views
2

所以我不知道我是否正確地做到了這一點。我會被這裏的僞代碼:http://en.wikipedia.org/wiki/MD5實現MD5,追加位1和0

它說:

//Pre-processing: 
append "1" bit to message 
append "0" bits until message length in bits ≡ 448 (mod 512) 
append length to message 

在java中,我將能夠將郵件轉換爲字節數組。然後通過獲取字符串長度來獲取位數* 8.然後執行諸如448 - ((#bits+1) mod 512)之類的操作來獲取要添加的0位數。

然後該字節數組複製到另一個數組,但墊以0的第一字節,然後1.

實施例:

字符串是746個比特 我然後會做448 - ((746+1) mod 512) = 213

所以我需要用213「0」位和1「1」位填充字符串。

所以後來我的陣列會是這樣的

byteArr[0] = 0x00 
byteArr[1] = 0x00 
... 
byteArr[27] = 000001(Rest of message bits) 
byteArr[n] = Rest of the bytes from message 

我怎樣才能找出1變爲雖然在哪裏?基本上我怎麼能找出它是否會創建一個短,如果我追加1位。

是否有更簡單的方式或其他方式來做到這一點?

+0

我不鼓勵你使用'MD5'。我會建議當然最低'SHA256'鹽。在我的代碼中,你可以傳遞'MD5'或'SHA-512'或'SHA-256',但是'MD5'(128位)幾乎沒有'SHA-1'(160-bit)那麼安全。 'SHA-256'(256位)。你可以使用更安全的'TripleDES'。 – Ali

+0

@Ali是的,我知道SHA和MD5的差異以及如何使用它們。我想要實現MD5的算法。不過謝謝。 – Matt

+0

這裏要實現的關鍵是(除了append意味着最終的事實):MD5和其他散列函數是在位而不是字節上定義的。從理論上講,你可以散列一個13位長的消息,其結果將不同於散列一個以開始或結束方式相同的16位長消息。但實際上,幾乎所有的實現(包括您的所有可能性)都假定輸入消息由整個字節組成。 –

回答

2

作爲別人抓到了,「追加」意味着廣告ded到底。所以,真正要擁有什麼如果要實現加密算法,你應該做它的消息,後面一串0字節,直到總字節數後的0x80的字節比64

+0

大聲笑,這更有意義。當我太累時,我不應該這樣做。當你說0x80時,這對我有意義。謝謝! – Matt

0

還有一個更簡單的方法來做到這一點:由Java SE API只需使用MD5 algorithm already implemented你。

邊注:在Java中的字符串包含字符,而不是字節。不要使用術語「字符串」來引用二進制消息。使用術語字節數組。

+0

我知道Java中已經有了一個類,我不想使用它。我想自己實現MD5算法。這是爲了我的理解。 – Matt

+0

啊。好。除非你編輯你的答案來提及它,否則我會在這裏留下我的答案,以避免其他類似的答案。 –

2

的位必須被添加到該消息,而不是一開始的。將消息填充到448位mod 512後,必須附加消息的長度(不帶填充位)。 但只要這不是一個練習,你應該使用JB Nizet提到的算法。

+0

好吧,這將是「消息位」......例如00000001或「消息位」1000000000 ......以此類推。通過這個我意味着數組的設置方式,所以這些位將會放到數組的末尾。我真的不明白1被追加到哪裏。就像是在最後一個字節之後? – Matt

+0

它應該是[messagebits] 10000000xxxx其中xxxx =「bit(不是字節)長度的未填充消息作爲64位little-endian整數」(參考wiki) – Matten

-2

你在說什麼是醃製散列。

這就是我的做法。

public static byte[] getSecure8ByteSalt(){ 
    SecureRandom random = null; 
    try { 
     random = SecureRandom.getInstance("SHA1PRNG"); 
     byte [] bSalt = new byte[8]; 
     random.nextBytes(bSalt); 
     return bSalt; 
    } catch (NoSuchAlgorithmException e) { 
     log.error(e.getMessage(),e); 
    } 
    return new byte[]{ 
     (byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32, 
     (byte)0x56, (byte)0x34, (byte)0xE3, (byte)0x03 
    }; 
} 

,對於鹽調用的方法被稱爲散列:

private void hash(String passwd, int hashType){ 
    byte[] bSalt = new byte[8]; 
    try { 
     if(this.salt == null){ 
      bSalt = getSecure8ByteSalt(); 
     } 
     else{ 
      bSalt = base64ToByte(salt); 
     } 
    } catch (IOException e1) { 
     log.error(e1.getMessage(),e1); 
     return; 
    } 


    byte[] bDigest=null; 
    try { 
     bDigest = getHash(ITERATION_NUMBER,passwd,bSalt,hashType); 
    } catch (NoSuchAlgorithmException e) { 
     log.error(e.getMessage(),e); 
    } 

    String sDigest = byteToBase64(bDigest); 
    if(this.salt == null) 
     setSalt(byteToBase64(bSalt)); 
setPasswordHash(sDigest); 
} 

字節到基座64方法:

public static byte[] base64ToByte(String data) throws IOException { 
    BASE64Decoder decoder = new BASE64Decoder(); 
    return decoder.decodeBuffer(data); 
} 

public static String byteToBase64(byte[] data){ 
     BASE64Encoder endecoder = new BASE64Encoder(); 
     return endecoder.encode(data); 
} 

的getHash方法:

private byte[] getHash(int iterationNb, String password, byte[] salt, int hashType) throws NoSuchAlgorithmException { 
     MessageDigest digest = MessageDigest.getInstance(HASH_TYPE[hashType]); 
     digest.reset(); 
     digest.update(salt); 
     byte[] input = null; 
     try { 
      input = digest.digest(password.getBytes("UTF-8")); 
     } catch (UnsupportedEncodingException e) { 
      log.error(e.getMessage(),e); 
     } 
     for (int i = 0; i < iterationNb; i++) { 
      digest.reset(); 
      input = digest.digest(input); 
     } 
     return input; 
    } 
+0

這不是一個哈希值。爲了使輸入的最後一個塊成爲正確的大小,需要使用填充。搗亂哈希是不同的。 – rossum

0

多少8將官方規格作爲實施藍圖的好習慣。與維基百科一樣偉大,我仍然不會依賴它來實現安全關鍵算法。當然,除官方規範外,還可以使用它。所以我會從RFC 1321開始,只會從其他來源獲得「靈感」。

RFC 1321甚至包含C中的一個實現,你也可以檢查出來。關於填補處理步驟,他們說

3.1步驟1中追加填充比特

該消息是「填補結束」(擴展),使得它的長度(位)是 全等448,模512。也就是說,這個消息被擴展了,所以它只是64位,而不是512位長的倍數。 填充總是執行,即使該消息的長度是 已經全等至448,模如下進行512

填充:一個單一的「1」比特被附加到 消息,然後「0 「位被附加,使得填充消息的長度以位爲單位變爲448,以512爲模。總而言之,在 處附加至少一位和至多512位。

這意味着你必須先追加1,然後填充餘下的零,而不是相反。由於你的輸入是位長度也是8的倍數的字節,所以要填充的剩餘位(包括「1」)將總是8的倍數。所以假設你必須填充128位。這意味着1加127 0位。總共有16(16 * 8 = 128)個填充字節,其中第一個字節的最高位設置爲1,即第一個字節將變爲0x80,其餘爲0x00。因此,這意味着可以=字節墊=餘數的總數由8

  • 追加0x80的劃分到消息
  • 追加N-1次0x00至比特簡化此填補處理步驟到

    • Ñ消息