72 lines
2.5 KiB
Java
72 lines
2.5 KiB
Java
import java.nio.charset.StandardCharsets;
|
|
import java.util.Arrays;
|
|
|
|
public final class SHA1Task {
|
|
|
|
public static void main(String[] args) {
|
|
System.out.println(SHA1.messageDigest("Rosetta Code"));
|
|
}
|
|
|
|
}
|
|
|
|
final class SHA1 {
|
|
|
|
public static String messageDigest(String message) {
|
|
int[] state = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
|
|
|
|
byte[] bytes = addPadding(message);
|
|
for ( int i = 0; i < bytes.length / BLOCK_LENGTH; i++ ) {
|
|
int[] values = new int[80];
|
|
for ( int j = 0; j < BLOCK_LENGTH; j++ ) {
|
|
values[j / 4] |= ( bytes[i * BLOCK_LENGTH + j] & 0xff ) << ( ( 3 - j % 4 ) * 8 );
|
|
}
|
|
for ( int j = 16; j < 80; j++ ) {
|
|
values[j] = Integer.rotateLeft(values[j - 3] ^ values[j - 8] ^ values[j - 14] ^ values[j - 16], 1);
|
|
}
|
|
|
|
int a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];
|
|
int f = 0, k = 0;
|
|
for ( int j = 0; j < 80; j++ ) {
|
|
switch ( j / 20 ) {
|
|
case 0 -> { f = ( b & c ) | ( ~b & d ); k = 0x5a827999; }
|
|
case 1 -> { f = b ^ c ^ d; k = 0x6ed9eba1; }
|
|
case 2 -> { f = ( b & c ) | ( b & d ) | ( c & d ); k = 0x8f1bbcdc; }
|
|
case 3 -> { f = b ^ c ^ d; k = 0xca62c1d6; }
|
|
}
|
|
|
|
int temp = Integer.rotateLeft(a, 5) + f + e + k + values[j];
|
|
e = d; d = c; c = Integer.rotateLeft(b, 30); b = a; a = temp;
|
|
}
|
|
|
|
state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e;
|
|
}
|
|
|
|
StringBuilder result = new StringBuilder();
|
|
for ( int i = 0; i < 20; i++ ) {
|
|
result.append(String.format("%02x", ( state[i / 4] >>> 24 - ( i % 4 ) * 8 ) & 0xFF ));
|
|
}
|
|
return result.toString();
|
|
}
|
|
|
|
private static byte[] addPadding(String message) {
|
|
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
|
|
bytes = Arrays.copyOf(bytes, bytes.length + 1);
|
|
bytes[bytes.length - 1] = (byte) 0x80;
|
|
|
|
int padding = BLOCK_LENGTH - ( bytes.length % BLOCK_LENGTH );
|
|
if ( padding < 8 ) {
|
|
padding += BLOCK_LENGTH;
|
|
}
|
|
bytes = Arrays.copyOf(bytes, bytes.length + padding);
|
|
|
|
final long bitLength = message.length() * 8;
|
|
for ( int i = 0; i < 8; i++ ) {
|
|
bytes[bytes.length - 1 - i] = (byte) ( bitLength >>> ( 8 * i ) );
|
|
}
|
|
return bytes;
|
|
}
|
|
|
|
private static final int BLOCK_LENGTH = 64;
|
|
|
|
}
|