Page 1 of 1

Doubts with implementation of SHA1 pseudo code[UNSOLVED]

Posted: Thu Oct 06, 2005 5:37 am
by raghavan20
[Please scroll down to my last post to see the new problem...thanks]

Code: Select all

Pseudo code for SHA1

Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating

Initialize variables:
h0 := 0x67452301
h1 := 0xEFCDAB89
h2 := 0x98BADCFE
h3 := 0x10325476
h4 := 0xC3D2E1F0

Pre-processing:
append a single "1" bit to message
append "0" bits until message length ≡ 448 ≡ -64 (mod 512)
append length of message, in bits as 64-bit big-endian integer to message

Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
    break chunk into sixteen 32-bit big-endian words w(i), 0 ≤ i ≤ 15

    Extend the sixteen 32-bit words into eighty 32-bit words:
    for i from 16 to 79
        w(i) := (w(i-3) xor w(i-8) xor w(i-14) xor w(i-16)) leftrotate 1

    Initialize hash value for this chunk:
    a := h0
    b := h1
    c := h2
    d := h3
    e := h4

    Main loop:
    for i from 0 to 79
        if 0 ≤ i ≤ 19 then
            f := (b and c) or ((not b) and d)
            k := 0x5A827999
        else if 20 ≤ i ≤ 39
            f := b xor c xor d
            k := 0x6ED9EBA1
        else if 40 ≤ i ≤ 59
            f := (b and c) or (b and d) or (c and d)
            k := 0x8F1BBCDC
        else if 60 ≤ i ≤ 79
            f := b xor c xor d
            k := 0xCA62C1D6

        temp := (a leftrotate 5) + f + e + k + w(i)
        e := d
        d := c
        c := b leftrotate 30
        b := a
        a := temp

    Add this chunk's hash to result so far:
    h0 := h0 + a
    h1 := h1 + b 
    h2 := h2 + c
    h3 := h3 + d
    h4 := h4 + e

digest = hash = h0 append h1 append h2 append h3 append h4 (expressed as big-endian)
I have got a few doubts
1. this line says, "Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating"
wot do they mean by wrap modulo 2^32 when calculating???

2. This line says, "append a single "1" bit to message"
then I should be convering the input string into bytes and add '1' bit to it. Now, how do I convert a string into bytes???

Any help is appreciated.

Re: Doubts with implementation of SHA1 pseudo code

Posted: Thu Oct 06, 2005 9:12 am
by feyd
raghavan20 wrote:I have got a few doubts
1. this line says, "Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating"
wot do they mean by wrap modulo 2^32 when calculating???
I believe it's talking about bit rotation, versus bit shifting.
raghavan20 wrote:2. This line says, "append a single "1" bit to message"
then I should be convering the input string into bytes and add '1' bit to it. Now, how do I convert a string into bytes???
A string is already broken into bytes, you simply add 0x80 character to the string.

Posted: Thu Oct 06, 2005 12:06 pm
by raghavan20
Thanks for your answers feyd.
raghavan20 wrote:
I have got a few doubts
1. this line says, "Note: All variables are unsigned 32 bits and wrap modulo 2^32 when calculating"
wot do they mean by wrap modulo 2^32 when calculating???
I believe it's talking about bit rotation, versus bit shifting
I know how to left shift and right shift; but is bit rotation is different from bit shifting???
raghavan20 wrote:
2. This line says, "append a single "1" bit to message"
then I should be convering the input string into bytes and add '1' bit to it. Now, how do I convert a string into bytes???
A string is already broken into bytes, you simply add 0x80 character to the string.
I recently found that since string is a set of c haracters; each character has an ascii code which can be represented directly in binary.
like A - 65 then binary format: 01000001
Why do I have to add 0x80 to it???
I know hex digits start with 0x but why is the 80 coming into the picture.

Posted: Thu Oct 06, 2005 12:16 pm
by raghavan20
1.
Initialize variables:
h0 := 0x67452301
h1 := 0xEFCDAB89
h2 := 0x98BADCFE
h3 := 0x10325476
h4 := 0xC3D2E1F0
how do they choose the values of the variables???

2. what is big endian integer??? I could not understand from web definitions.

