2011-06-15 76 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

相关问题