问题描述
我一直在尝试按照我在网上找到的维基百科伪代码和幻灯片在 Java 中实现 SHA-1,但与在线实现(例如 http://www.sha1-online.com/)的值相比,我得到了不正确的哈希值
我有两个功能。一个预处理函数,它接受一个字符串并返回一个列表列表,其中外部列表表示 512 位块,内部列表每个包含 80 个 32 位字。我经历了所描述的获取消息的二进制值、附加 1、填充零直到长度为 -64 mod 512 然后在附加/填充为 64 位值之前添加原始消息的长度(位数)的过程到二进制字符串的末尾。这给了我 512 的倍数。将它们分成 512 位的块,每块分成 16 个 32 位的字。然后使用 XOR 添加单词,直到每个块有 80 个单词。
第二个函数循环遍历块和词,然后根据在线伪代码更改 h 变量。但是,在生成最终哈希时,似乎有些地方说只连接五个 h 变量,而其他来源则说要进行旋转和 OR 它们。下面的代码不适用于附加,因为它产生 80 位的哈希值(即假设大小的两倍),但使用旋转然后 ORing 给出了不正确的值。我不知道接下来要做什么,我找不到任何合适的在线实现。
注意:关于旋转的距离,我将其除以四,因为根据我的理解,这是将左旋转应用于十六进制而不是二进制字符串的正确方法。
private static ArrayList<ArrayList<String>> preprocessing(String s){
String binary_message = "";
for(int i = 0 ;i<s.length();i++){
binary_message+= toBinary8((int) s.charat(i));
}
int msg_len = binary_message.length();
binary_message+="1";
while(binary_message.length()%512 != 448){
binary_message = "0"+binary_message;
}
binary_message+=toBinary64(msg_len);
System.out.println(binary_message.length());
ArrayList<String> chunks = new ArrayList<String>();
for(int i = 0 ; i<binary_message.length()/512 ; i++){
chunks.add(binary_message.substring(i*512,(i*512) + 512));
}
ArrayList<ArrayList<String>> words = new ArrayList<ArrayList<String>>();
for(int i=0; i<chunks.size();i++){
ArrayList<String> temp = new ArrayList<String>();
String tempStr = chunks.get(i);
for(int j=0;j<16;j++){
temp.add(tempStr.substring(j*32,(j*32) +32));
}
words.add(temp);
}
//Use XOR to extend each chunk to have 80 32-bit words
int size = chunks.size();
for(int i=0; i<size;i++){
for(int j=16;j<80;j++){
//calculate word using XOR on long values
long t1 = Long.parseLong(words.get(i).get(j-3),2);
long t2 = Long.parseLong(words.get(i).get(j-8),2);
long t3 = Long.parseLong(words.get(i).get(j-14),2);
long t4 = Long.parseLong(words.get(i).get(j-16),2);
long t = t1 ^ t2 ^ t3 ^ t4;//new word to append
String toApp = Long.toBinaryString(t);//convert to string
while(toApp.length()<32){
toApp="0"+toApp;
}
if(toApp.length()!=32){
System.out.println("Error");
System.out.println(toApp.length());
}
ArrayList<String> temp = words.get(i);
temp.add(toApp);
words.add(i,temp);
}
}
return words;
}
private static String hashF2(String s){
String ret = null;
if ((s.length() > 64) || (s.length() < 1)) { // String does not have required length
ret = null;
}else{
/*
The following is an implementation of SHA-1 hashing algorithm that follows the pseudo code from:
https://en.wikipedia.org/wiki/SHA-1
It returns a 160-bit hexadecimal hash (the size is 40)
*/
//default values
long h0 = 0x67452301;
long h1 = 0xEFCDAB89;
long h2 = 0x98BADCFE;
long h3 = 0x10325476;
long h4 = 0xC3D2E1F0;
ArrayList<ArrayList<String>> words = preprocessing(s);
//loop over each chunk and reassign initialised variables h0 -> h4 using bitwise operations
for(int i=0; i<words.size();i++){
long a = h0;
long b = h1;
long c = h2;
long d = h3;
long e = h4;
long f = 0x0;
long k = 0x0;
//loop over each word and calculate f and k correspondingly
for(int j=0;j<80;j++){
if(j>= 0 && j <= 19){
f = (b & c) | ((~ b) & d);
k = 0x5A827999;
}
else if( j>= 20 && j<= 39){
f = b ^ c ^ d;
k = 0x6ED9EBA1;
}
else if(j>=40 && j<=59){
f = (b & c) | (b & d) | (c & d);
k = 0x8F1BBCDC;
}
else if(j>=60 && j<= 79){
f = b ^ c ^ d;
k = 0xCA62C1D6;
}
//left shift a by 5 bits then add to f,e,k,and the jth word of the ith chunk
long temp = Long.rotateLeft(a,5) + f + e + k + Long.parseLong(words.get(i).get(j),2);
e = d;
d = c;
c = Long.rotateLeft(b,30);
b = a;
a = temp;
}
//after each chunk reassign h0 to h4
h0 = h0 + a;
h1 = h1 + b;
h2 = h2 + c;
h3 = h3 + d;
h4 = h4 + e;
}
/*
turn h values to a hash string
*/
//get hex strings from each h
String h0S = Long.toHexString(h0);
String h1S = Long.toHexString(h1);
String h2S = Long.toHexString(h2);
String h3S = Long.toHexString(h3);
String h4S = Long.toHexString(h4);
System.out.println(h0S);
System.out.println(h1S);
System.out.println(h2S);
System.out.println(h3S);
System.out.println(h4S);
System.out.println(" ");
while(h0S.length() < 40) {
StringBuilder h0L = new StringBuilder(h0S);
h0L.insert(0,0);
h0S = h0L.toString();
}
while(h1S.length() < 40) {
StringBuilder h1L = new StringBuilder(h1S);
h1L.insert(0,0);
h1S = h1L.toString();
}
while(h2S.length() < 40) {
StringBuilder h2L = new StringBuilder(h2S);
h2L.insert(0,0);
h2S = h2L.toString();
}
while(h3S.length() < 40) {
StringBuilder h3L = new StringBuilder(h3S);
h3L.insert(0,0);
h3S = h3L.toString();
}
while(h4S.length() < 40) {
StringBuilder h4L = new StringBuilder(h4S);
h4L.insert(0,0);
h4S = h4L.toString();
}
//left rotate h0 -> h3 according to wikipedia pseudocode
//note that the pseudocode distances are divided by 4 since this is rotating hexadecimal values not binary values
h0S = h0S.substring(32) + h0S.substring(0,32);
h1S = h1S.substring(24) + h1S.substring(0,24);
h2S = h2S.substring(16) + h2S.substring(0,16);
h3S = h3S.substring(8) + h3S.substring(0,8);
//convert to BigInteger to be able to store in a format that can be ORed easily
BigInteger b0 = new BigInteger(h0S,16);
BigInteger b1 = new BigInteger(h1S,16);
BigInteger b2 = new BigInteger(h2S,16);
BigInteger b3 = new BigInteger(h3S,16);
BigInteger b4 = new BigInteger(h4S,16);
//OR all values to create the final hash value
BigInteger hh = b0.or(b1).or(b2).or(b3).or(b4);
ret = hh.toString(16);//return as string
}
return ret;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)