3.
Main loop:
for i from 0 to 79
if 0 ≤ i ≤ 19 then
f := (b and c) or ((not b) and d)
k := 0x5A827999
else if 20 ≤ i ≤ 39
f := b xor c xor d
k := 0x6ED9EBA1
else if 40 ≤ i ≤ 59
f := (b and c) or (b and d) or (c and d)
k := 0x8F1BBCDC
else if 60 ≤ i ≤ 79
f := b xor c xor d
k := 0xCA62C1D6

temp := (a leftrotate 5) + f + e + k + w(i)
e := d
d := c
c := b leftrotate 30
b := a
a := temp

Add this chunk's hash to result so far:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e

digest = hash = h0 append h1 append h2 append h3 append h4 (expressed as big-endian)
If you have a look at the main loop, I dont know how far the loop block continues.
I dont think it continues until all the h0, h1, h2, h3 and h4 variables get assigned cos then a, b, c, d and e would be having values for the last loop index i = 79.

Posted: Thu Oct 06, 2005 1:19 pm
by feyd
raghavan20 wrote:1. how do they choose the values of the variables???
it's a part of creating a cryptographic system. You need to start with some form of entropy.
raghavan20 wrote:2. what is big endian integer??? I could not understand from web definitions.
a big endian number of the storage format for the binary representation of a number. In big endian the left hand side is the big end, or most significant. The bytes are stored from highest to lowest significance (greatest impact on what the number actually is). This corresponds to little endian, where the left hand side is the least significant ramping up to most significant.
raghavan20 wrote:If you have a look at the main loop, I dont know how far the loop block continues.
I dont think it continues until all the h0, h1, h2, h3 and h4 variables get assigned cos then a, b, c, d and e would be having values for the last loop index i = 79.
The loop references the last iteration, this is how minor alterations in the binary print greatly affect the resulting hash.

If you look at the (quite) verbose testing class of my SHA256 implementation you will see very similar behaviour in the encoding passes and such..

Posted: Sat Oct 08, 2005 11:11 am
by raghavan20
feyd wrote: raghavan20 wrote:
2. what is big endian integer??? I could not understand from web definitions.
a big endian number of the storage format for the binary representation of a number. In big endian the left hand side is the big end, or most significant. The bytes are stored from highest to lowest significance (greatest impact on what the number actually is). This corresponds to little endian, where the left hand side is the least significant ramping up to most significant.
Is our normal bit format big endian?
say suppose there is a decimal number 12, if I represent it as 1100, is this big endian??
and is 0011 for 12 is little endian??

Posted: Sat Oct 08, 2005 11:48 am
by feyd
writing is "normally" done in big endian since our decimal system is big endian, in my experience. As for writing out little endian.. from what I remember, bytes are still stored the same (big endian) but they are all flipped in order... so 1100 stays the same since that's only a nibble. At least, that's how I remember coding the conversions.. writing out would probably flip everything I'd think..

Posted: Sun Oct 09, 2005 7:34 am
by raghavan20
If you look at this set of steps

Code: Select all

Pre-processing:
append a single "1" bit to message
append "0" bits until message length ≡ 448 ≡ -64 (mod 512)
append length of message, in bits as 64-bit big-endian integer to message
Let me explain my logical problem with example:
input string: hello all

Code: Select all

Main block- input binary string:
0110100001100101011011000110110001101111001000000110000101101100011011001
make_512_bits_chunks: length of the input binary string: 73
make_512_bits_chunks: length of the input binary string in bits: 1001001
make_512_bits_chunks: length of the input binary string in 64 bits:
 00000000000000000000000000000000000000000
00000000000000001001001
make_512_bits_chunks: number of zeros to be padded: 375
make_512_bits_chunks: after padding zeros to be binary string to make it multiples of 448:
 0110100001100101011011000110110001101111001000000110000101101100011
01100100000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000
make_512_bits_chunks: Final binary string: 
011010000110010101101100011011000110111100100000011000010110110
00110110010000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000001001001
make_512_bits_chunks: Length of the binary string: 512
There is no problem here. I append the input string in binary with zeros to make it 448 and add the length of the string in 64 bits to make the total length of the string as 512.

But if there is a different larger input:
Input:phpdn is one of best forums available. There are various forums available in phpdn.

Code: Select all

