How to resolve the algorithm SHA-1 step by step in the Java programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm SHA-1 step by step in the Java programming language

Table of Contents

Problem Statement

SHA-1 or SHA1 is a one-way hash function; it computes a 160-bit message digest. SHA-1 often appears in security protocols; for example, many HTTPS websites use RSA with SHA-1 to secure their connections. BitTorrent uses SHA-1 to verify downloads. Git and Mercurial use SHA-1 digests to identify commits. A US government standard, FIPS 180-1, defines SHA-1. Find the SHA-1 message digest for a string of octets. You may either call a SHA-1 library, or implement SHA-1 in your language. Both approaches interest Rosetta Code.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm SHA-1 step by step in the Java programming language

The provided Java code implements the SHA-1 (Secure Hash Algorithm 1) hashing algorithm, which is a cryptographic function that converts a message of any length into a fixed-size digest value of 160 bits. SHA-1 is widely used for data integrity verification, password storage, and digital signatures.

Explanation:

1. Main Method (SHA1Task class):

  • The main method creates an instance of the SHA1 class and calls its messageDigest method, passing it the message "Rosetta Code."
  • The result of the hashing operation is printed to the console.

2. SHA1 Class:

The SHA1 class defines the SHA-1 hashing algorithm.

3. messageDigest Method:

  • This method takes a message as input and returns its SHA-1 digest as a hexadecimal string.

4. SHA-1 Algorithm:

  • The SHA-1 algorithm is implemented in the messageDigest method.

  • It involves the following steps:

    a. Padding:

    • The message is padded with a single 1 bit, followed by zeros until the length is congruent to 56 (mod 64).
    • A 64-bit representation of the message length is appended to the padded message.

    b. Processing Blocks:

    • The message is broken into blocks of 512 bits (64 bytes).
    • Each block is processed independently.

    c. Initialization:

    • Five state variables (a, b, c, d, e) are initialized to specific hexadecimal values.

    d. Processing Rounds:

    • The block is divided into 80 32-bit words.
    • A set of 80 constants (K) and four functions (f1, f2, f3, f4) are defined.
    • The state variables are updated in 80 rounds using the following formula:
    temp = a + f(b, c, d) + e + K + w[i]
    a = e
    e = d
    d = c
    c = b
    b = temp
    

    e. Finalization:

    • The state variables are added to the initial values to produce the final digest value.

5. addPadding Method:

  • This method adds padding to the input message as described in step 4a of the SHA-1 algorithm.

6. Constants and Variables:

  • BLOCK_LENGTH: Constant representing the block size in bytes (64).

Source code in the java programming language

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;
	
}


  

You may also check:How to resolve the algorithm Digital root step by step in the Phix programming language
You may also check:How to resolve the algorithm Stable marriage problem step by step in the D programming language
You may also check:How to resolve the algorithm Loops/Break step by step in the MUMPS programming language
You may also check:How to resolve the algorithm Fraction reduction step by step in the C# programming language
You may also check:How to resolve the algorithm Product of min and max prime factors step by step in the Sidef programming language