[C#] - Calculating CRC32 Hash from any file or string

Discussion in 'Mixed Languages' started by Josh Cell, Sep 18, 2011.

  1. Josh Cell

    Josh Cell MDL Developer

    Jan 8, 2011
    3,515
    7,170
    120
    #1 Josh Cell, Sep 18, 2011
    Last edited by a moderator: Apr 20, 2017
    This is a small code to get CRC32 from any file or string:

    Code:
        public class Crc32 : HashAlgorithm //Core code
        {
            public const UInt32 DefaultPolynomial = 0xedb88320;
            public const UInt32 DefaultSeed = 0xffffffff;
    
            private UInt32 hash;
            private UInt32 seed;
            private UInt32[] table;
            private static UInt32[] defaultTable;
    
            public Crc32()
            {
                table = InitializeTable(DefaultPolynomial);
                seed = DefaultSeed;
                Initialize();
            }
    
            public Crc32(UInt32 polynomial, UInt32 seed)
            {
                table = InitializeTable(polynomial);
                this.seed = seed;
                Initialize();
            }
    
            public override void Initialize()
            {
                hash = seed;
            }
    
            protected override void HashCore(byte[] buffer, int start, int length)
            {
                hash = CalculateHash(table, hash, buffer, start, length);
            }
    
            protected override byte[] HashFinal()
            {
                byte[] hashBuffer = UInt32ToBigEndianBytes(~hash);
                this.HashValue = hashBuffer;
                return hashBuffer;
            }
    
            public override int HashSize
            {
                get { return 32; }
            }
    
            public static UInt32 Compute(byte[] buffer)
            {
                return ~CalculateHash(InitializeTable(DefaultPolynomial), DefaultSeed, buffer, 0, buffer.Length);
            }
    
            public static UInt32 Compute(UInt32 seed, byte[] buffer)
            {
                return ~CalculateHash(InitializeTable(DefaultPolynomial), seed, buffer, 0, buffer.Length);
            }
    
            public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer)
            {
                return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
            }
    
            private static UInt32[] InitializeTable(UInt32 polynomial)
            {
                if (polynomial == DefaultPolynomial && defaultTable != null)
                    return defaultTable;
    
                UInt32[] createTable = new UInt32[256];
                for (int i = 0; i < 256; i++)
                {
                    UInt32 entry = (UInt32)i;
                    for (int j = 0; j < 8; j++)
                        if ((entry & 1) == 1)
                            entry = (entry >> 1) ^ polynomial;
                        else
                            entry = entry >> 1;
                    createTable = entry;
                }
    
                if (polynomial == DefaultPolynomial)
                    defaultTable = createTable;
    
                return createTable;
            }
    
            private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, byte[] buffer, int start, int size)
            {
                UInt32 crc = seed;
                for (int i = start; i < size; i++)
                    unchecked
                    {
                        crc = (crc >> 8) ^ table[buffer ^ crc & 0xff];
                    }
                return crc;
            }
    
            private byte[] UInt32ToBigEndianBytes(UInt32 x)
            {
                return new byte[] {
    (byte)((x >> 24) & 0xff),
    (byte)((x >> 16) & 0xff),
    (byte)((x >> 8) & 0xff),
    (byte)(x & 0xff)
    };
            }
        }
    
            public static void Crc(string file) // invoke code
            {
                try
                {
                    Crc32 crc32 = new Crc32();
                    String hash = String.Empty;
                    byte[] fs = File.ReadAllBytes(file);
                    foreach (byte b in crc32.ComputeHash(fs)) hash += b.ToString("x2").ToUpper();
                    Hashes = hash;
                }
                catch
                {
                }
            }


    To use this:

    Code:
            Crc("your file to get CRC");
            Hashes = "your object to dump CRC" // as textBox1.Text;
    I hope it's useful :eek:
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. ThePieMan73

    ThePieMan73 MDL Novice

    Nov 14, 2011
    4
    0
    0
    Hi Josh, this is awesome. Thank you. I have a question about CRC32 though .. given that you are generating a hash here for a string .. how easily can it be reversed? Say I have a hash value of 16164246 , how easily could the code above be modified to generate a list of strings that have the same hash value?:biggrin:
     
  3. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    So you have a hash value of 16164246 for a string, and you want to generate the same hash for multiple strings ???
    Sorry but your question doesn't make much senseo_O
    Can you elaborate a little?
     
  4. ThePieMan73

    ThePieMan73 MDL Novice

    Nov 14, 2011
    4
    0
    0
    Hi,
    Basically, what it boils down to is this:
    I have a checksum of a string which is : 16164246
    I have a bet with a colleague in the office.
    He has bet me lunch for a week that I cannot easily generate other strings that would match that CRC32 checksum.
    If you can point me in the right direction, I would be forever grateful :)

    Does that make sense? o_O
     
  5. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    I understand what your saying but to have other strings compute the same hash outcome sounds near impossible. Ive not had any luck trying this, you can use my ComputeHASH Utility to try computing strings and see how you go. I think maybe lunch is on you tho;):)

    ComputeHASH Utility
     
  6. ThePieMan73

    ThePieMan73 MDL Novice

    Nov 14, 2011
    4
    0
    0
    Oh well, worth asking :)
    I know I am close, that is what's killing me with this.
    The file in question is a PST file, and I know that CRC32 password hashing in those is really weak. The promise at the moment, is that I have to write the solution, not download a third party tool. (This in it self is a massive undertaking on my part!!!!)
    I have been given a copy of the file, and can get the Password checksum out of it (the one in the previous comments), and now I am at the point of trying to force collisions with that checksum so I can open the file.
    Read things on the web by a developer - if you look up "bug in outlook pst password protection" it explains it all.
    It's like the explanation on that site is teasing me :)

    Thanks for your help though, have a great day :)
     
  7. Alphawaves

    Alphawaves Super Moderator/Developer
    Staff Member

    Aug 11, 2008
    6,222
    22,280
    210
    If i had more time i could of helped you but im really busy..:(
    Good luck anyway, hope you get your lunches..:D;)
     
  8. ThePieMan73

    ThePieMan73 MDL Novice

    Nov 14, 2011
    4
    0
    0
    That's cool, thank you anyway :)
     
  9. PAYMYRENT

    PAYMYRENT MDL Developer

    Jul 28, 2009
    1,460
    420
    60
    ok i may be late but i noticed he didnt tell you how to do it right.

    just convert your string to a byte array then hash the array lol really simple
     
  10. Muerto

    Muerto MDL Debugger

    Mar 7, 2012
    1,855
    2,103
    60
    Was he asking if you can generate a different CRC32 from different data?

    I bet a Ferrari you can't :D