Main block- input binary string:
0111000001101000011100000110010001101110001000000110100101110011001
0000001101111011011100110010100100000011011110110011000100000011000100110010
101110011011101000010000001100110011011110111001001110101011011010111001100100000
01100001011101100110000101101001011011000110000101100010011011000110010100101110001
000000101010001101000011001010111001001100101001000000110000101110010011001010010000
001110110011000010111001001101001011011110111010101110011001000000110011001101111011
100100111010101101101011100110010000001100001011101100110000101101001011011000110000101
1000100110110001100101001000000110100101101110001000000111000001101000011100000110010001101110001011101
make_512_bits_chunks: length of the input binary string: 665
make_512_bits_chunks: length of the input binary string in bits: 1010011001
make_512_bits_chunks: length of the input binary string in 64 bits: 
0000000000000000000000000000000000000000000000000000001010011001
make_512_bits_chunks: number of zeros to be padded: 231
make_512_bits_chunks: after padding zeros to be binary string to make it multiples of 448:
 01110000011010000111000001100100011011100010000001101001011100110010000001101
111011011100110010100100000011011110110011000100000011000100110010101110011011101
000010000001100110011011110111001001110101011011010111001100100000011000010111011
0011000010110100101101100011000010110001001101100011001010010111000100000010101000
11010000110010101110010011001010010000001100001011100100110010100100000011101100110
000101110010011010010110111101110101011100110010000001100110011011110111001001110101
0110110101110011001000000110000101110110011000010110100101101100011000010110001001101
1000110010100100000011010010110111000100000011100000110100001110000011001000110111000
1011101000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000
make_512_bits_chunks: Final binary string:
 01110000011010000111000001100100011011100010000001101001011100110010000001101111011
011100110010100100000011011110110011000100000011000100110010101110011011101000010000
001100110011011110111001001110101011011010111001100100000011000010111011001100001011
0100101101100011000010110001001101100011001010010111000100000010101000110100001100101
01110010011001010010000001100001011100100110010100100000011101100110000101110010011010
010110111101110101011100110010000001100110011011110111001001110101011011010111001100100
0000110000101110110011000010110100101101100011000010110001001101100011001010010000001101
001011011100010000001110000011010000111000001100100011011100010111010000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001010011001
make_512_bits_chunks: Length of the binary string: 960
Not you can see that actually the length has to be made as 1024 for further processing in chunks of 512
but wot happens is: 448 * 2 = 896 + 64 (length of binary input) = 960.
I now have a logical problem. How should I proceed???

Posted: Sun Oct 09, 2005 11:19 am
by feyd
if your message can span the full 512 bits, then it should. Basically, you take the full string break it into 512 bit chunks, on the last chunk you add 1 bit, then pad whatever amount needed to span the distance between the trailing 64 bit length and that position. If it goes over, you pad out that block then padd a new block up to the last 64 bits which then take the length.

Posted: Mon Oct 10, 2005 9:21 am
by raghavan20
Thanks for pointing that out...I hv corrected it now

I now have a logical problem which we discussed earlier,, implementation of this block of logic

Code: Select all

Main loop:
    for i from 0 to 79
        if 0 ≤ i ≤ 19 then
            f := (b and c) or ((not b) and d)
            k := 0x5A827999
        else if 20 ≤ i ≤ 39
            f := b xor c xor d
            k := 0x6ED9EBA1
        else if 40 ≤ i ≤ 59
            f := (b and c) or (b and d) or (c and d)
            k := 0x8F1BBCDC
        else if 60 ≤ i ≤ 79
            f := b xor c xor d
            k := 0xCA62C1D6

        temp := (a leftrotate 5) + f + e + k + w(i)
        e := d
        d := c
        c := b leftrotate 30
        b := a
        a := temp

    Add this chunk's hash to result so far:
    h0 := h0 + a
    h1 := h1 + b 
    h2 := h2 + c
    h3 := h3 + d
    h4 := h4 + e

digest = hash = h0 append h1 append h2 append h3 append h4 (expressed as big-endian)
This is how I have implemented it....I am not showing many user-defined functions used which are not really necessary to deal with this problem.

You can see the output and the flow here

Code: Select all

