locked
SHA1 Source code

    Question

  • Hello.

    i want use sha-1 algorithms to encrypted an string. i think sha-1 class is exiting in C# but i need source code.i want know how implement in C#.

    is there other asymmetric cryptography algorithms source code?

    Thanks.

    Thursday, December 13, 2012 12:01 PM

Answers

  • That makes it an interesting exercise. :)

    For more help may be you should consult RFC 3174 (also available as pdf - try googling). It has an example in C that will convert to C# but requires some work (and a knowledge of C).

    There might be a converter online - but I would not hold out much hope of it getting the conversion 100% correct.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    • Marked as answer by Bouki Thursday, December 13, 2012 7:18 PM
    Thursday, December 13, 2012 3:53 PM
  • Here's a conversion from the C code in the RFC. It compiles and runs but gives incorrect results so needs debugging. However, might give you some idea about what's involved. NB it's not a good bit of C# but reasonably close to the C.

    using System;
    using System.Text;
    
    namespace SHA1_Algo
    {
       class Program
       {
          #region Test Data
          //Test data from RFC C program - assumes ASCII strings
          static string TEST2a = "abcdbcdecdefdefgefghfghighijhi";
          static string TEST2b = "jkijkljklmklmnlmnomnopnopq";
          static string TEST4a = "01234567012345670123456701234567";
          static string TEST4b = "01234567012345670123456701234567";
    
          static string TEST1 = "abc";
          static string TEST2 = TEST2a + TEST2b;
          static string TEST3 = "a";
          static string TEST4 = TEST4a + TEST4b;
          static string[] testarray = { TEST1, TEST2, TEST3, TEST4 };
    
          //Test data as ASCII byte arrays - may be needed to work with algo.
          static byte[] t2a = Encoding.ASCII.GetBytes(TEST2a);
          static byte[] t2b = Encoding.ASCII.GetBytes(TEST2b);
          static byte[] t4a = Encoding.ASCII.GetBytes(TEST4a);
          static byte[] t4b = Encoding.ASCII.GetBytes(TEST4b);
    
          static byte[] t1 = Encoding.ASCII.GetBytes(TEST1);
          static byte[] t2 = Encoding.ASCII.GetBytes(TEST2);
          static byte[] t3 = Encoding.ASCII.GetBytes(TEST3);
          static byte[] t4 = Encoding.ASCII.GetBytes(TEST4);
    
          //static byte[] t2a = Encoding.Unicode.GetBytes(TEST2a);
          //static byte[] t2b = Encoding.Unicode.GetBytes(TEST2b);
          //static byte[] t4a = Encoding.Unicode.GetBytes(TEST4a);
          //static byte[] t4b = Encoding.Unicode.GetBytes(TEST4b);
    
          //static byte[] t1 = Encoding.Unicode.GetBytes(TEST1);
          //static byte[] t2 = Encoding.Unicode.GetBytes(TEST2);
          //static byte[] t3 = Encoding.Unicode.GetBytes(TEST3);
          //static byte[] t4 = Encoding.Unicode.GetBytes(TEST4);
    
          static byte[][] tester = { t1, t2, t3, t4 };
    
          static long[] repeatcount = { 1, 1, 1000000, 10 };
          static string[] resultarray = {
              "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
              "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
              "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
              "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
              };
          #endregion
    
          static UInt32 SHA1HashSize = 20;
          enum SHA_enum
          {
             shaSuccess = 0,
             shaNull,            /* Null pointer parameter */
             shaInputTooLong,    /* input data too long */
             shaStateError       /* called Input after Result */
          };
    
          static int SHA1Reset(SHA1Context context)
          {
             if (context == null)
             {
                return (int)SHA_enum.shaNull;
             }
    
             context.Length_Low = 0;
             context.Length_High = 0;
             context.Message_Block_Index = 0;
    
             context.Intermediate_Hash[0] = 0x67452301;
             context.Intermediate_Hash[1] = 0xEFCDAB89;
             context.Intermediate_Hash[2] = 0x98BADCFE;
             context.Intermediate_Hash[3] = 0x10325476;
             context.Intermediate_Hash[4] = 0xC3D2E1F0;
    
             context.Computed = 0;
             context.Corrupted = 0;
             return (int)SHA_enum.shaSuccess;
          }
    
          static int SHA1Input(SHA1Context context, byte[] message_array, UInt32 length)
          {
             if (length == 0) { return (int)SHA_enum.shaSuccess; }
             if (context == null || message_array == null) { return (int)SHA_enum.shaNull; }
    
             if (context.Computed != 0)
             {
                context.Corrupted = (int)SHA_enum.shaStateError;
                return (int)SHA_enum.shaStateError;
             }
    
             if (context.Corrupted != 0) { return context.Corrupted; }
    
             int i = 0;
             while (length == 0 && context.Corrupted == 0)
             {
                length--;
                context.Message_Block[context.Message_Block_Index++] = (byte)(message_array[i] & 0xFF);
                context.Length_Low += 8;
                if (context.Length_Low == 0)
                {
                   context.Length_High++;
                   if (context.Length_High == 0)
                   {
                      /* Message is too long */
                      context.Corrupted = 1;
                   }
                }
    
                if (context.Message_Block_Index == 64) { SHA1ProcessMessageBlock(context); }
                i++;
             }
             return (int)SHA_enum.shaSuccess;
          }
    
          static void SHA1ProcessMessageBlock(SHA1Context context)
          {
             UInt32[] K = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
             int t;                        /* Loop counter                */
             UInt32 temp;                  /* Temporary word value        */
             UInt32[] W = new UInt32[80];  /* Word sequence               */
             UInt32 A, B, C, D, E;         /* Word buffers                */
    
             /* Initialize the first 16 words in the array W    */
             for (t = 0; t < 16; t++)
             {
                W[t] = (UInt32)context.Message_Block[t * 4] << 24;
                W[t] |= (UInt32)context.Message_Block[t * 4 + 1] << 16;
                W[t] |= (UInt32)context.Message_Block[t * 4 + 2] << 8;
                W[t] |= (UInt32)context.Message_Block[t * 4 + 3];
             }
    
             for (t = 16; t < 80; t++)
             {
                W[t] = SHA1CircularShift(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
             }
    
             A = context.Intermediate_Hash[0];
             B = context.Intermediate_Hash[1];
             C = context.Intermediate_Hash[2];
             D = context.Intermediate_Hash[3];
             E = context.Intermediate_Hash[4];
    
             for (t = 0; t < 20; t++)
             {
                temp = SHA1CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             for (t = 20; t < 40; t++)
             {
                temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             for (t = 40; t < 60; t++)
             {
                temp = SHA1CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             for (t = 60; t < 80; t++)
             {
                temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             context.Intermediate_Hash[0] += A;
             context.Intermediate_Hash[1] += B;
             context.Intermediate_Hash[2] += C;
             context.Intermediate_Hash[3] += D;
             context.Intermediate_Hash[4] += E;
    
             context.Message_Block_Index = 0;
          }
    
          static void SHA1PadMessage(SHA1Context context)
          {
             if (context.Message_Block_Index > 55)
             {
                context.Message_Block[context.Message_Block_Index++] = 0x80;
                while (context.Message_Block_Index < 64)
                {
                   context.Message_Block[context.Message_Block_Index++] = 0;
                }
                SHA1ProcessMessageBlock(context);
                while (context.Message_Block_Index < 56)
                {
                   context.Message_Block[context.Message_Block_Index++] = 0;
                }
             }
             else
             {
                context.Message_Block[context.Message_Block_Index++] = 0x80;
                while (context.Message_Block_Index < 56)
                {
                   context.Message_Block[context.Message_Block_Index++] = 0;
                }
             }
    
             /*  Store the message length as the last 8 octets     */
             context.Message_Block[56] = (byte)(context.Length_High >> 24);
             context.Message_Block[57] = (byte)(context.Length_High >> 16);
             context.Message_Block[58] = (byte)(context.Length_High >> 8);
             context.Message_Block[59] = (byte)(context.Length_High);
             context.Message_Block[60] = (byte)(context.Length_Low >> 24);
             context.Message_Block[61] = (byte)(context.Length_Low >> 16);
             context.Message_Block[62] = (byte)(context.Length_Low >> 8);
             context.Message_Block[63] = (byte)(context.Length_Low);
    
             SHA1ProcessMessageBlock(context);
          }
    
          static int SHA1Result(SHA1Context context, byte[] Message_Digest)
          {
             int i;
    
             if (context == null || Message_Digest == null) { return (int)SHA_enum.shaNull; }
             if (context.Corrupted != 0) { return context.Corrupted; }
    
             if (context.Computed == 0)
             {
                SHA1PadMessage(context);
                for (i = 0; i < 64; ++i)
                {
                   /* message may be sensitive, clear it out */
                   context.Message_Block[i] = 0;
                }
                context.Length_Low = 0;    /* and clear length */
                context.Length_High = 0;
                context.Computed = 1;
             }
    
             for (i = 0; i < SHA1HashSize; ++i)
             {
                Message_Digest[i] = (byte)(context.Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
             }
             return (int)SHA_enum.shaSuccess;
          }
    
          static UInt32 SHA1CircularShift(Int32 bits, UInt32 word)
          {
             return ((word << bits) | (word >> (32 - bits)));
          }
    
          static int Main(string[] args)
          {
             SHA1Context sha = new SHA1Context();
             int i, j, err;
             byte[] Message_Digest = new byte[20];
    
             /*   Perform SHA-1 tests     */
             for (j = 0; j < 4; ++j)
             {
                Console.Write("\nTest {0}: {1}, '{2}'\n", j + 1, repeatcount[j], testarray[j]);
                err = SHA1Reset(sha);
                if (err != 0)
                {
                   Console.Write("SHA1Reset Error {0}.\n", err);
                   break;    /* out of for j loop */
                }
    
                for (i = 0; i < repeatcount[j]; ++i)
                {
                   err = SHA1Input(sha, tester[j], (UInt32)tester[j].Length - 1);
                   if (err != 0)
                   {
                      Console.Write("SHA1Input Error {0}.\n", err);
                      break;    /* out of for i loop */
                   }
                }
    
                err = SHA1Result(sha, Message_Digest);
                if (err != 0)
                {
                   Console.Write("SHA1Result Error {0}, could not compute message digest.\n", err);
                }
                else
                {
                   Console.Write("\t");
                   for (i = 0; i < 20; ++i)
                   {
                      Console.Write("{0} ", Message_Digest[i].ToString("X2"));
                   }
                   Console.Write("\n");
                }
                Console.Write("Should match:\n");
                Console.Write("\t{0}\n", resultarray[j]);
             }
    
             /* Test some error returns */
             err = SHA1Input(sha, tester[1], 1);
             Console.Write("\nError {0}. Should be {1}.\n", err, (int)SHA_enum.shaStateError);
             err = SHA1Reset(null);
             Console.Write("\nError {0}. Should be {1}.\n", err, (int)SHA_enum.shaNull);
             Console.WriteLine("\n === ALL DONE ====");
             Console.ReadLine();
             return 0;
          }
       }
    
       public class SHA1Context
       {
          /* This structure will hold context information for the SHA-1 hashing operation  */
          static UInt32 SHA1HashSize = 20;
          public UInt32[] Intermediate_Hash = new UInt32[SHA1HashSize / 4]; /* Message Digest  */
          public UInt32 Length_Low;                        /* Message length in bits      */
          public UInt32 Length_High;                       /* Message length in bits      */
          public int Message_Block_Index;                  /* Index into message block array   */
          public byte[] Message_Block = new byte[64];      /* 512-bit message blocks      */
          public int Computed;                             /* Is the digest computed?         */
          public int Corrupted;                            /* Is the message digest corrupted? */
       }
    }
    


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    • Marked as answer by Bouki Friday, December 14, 2012 3:41 AM
    Thursday, December 13, 2012 7:35 PM

All replies

  • Please check into the following URLs

    http://pastebin.com/fkfgvsnw

    http://www.mindstick.com/Blog/119/Implementing%20Cryptography%20in%20C%20NET%20by%20using%20SHA1%20Algorithm


    With Thanks and Regards
    Sambath Raj.C
    click "Proposed As Answer by" if this post solves your problem or "Vote As Helpful" if a post has been useful to you
    Happy Programming!

    Thursday, December 13, 2012 12:13 PM
  • Thanks dear sambath.

    but in that urls show how to calculate SHA1 for given string by using System.Security.Cryptography class.

    but i need sha-1 source code!

    Thursday, December 13, 2012 12:45 PM
  • Look here for an example in pseudo code. It looks like it will translate easily into C#.

    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    Thursday, December 13, 2012 1:41 PM
  • thanks Riced.

    would you please help me for translating this to c#?

    i really dont understand whats happenig in this pesudo code:

    Note 1: All variables are unsigned 32 bits and wrap modulo 232 when calculating
    Note 2: All constants in this pseudo code are in big endian. 
            Within each word, the most significant byte is stored in the leftmost byte position
    
    Initialize variables:
    h0 = 0x67452301
    h1 = 0xEFCDAB89
    h2 = 0x98BADCFE
    h3 = 0x10325476
    h4 = 0xC3D2E1F0
    
    Pre-processing:
    append the bit '1' to the message
    append 0 ≤ k < 512 bits '0', so that the resulting message length (in bits)
       is congruent to 448 (mod 512)
    append length of message (before pre-processing), in bits, as 64-bit big-endian integer
    
    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:[37]
        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
    
    Produce the final hash value (big-endian):
    digest = hash = h0 append h1 append h2 append h3 append h4

    Thursday, December 13, 2012 2:42 PM
  • That makes it an interesting exercise. :)

    For more help may be you should consult RFC 3174 (also available as pdf - try googling). It has an example in C that will convert to C# but requires some work (and a knowledge of C).

    There might be a converter online - but I would not hold out much hope of it getting the conversion 100% correct.


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    • Marked as answer by Bouki Thursday, December 13, 2012 7:18 PM
    Thursday, December 13, 2012 3:53 PM
  • i guess this means end of discussion. :)

    just one more question:

    i know i should ask it it in c++ forum but:

    is this exist in c++?

    • Edited by Bouki Thursday, December 13, 2012 5:58 PM
    Thursday, December 13, 2012 5:45 PM
  • The.NET source code is available as ReferenceSource or use ILSpy.

    Thursday, December 13, 2012 7:00 PM
  • Here's a conversion from the C code in the RFC. It compiles and runs but gives incorrect results so needs debugging. However, might give you some idea about what's involved. NB it's not a good bit of C# but reasonably close to the C.

    using System;
    using System.Text;
    
    namespace SHA1_Algo
    {
       class Program
       {
          #region Test Data
          //Test data from RFC C program - assumes ASCII strings
          static string TEST2a = "abcdbcdecdefdefgefghfghighijhi";
          static string TEST2b = "jkijkljklmklmnlmnomnopnopq";
          static string TEST4a = "01234567012345670123456701234567";
          static string TEST4b = "01234567012345670123456701234567";
    
          static string TEST1 = "abc";
          static string TEST2 = TEST2a + TEST2b;
          static string TEST3 = "a";
          static string TEST4 = TEST4a + TEST4b;
          static string[] testarray = { TEST1, TEST2, TEST3, TEST4 };
    
          //Test data as ASCII byte arrays - may be needed to work with algo.
          static byte[] t2a = Encoding.ASCII.GetBytes(TEST2a);
          static byte[] t2b = Encoding.ASCII.GetBytes(TEST2b);
          static byte[] t4a = Encoding.ASCII.GetBytes(TEST4a);
          static byte[] t4b = Encoding.ASCII.GetBytes(TEST4b);
    
          static byte[] t1 = Encoding.ASCII.GetBytes(TEST1);
          static byte[] t2 = Encoding.ASCII.GetBytes(TEST2);
          static byte[] t3 = Encoding.ASCII.GetBytes(TEST3);
          static byte[] t4 = Encoding.ASCII.GetBytes(TEST4);
    
          //static byte[] t2a = Encoding.Unicode.GetBytes(TEST2a);
          //static byte[] t2b = Encoding.Unicode.GetBytes(TEST2b);
          //static byte[] t4a = Encoding.Unicode.GetBytes(TEST4a);
          //static byte[] t4b = Encoding.Unicode.GetBytes(TEST4b);
    
          //static byte[] t1 = Encoding.Unicode.GetBytes(TEST1);
          //static byte[] t2 = Encoding.Unicode.GetBytes(TEST2);
          //static byte[] t3 = Encoding.Unicode.GetBytes(TEST3);
          //static byte[] t4 = Encoding.Unicode.GetBytes(TEST4);
    
          static byte[][] tester = { t1, t2, t3, t4 };
    
          static long[] repeatcount = { 1, 1, 1000000, 10 };
          static string[] resultarray = {
              "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
              "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
              "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
              "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
              };
          #endregion
    
          static UInt32 SHA1HashSize = 20;
          enum SHA_enum
          {
             shaSuccess = 0,
             shaNull,            /* Null pointer parameter */
             shaInputTooLong,    /* input data too long */
             shaStateError       /* called Input after Result */
          };
    
          static int SHA1Reset(SHA1Context context)
          {
             if (context == null)
             {
                return (int)SHA_enum.shaNull;
             }
    
             context.Length_Low = 0;
             context.Length_High = 0;
             context.Message_Block_Index = 0;
    
             context.Intermediate_Hash[0] = 0x67452301;
             context.Intermediate_Hash[1] = 0xEFCDAB89;
             context.Intermediate_Hash[2] = 0x98BADCFE;
             context.Intermediate_Hash[3] = 0x10325476;
             context.Intermediate_Hash[4] = 0xC3D2E1F0;
    
             context.Computed = 0;
             context.Corrupted = 0;
             return (int)SHA_enum.shaSuccess;
          }
    
          static int SHA1Input(SHA1Context context, byte[] message_array, UInt32 length)
          {
             if (length == 0) { return (int)SHA_enum.shaSuccess; }
             if (context == null || message_array == null) { return (int)SHA_enum.shaNull; }
    
             if (context.Computed != 0)
             {
                context.Corrupted = (int)SHA_enum.shaStateError;
                return (int)SHA_enum.shaStateError;
             }
    
             if (context.Corrupted != 0) { return context.Corrupted; }
    
             int i = 0;
             while (length == 0 && context.Corrupted == 0)
             {
                length--;
                context.Message_Block[context.Message_Block_Index++] = (byte)(message_array[i] & 0xFF);
                context.Length_Low += 8;
                if (context.Length_Low == 0)
                {
                   context.Length_High++;
                   if (context.Length_High == 0)
                   {
                      /* Message is too long */
                      context.Corrupted = 1;
                   }
                }
    
                if (context.Message_Block_Index == 64) { SHA1ProcessMessageBlock(context); }
                i++;
             }
             return (int)SHA_enum.shaSuccess;
          }
    
          static void SHA1ProcessMessageBlock(SHA1Context context)
          {
             UInt32[] K = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
             int t;                        /* Loop counter                */
             UInt32 temp;                  /* Temporary word value        */
             UInt32[] W = new UInt32[80];  /* Word sequence               */
             UInt32 A, B, C, D, E;         /* Word buffers                */
    
             /* Initialize the first 16 words in the array W    */
             for (t = 0; t < 16; t++)
             {
                W[t] = (UInt32)context.Message_Block[t * 4] << 24;
                W[t] |= (UInt32)context.Message_Block[t * 4 + 1] << 16;
                W[t] |= (UInt32)context.Message_Block[t * 4 + 2] << 8;
                W[t] |= (UInt32)context.Message_Block[t * 4 + 3];
             }
    
             for (t = 16; t < 80; t++)
             {
                W[t] = SHA1CircularShift(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
             }
    
             A = context.Intermediate_Hash[0];
             B = context.Intermediate_Hash[1];
             C = context.Intermediate_Hash[2];
             D = context.Intermediate_Hash[3];
             E = context.Intermediate_Hash[4];
    
             for (t = 0; t < 20; t++)
             {
                temp = SHA1CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             for (t = 20; t < 40; t++)
             {
                temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             for (t = 40; t < 60; t++)
             {
                temp = SHA1CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             for (t = 60; t < 80; t++)
             {
                temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3];
                E = D;
                D = C;
                C = SHA1CircularShift(30, B);
                B = A;
                A = temp;
             }
    
             context.Intermediate_Hash[0] += A;
             context.Intermediate_Hash[1] += B;
             context.Intermediate_Hash[2] += C;
             context.Intermediate_Hash[3] += D;
             context.Intermediate_Hash[4] += E;
    
             context.Message_Block_Index = 0;
          }
    
          static void SHA1PadMessage(SHA1Context context)
          {
             if (context.Message_Block_Index > 55)
             {
                context.Message_Block[context.Message_Block_Index++] = 0x80;
                while (context.Message_Block_Index < 64)
                {
                   context.Message_Block[context.Message_Block_Index++] = 0;
                }
                SHA1ProcessMessageBlock(context);
                while (context.Message_Block_Index < 56)
                {
                   context.Message_Block[context.Message_Block_Index++] = 0;
                }
             }
             else
             {
                context.Message_Block[context.Message_Block_Index++] = 0x80;
                while (context.Message_Block_Index < 56)
                {
                   context.Message_Block[context.Message_Block_Index++] = 0;
                }
             }
    
             /*  Store the message length as the last 8 octets     */
             context.Message_Block[56] = (byte)(context.Length_High >> 24);
             context.Message_Block[57] = (byte)(context.Length_High >> 16);
             context.Message_Block[58] = (byte)(context.Length_High >> 8);
             context.Message_Block[59] = (byte)(context.Length_High);
             context.Message_Block[60] = (byte)(context.Length_Low >> 24);
             context.Message_Block[61] = (byte)(context.Length_Low >> 16);
             context.Message_Block[62] = (byte)(context.Length_Low >> 8);
             context.Message_Block[63] = (byte)(context.Length_Low);
    
             SHA1ProcessMessageBlock(context);
          }
    
          static int SHA1Result(SHA1Context context, byte[] Message_Digest)
          {
             int i;
    
             if (context == null || Message_Digest == null) { return (int)SHA_enum.shaNull; }
             if (context.Corrupted != 0) { return context.Corrupted; }
    
             if (context.Computed == 0)
             {
                SHA1PadMessage(context);
                for (i = 0; i < 64; ++i)
                {
                   /* message may be sensitive, clear it out */
                   context.Message_Block[i] = 0;
                }
                context.Length_Low = 0;    /* and clear length */
                context.Length_High = 0;
                context.Computed = 1;
             }
    
             for (i = 0; i < SHA1HashSize; ++i)
             {
                Message_Digest[i] = (byte)(context.Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)));
             }
             return (int)SHA_enum.shaSuccess;
          }
    
          static UInt32 SHA1CircularShift(Int32 bits, UInt32 word)
          {
             return ((word << bits) | (word >> (32 - bits)));
          }
    
          static int Main(string[] args)
          {
             SHA1Context sha = new SHA1Context();
             int i, j, err;
             byte[] Message_Digest = new byte[20];
    
             /*   Perform SHA-1 tests     */
             for (j = 0; j < 4; ++j)
             {
                Console.Write("\nTest {0}: {1}, '{2}'\n", j + 1, repeatcount[j], testarray[j]);
                err = SHA1Reset(sha);
                if (err != 0)
                {
                   Console.Write("SHA1Reset Error {0}.\n", err);
                   break;    /* out of for j loop */
                }
    
                for (i = 0; i < repeatcount[j]; ++i)
                {
                   err = SHA1Input(sha, tester[j], (UInt32)tester[j].Length - 1);
                   if (err != 0)
                   {
                      Console.Write("SHA1Input Error {0}.\n", err);
                      break;    /* out of for i loop */
                   }
                }
    
                err = SHA1Result(sha, Message_Digest);
                if (err != 0)
                {
                   Console.Write("SHA1Result Error {0}, could not compute message digest.\n", err);
                }
                else
                {
                   Console.Write("\t");
                   for (i = 0; i < 20; ++i)
                   {
                      Console.Write("{0} ", Message_Digest[i].ToString("X2"));
                   }
                   Console.Write("\n");
                }
                Console.Write("Should match:\n");
                Console.Write("\t{0}\n", resultarray[j]);
             }
    
             /* Test some error returns */
             err = SHA1Input(sha, tester[1], 1);
             Console.Write("\nError {0}. Should be {1}.\n", err, (int)SHA_enum.shaStateError);
             err = SHA1Reset(null);
             Console.Write("\nError {0}. Should be {1}.\n", err, (int)SHA_enum.shaNull);
             Console.WriteLine("\n === ALL DONE ====");
             Console.ReadLine();
             return 0;
          }
       }
    
       public class SHA1Context
       {
          /* This structure will hold context information for the SHA-1 hashing operation  */
          static UInt32 SHA1HashSize = 20;
          public UInt32[] Intermediate_Hash = new UInt32[SHA1HashSize / 4]; /* Message Digest  */
          public UInt32 Length_Low;                        /* Message length in bits      */
          public UInt32 Length_High;                       /* Message length in bits      */
          public int Message_Block_Index;                  /* Index into message block array   */
          public byte[] Message_Block = new byte[64];      /* 512-bit message blocks      */
          public int Computed;                             /* Is the digest computed?         */
          public int Corrupted;                            /* Is the message digest corrupted? */
       }
    }
    


    Regards David R
    ---------------------------------------------------------------
    The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones.
    Object-oriented programming offers a sustainable way to write spaghetti code. - Paul Graham.
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.

    • Marked as answer by Bouki Friday, December 14, 2012 3:41 AM
    Thursday, December 13, 2012 7:35 PM