2011-06-15 84 views
4

我試圖實現DSA簽名算法,我被困在一個問題上。我使用java.securityMessageDigest類,下面的代碼:SHA散列函數給出了一個負面的輸出

MessageDigest md; 
md = MessageDigest.getInstance("SHA-1"); 
md.update(text.getBytes()); 
return new BigInteger(md.digest()); 

文本是一個隨機字符串對象。問題是這段代碼給了我散列的負值,這是算法不接受的。難道我做錯了什麼?提前致謝。

P.S.順便說一下,我也試圖在不使用BigIntegers的情況下實現DSA,這可能嗎?我還沒有找到小於1024和160的L和N值,所以我不知道應該使用什麼值以及應該使用什麼散列函數。聽到這些問題的答案將非常感謝。

+2

那麼你期望什麼? BigInteger只是一個byte [] w /方法。 MessageDigest和BigInteger的外部byte []表示沒有接觸點。 – bestsss 2011-06-15 11:52:56

+0

@bestsss如何將摘要轉換爲BigInteger?也許對P.S.有任何想法。我的問題的一部分?謝謝你的回答。 – Egor 2011-06-15 12:01:17

+0

你爲什麼要重新實現DSA?通常你應該使用系統提供的功能;重新實現加密是危險的,因爲它可能導致微妙的安全漏洞。 – crazyscot 2011-06-15 12:04:36

回答

3
MessageDigest md; 
md = MessageDigest.getInstance("SHA-1"); 
md.update(text.getBytes()); 
return new BigInteger(1, md.digest()); // use this 1 to tell it is positive. 

然後您可以將您的散列轉換爲一個String:

String hash = biginteger.toString(16); 

然後任選前面加上前導零。

String zeros = String.format("%032d", 0); 
hash = zeros.substring(hash.length()) + hash; 
+0

比我的回答更好! – crazyscot 2011-06-15 12:03:29

+1

首先,沒有MessageDigest.toString(base)方法,這就是我想說的第一個問題的原因。上面的第二個代碼片段應該使用BigInteger.toString(16)代替。其次,絕對不需要填零。甚至連最差的摘要函數都會返回一個具有四個零值連續位的散列值。 – 2012-12-22 12:02:06

+0

是的,你說得對,我修好了。關於填充,這也是我爲什麼寫「最終」的原因。 – 2012-12-22 16:59:53

1

你傳入字節回到BigIntegerconstructor。雖然類型匹配,但我不確定你想在這裏完成什麼。從BigInteger的JavaDoc:

平移包含的字節數組二進制補碼的一個BigInteger

2

你爲什麼驚訝二進制表示? MessageDigest#digest()返回均勻分佈的160位數據。它們通常表示爲十六進制字符串,但是如果將它們轉換爲整數,則最重要的位指定符號。看看這個代碼:

System.out.println(new BigInteger(new byte[]{(byte) 255})); //-1 
0

不要重新發明輪子,尤指密碼 - 用java.security.Signature或更高級別的圖書館。

+0

我想,但是這是我在大學的功課=) – Egor 2011-06-15 12:05:12

相關問題