<?php
	/* set parameters */		
	error_reporting(E_ALL);
	
	/* encrypt if initial conditions are met */
	if (isset($_GET["input_string"])){
		/* initialize variables */
		$input_string_ascii_array = array();
		$input_string_binary_array = array();
		$binary_512_chunks_array = array();
		$binary_32_chunks_array = array();
		
		/* Get the input varible from the $_GET array */
		$input_string = $_GET["input_string"];
		
		/* define initial variables */
		$h0 = "67452301";
		$h1 = "EFCDAB89";
		$h2 = "98BADCFE";
		$h3 = "10325476";
		$h4 = "C3D2E1F0";
		
		/* convert and obtain the input string in ASCII chars */
		$input_string_ascii_array = change_string_to_ascii($input_string);
		echo "<br />"."Main block- Original input binary string:"; print_r($input_string_ascii_array);
		
		/* convert and obtain the ASCII chars as Binary array */
		$input_string_binary_array = change_ascii_to_binary($input_string_ascii_array);
		echo "-----------received binary array------------";
		print_r($input_string_binary_array);
		$input_string_binary = implode("", $input_string_binary_array);
		
		/* pad an additional bit with value one to the existing binary input string */
		$input_string_binary .= '1';
		echo "<br />"."Main block- After appending to the original input binary string:".$input_string_binary; 
		
		/* make the string as 512 bits chunk; else pad zero to make it 512 bit chunks */
		$input_string_binary = make_512_bits_chunks($input_string_binary);
		
		/* get the input binary string as array of individual 512 bits chunks */
		$binary_512_chunks_array = get_array_n_bits_chunks($input_string_binary, 512);

		/* find the number of 512 bits chunks returned */
		$binary_512_chunks_array_length = count($binary_512_chunks_array);
		
		/* Continue the loop until all 512 bits chunks are processed. compute has for every chunk */
		for ($i = 0; $i < $binary_512_chunks_array_length; $i++){		
			/* split the nth 512 bits chunk into 32 bits chunks array */
			$binary_32_chunks_array = get_array_n_bits_chunks($binary_512_chunks_array[$i], 32);
			
			/* extend 16 32-bits chunks into 80(0 - 79) 32-bits chunks */
			for ($i = 16; $i <= 79; $i++){
				$binary_32_chunks_array[$i] = decbin((bindec($binary_32_chunks_array[$i-3]) ^ bindec($binary_32_chunks_array[$i-8]) ^ bindec($binary_32_chunks_array[$i-14]) ^ bindec($binary_32_chunks_array[$i-16])) << 1);
			}
			/*echo "<br />";print_r($binary_32_chunks_array);
			echo "<br />111 ^ 101:".(111 ^ 101);
			echo "<br />011 ^ 101:".(011 ^ 101);
			echo "<br />111 ^ 111:".(111 ^ 111);
			echo "<br />000 ^ 101:".(000 ^ 101);
			echo "<br />1010<<1:".decbin((bindec(1010) << 1));*/
			
			/* Initialize hash value for this chunk */
			$a = $h0;
			$b = $h1;
			$c = $h2;
			$d = $h3;
			$e = $h4;
			
			/* Generating f and k values */
			for ($i = 0; $i <= 79; $i++){
				if ($i >= 0 && $i <= 19){
					$f = dechex((hexdec($b) & hexdec($c)) | (~hexdec($b) & hexdec($d)));
					$k = "5A827999";
				}elseif($i >= 20 && $i <= 39){
					$f = dechex(hexdec($b) ^ hexdec($c) ^ hexdec($d));
					$k = "6ED9EBA1";
				}elseif($i >= 40 && $i <= 59){
					$f = dechex((hexdec($b) & hexdec($c)) | (hexdec($b) & hexdec($d)) | (hexdec($c) & hexdec($d)));
					$k = "8F1BBCDC";
				}elseif($i >= 60 && $i <= 79){
					$f = dechex(hexdec($b) ^ hexdec($c) ^ hexdec($d));
					$k = "CA62C1D6";
				}
		
				echo "<br />Main Block - Inside for loop - Generating f and k values: a, b, c, d, e, f, k: $a, $b, $c, $d, $e, $f, $k";
				
				/* add all the variables in the next statement in decimals and convert them back to hex */
				$temp = dechex((hexdec($a) << 5) + hexdec($f) + hexdec($e) + hexdec($k) + bindec($binary_32_chunks_array[$i]));
				$e = $d;
				$d = $c;
				##DEBUG##echo "value of c in main block: ".$b;
				$c = dechex(hexdec($b) << 30);
				$b = $a;
				$a = $temp;
			}
			echo "<br />Main Block - After final assignments: a, b, c, d, e, f, k: $a, $b, $c, $d, $e, $f, $k";
			
			
			/* Add this chunk's hash to result so far: */
			$h0 = dechex(hexdec($h0) + hexdec($a));
			$h1 = dechex(hexdec($h1) + hexdec($b)); 
			$h2 = dechex(hexdec($h2) + hexdec($c));
			$h3 = dechex(hexdec($h3) + hexdec($d));
			$h4 = dechex(hexdec($h4) + hexdec($e));
	    }
		
	    /* compute the digest */
	    $hash = $h0.$h1.$h2.$h3.$h4;
	    
	    echo "<br />Computed hash using user-defined SHA1 algorithm implementation: ".$hash;
	    echo "<br />Computed hash using built-in SHA1 algorithm implementation: ".sha1($_GET["input_string"]);

	}
	

