Nie umiałem znaleźć w internecie odpowiadającej mi implementacji sha1 w javie, więc postanowiłem napisać ją sam. Problem w tym, że wyniki za nic nie zgadzają się z wynikami z innych implementacji. Kod oparłem na pseudokodzie z wikipedii.
import java.util.Arrays;
import org.apache.commons.lang3.ArrayUtils;
public class SHA1 {
private static byte[] longToBytes (long a ){
byte[] b = new byte[8];
for(int i=7; i>=0; i--){
b[7-i] = (byte) ((a>>(i*8)&0xff));
}
return b;
}
private static byte[] intToBytes (int a ){
byte[] b = new byte[4];
for(int i=3; i>=0; i--){
b[3-i] = (byte) ((a>>(i*8)&0xff));
}
return b;
}
private static int rol( int word, int bits ){
return (word<<bits | word>>(32-bits))&0xffffffff;
}
public static byte[] calculate( String mesage ){
byte[] msg = mesage.getBytes();
int h0 = 0x67452301;
int h1 = 0xEFCDAB89;
int h2 = 0x98BADCFE;
int h3 = 0x10325476;
int h4 = 0xC3D2E1F0;
long ml = mesage.length() * 8;
msg = ArrayUtils.addAll(msg, (byte) 0x80);
msg = ArrayUtils.addAll(msg, new byte[(int)((512 - ((ml+72)%512))/8)]);
msg = ArrayUtils.addAll(msg, longToBytes(ml));
byte[][] chunks = new byte[msg.length/64][64];
for(int i=0; i < chunks.length; i++) {
chunks[i] = Arrays.copyOfRange( msg, i*64, (i+1)*64 );
}
for( byte[] chunk : chunks ){
int[] words = new int[80];
for( int i = 0; i < 16; i++ ){
words[i] = ((int)chunk[i*4])<<24 | ((int)chunk[4*i+1])<<16 | ((int)chunk[4*i+2])<<8 | ((int)chunk[4*i+3]);
}
for( int i = 16; i < 32; i++ ){
words[i] = rol(( words[i-3]^words[i-8]^words[i-14]^words[i-16] ), 1);
}
for( int i = 32; i < 80; i++ ){
words[i] = rol(( words[i-6]^words[i-16]^words[i-24]^words[i-32] ), 2);
}
int a = h0;
int b = h1;
int c = h2;
int d = h3;
int e = h4;
for( int i = 0; i < 80; i++ ){
int f;
int k;
if( 0 <= i && i <= 19 ){
f = d ^ (b & (c ^ d));
k = 0x5A827999;
}
else if( 20 <= i && i <= 39 ){
f = b^c^d;
k = 0x6ED9EBA1;
}
else if( 40 <= i && i <= 59 ){
f = ( b & c ) | (b & d) | (c & d) ;
k = 0x8F1BBCDC;
}
else{
f = b^c^d;
k = 0xCA62C1D6;
}
int temp = ( rol( a, 5 ) ) + f + e + k + words[i];
e = d;
d = c;
c = rol( b,30 );
b = a;
a = temp;
}
h0 += a;
h1 += b;
h2 += c;
h3 += d;
h4 += e;
}
byte[] hh = ArrayUtils.addAll(ArrayUtils.addAll(ArrayUtils.addAll(ArrayUtils.addAll( intToBytes(h0), intToBytes(h1)), intToBytes(h2)), intToBytes(h3)), intToBytes(h4));
return hh;
}
}
EDIT:
Znalazłem wreszcie odpowiednią implementację. Była tuż pod moim nosem, a mianowicie w klasie java.security.MessageDigest, ale mimo tego dalej jestem ciekawy co zrobiłem nie tak w swojej implementacji.