?>

Posted: Tue Nov 15, 2005 4:07 pm
by raghavan20
I have tried a new code to implement the Sha1 algorithm but still I could not succeed in it.
Could any one help me find out where i have done the mistake?


the wikipedia link
the rfc link
my page at work
Supply an input string in the text box and you will see the debug statements printed on the screen; i have tried my best to make it as easy as possible for you to understand my code.
thanks for any help.


Here is the source code of the file:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>SHA 1 Hashing</title>
</head>

<body>
<form name="form_encryption" method="get" action="">
<input type="text" value="" name="input_string"  onblur="this.form.submit();" />
</form>
</body>
</html>
<?php
	/* set parameters */		
	error_reporting(E_ALL);
	
	/* encrypt if initial conditions are met */
	if (isset($_GET["input_string"])){
		/* initialize variables */
		$input_string_ascii_array = array();
		$input_string_binary_array = array();
		$binary_512_chunks_array = array();
		$binary_32_chunks_array = array();
		
		/* Get the input varible from the $_GET array */
		$input_string = $_GET["input_string"];
		
		/* define initial variables */
		$h0 = "0x67452301";
		$h1 = "0xEFCDAB89";
		$h2 = "0x98BADCFE";
		$h3 = "0x10325476";
		$h4 = "0xC3D2E1F0";
		
		echo "<br /><br />"."<---------------Start of processing input string to binary and appending 1 to it----------------->";
		/* convert and obtain the input string in ASCII chars */
		$input_string_ascii_array = change_string_to_ascii($input_string);
		echo "<br /><br />"."Main block- Original input binary string:"; print_r($input_string_ascii_array);
		
		/* convert and obtain the ASCII chars as Binary array */
		$input_string_binary_array = change_ascii_to_binary($input_string_ascii_array);
		echo "-----------received binary array------------";
		print_r($input_string_binary_array);
		$input_string_binary = implode("", $input_string_binary_array);
		
		/* pad an additional one bit, the value one to the existing binary input string */
		$input_string_binary .= '1';
		echo "<br /><br />"."Main block- After appending to the original input binary string:".$input_string_binary; 
		
		echo "<br /><br />"."<------------End of processing input string to binary and appending 1 to it-------------->";

		/* make the string as 512 bits chunk; else pad zero to make it 512 bit chunks */
		$input_string_binary = make_512_bits_chunks($input_string_binary);
		
		/* get the input binary string as array of individual 512 bits chunks */
		$binary_512_chunks_array = get_array_n_bits_chunks($input_string_binary, 512);
		
		/* split each 512 bits chunk into 32 bit chunks array */
		$binary_32_chunks_array = get_array_n_bits_chunks($input_string_binary, 32);
		
		/* extend 16 32-bits chunks into 80(0 - 79) 32-bits chunks */
		for ($i = 16; $i <= 79; $i++){
			$binary_32_chunks_array[$i] = decbin((bindec($binary_32_chunks_array[$i-3]) ^ bindec($binary_32_chunks_array[$i-8]) ^ bindec($binary_32_chunks_array[$i-14]) ^ bindec($binary_32_chunks_array[$i-16])) << 1);
		}

		echo "<br /><br /><---------Main block - Start of displaying 80 32bits chunks:----------><br />"; 
		print_r($binary_32_chunks_array);
		echo "<br /><----------Main block - End of displaying 80 32bits chunks:----------><br />"; 
				
		/* Initialize hash value for this chunk */
		$a = $h0;
		$b = $h1;
		$c = $h2;
		$d = $h3;
		$e = $h4;

		
		/* Generating a, b, c, d, e, f and k values; Bitwise operations performed in decimals */
		echo "<br /><----------Main block - Start of generating f and k values----------><br />"; 
		for ($i = 0; $i <= 79; $i++){
			if ($i >= 0 && $i <= 19){
				$f = (hexdec($b) & hexdec($c)) | (~hexdec($b) & hexdec($d));
				$k = "0x5A827999";
			}elseif($i >= 20 && $i <= 39){
				$f = hexdec($b) ^ hexdec($c) ^ hexdec($d);
				$k = "0x6ED9EBA1";
			}elseif($i >= 40 && $i <= 59){
				$f = (hexdec($b) & hexdec($c)) or (hexdec($b) & hexdec($d)) or (hexdec($c) & hexdec($d));
				$k = "0x8F1BBCDC";
			}elseif($i >= 60 && $i <= 79){
				$f = hexdec($b) ^ hexdec($c) ^ hexdec($d);
				$k = "0xCA62C1D6";
			}
			echo "<br /><br />Main Block - f and k values: $i: $f, $k";
		
			echo "<br />Main Block: a, b, c, d, e, f, k: $a, $b, $c, $d, $e, $f, $k";
			
			/* add all the variables in the next statement in decimals and convert them back to hex */
			$temp = (hexdec($a) << 5) + $f + $e + hexdec($k) + bindec($binary_32_chunks_array[$i]);
			$e = $d;
			$d = $c;
			$c = hexdec($b) << 30;
			$b = $a;
			$a = $temp;
			
			echo "<br />Main Block - After final assignments: a, b, c, d, e, f, k: $a, $b, $c, $d, $e, $f, $k";
		}
		echo "<br /><----------Main block - End of generating a, b, c, d, e, f and k values----------><br />"; 
		
		//Add this chunk hash to the result so far
		echo "<br /><br />"."h0, h1, h2, h3 & h4:$h0, $h1, $h2, $h3, $h4";
		$h0 = dechex(hexdec($h0) + $a);
		$h1 = dechex(hexdec($h1) + $b);
		$h2 = dechex(hexdec($h2) + $c);
		$h3 = dechex(hexdec($h3) + $d);
		$h4 = dechex(hexdec($h4) + $e);
		
		$digest = $h0.$h1.$h2.$h3.$h4;
		echo "<br /><br />"."Final digest generated:".$digest;
		echo "<br />"."Php sha1 value:".sha1($_GET["input_string"]);
	}
	

?>
<?php
	function change_ascii_to_binary($input_string_ascii_array){
		/* initialize an array where all the converted ASCII chars are stored*/
		$input_string_binary_array = array();
		
		/* count the number of elements in the array*/
		$input_string_ascii_length = count($input_string_ascii_array);
		
		/* convert the input string in ASCII(Decimal) to binary data */
		for($i = 0; $i < $input_string_ascii_length; $i++){
			array_push($input_string_binary_array, pad_leading_zeros(base_convert($input_string_ascii_array[$i], 10, 2), );
		}
		echo "<br /><br />change_ascii_to_binary-input string in binary format:"; print_r($input_string_binary_array);
		return $input_string_binary_array;
	}
?>

<?php
	function change_string_to_ascii($input_string){
		/* initialize an array where all the converted ASCII chars are stored*/
		$input_string_ascii_array = array();
		
		/* find the length of the input string */
		$input_len = strlen($input_string);
		
		/* loop and extract every character of the input string and convert to ASCII */
		for($i = 0; $i < $input_len; $i++){
			##DEBUG##echo  "<br />"."Print ASCII chars:<br />".ord($input_string{$i})."<br />";
			array_push($input_string_ascii_array, ord($input_string{$i}));
		}
		
		##DEBUG##echo "<br />changeStringToAscii-Input as ASCII:"; print_r($input_string_ascii_array);
		return $input_string_ascii_array;
	}
?>

<?php
	function pad_leading_zeros($input_binary, $output_string_binary_length){
		##DEBUG##echo "Input binary:".$input_binary."<br />";
		/* input element index used to navigate characters */
		$input_index = 0; 
		
		/* New binary string which is going to returned */
		$output_binary_array = array();
		
		/* find the length of the binary input */		
		$input_binary_length = strlen($input_binary);
		
		/* find the number of zeros to be padded to the binary character */
		$pad_zeros_length = $output_string_binary_length - $input_binary_length;
		
		for ($i = 0; $i < $output_string_binary_length; $i++){
			if ($i < $pad_zeros_length){
				$output_binary_array[$i] = "0";
			}else{
				$input_index = $i - $pad_zeros_length;
				$output_binary_array[$i] = $input_binary{$input_index};
			}
			##DEBUG##echo "<br />padLeadingZeros - Leading zeros padded string:"; print_r($output_binary_array);
		}

		##DEBUG##echo  "<br />"."binary values imploded:".implode("", $output_binary_array);
		return implode("", $output_binary_array);
	}
?>

<?php
	function make_512_bits_chunks($input_string_binary){
		echo "<br /><br />"."<------------ Start of 512 bits processing --------------->";
		/* initialize variables */
		$output_string_binary = $input_string_binary;
		
		/* find the length of the input binary string */
		$input_string_length_binary = strlen($input_string_binary);
		echo  "<br />"."make_512_bits_chunks: length of the input binary string: ".$input_string_length_binary;
		
		/* convert the length of the input string in binary */
		$input_string_length_binary = base_convert($input_string_length_binary, 10, 2);
		echo  "<br />"."make_512_bits_chunks: length of the input binary string in bits: ".$input_string_length_binary;
		
		/* Pad the length of the input string in binary with leading zeros to make the length as 64 bits */
		$input_string_length_binary = pad_leading_zeros($input_string_length_binary, 64);
		echo  "<br />"."make_512_bits_chunks: length of the input binary string in 64 bits: ".$input_string_length_binary;
		
		/* find number of zeros to be padded */	
		$input_string_binary_length = strlen($input_string_binary);
		if ($input_string_binary_length < 512){
			$pad_zeros_length = (($input_string_binary_length < 448)?(448-$input_string_binary_length):(448- ($input_string_binary_length % 448)));
		}
		else{
			/* 
			1. find the integer value when dividing the input string length by 512
			2. multiply the 512 by the above value + 448 which should be the required length of the input string 
			*/
			$temp = intval($input_string_binary_length / 512);
			echo  "<br />"."make_512_bits_chunks: input binary string length/512: ".$temp;	
			$pad_zeros_length = ((512 * $temp) + 448) - $input_string_binary_length;
		}
			
		echo  "<br />"."make_512_bits_chunks: number of zeros to be padded: ".$pad_zeros_length;		
		
		/* pad trailing zeros to the input binary string to make the length of string as multiples of 448*/
		for ($i = 0; $i < abs($pad_zeros_length); $i++){
			$output_string_binary .= '0';
		}
		echo "<br />"."make_512_bits_chunks: after padding zeros to be binary string to make it multiples of 448: ".$output_string_binary;		
		
		/* append the length of the string in 64 bits with the input string in binary and in multiples in 448 */
		$output_string_binary .= $input_string_length_binary;
		echo  "<br />"."make_512_bits_chunks: Final binary string: ".$output_string_binary;

		
		echo  "<br />"."make_512_bits_chunks: Length of the binary string: ".strlen($output_string_binary);

		echo "<br /><br />"."<------------ End of 512 bits processing --------------->";

		return $output_string_binary;
	}
?>

<?php
	function get_array_n_bits_chunks($input_string_binary, $n){
		/* initialize variables */
		$binary_n_bits_chunks_array = array();
		
		/* find the number of 512 chunks available */
		$input_string_binary_chunks = strlen($input_string_binary) / $n ;
		
		/* look and separate 'n' bits chunks and put them in array */
		for ($i = 0; $i < $input_string_binary_chunks; $i++){
			array_push($binary_n_bits_chunks_array, substr($input_string_binary, $i * $n, $n));
		}
		
		##DEBUG##echo "<br />get_array_$n_bits_chunks:"; print_r($binary_n_bits_chunks_array);
		return $binary_n_bits_chunks_array;
	}
?>