Tag archive for 'hashing'

24
Nov

Calculating Elf-32 in C# and .NET

Because you can never have enough hashing algorithms at your disposal this one is compatible with the elf_hash function that forms part of the Executable and Linkable Format.

using System;
using System.Security.Cryptography;

public class Elf32 : HashAlgorithm
{
	private UInt32 hash;

	public Elf32()
	{
		Initialize();
	}

	public override void Initialize()
	{
		hash = 0;
	}

	protected override void HashCore(byte[] buffer, int start, int length)
	{
		hash = CalculateHash(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(UInt32 polynomial, UInt32 seed, byte[] buffer)
	{
		return CalculateHash(seed, buffer, 0, buffer.Length);
	}

	private static UInt32 CalculateHash(UInt32 seed, byte[] buffer, int start, int size)
	{
		UInt32 hash = seed;

		for (int i = start; i < size; i++)
			unchecked {
				hash = (hash << 4) + buffer[i];
				UInt32 work = (hash & 0xf0000000);
				if (work != 0)
					hash ^= (work >> 24);
				hash &= ~work;
			}
		return hash;
	}

	private byte[] UInt32ToBigEndianBytes(UInt32 x)
	{
		return new byte[] {
			(byte)((x >> 24) & 0xff),
			(byte)((x >> 16) & 0xff),
			(byte)((x >> 8) & 0xff),
			(byte)(x & 0xff)
		};
	}
}

[)amien

19
Nov

Calculating CRC-64 in C# and .NET

Seeing how the CRC-32 C# class I posted some time ago continues to get lots of Google hits I thought I'd post a CRC-64 version which will no doubt be far less popular being the more limited use. Again, do not use this as a secure message signature, it's really for backward compatibility with legacy systems.

Unlike the previous CRC-32 version this one uses a pre-generated constant (well, readonly) table as the generation code was quite slow.

using System;
using System.Security.Cryptography;

public class Crc64 : HashAlgorithm
{
	public const UInt64 DefaultSeed = 0x0;

	private static readonly UInt64[] table = new UInt64[] {
		0x0000000000000000L, 0x01b0000000000000L, 0x0360000000000000L,
		0x02d0000000000000L, 0x06c0000000000000L, 0x0770000000000000L,
		0x05a0000000000000L, 0x0410000000000000L, 0x0d80000000000000L,
		0x0c30000000000000L, 0x0ee0000000000000L, 0x0f50000000000000L,
		0x0b40000000000000L, 0x0af0000000000000L, 0x0820000000000000L,
		0x0990000000000000L, 0x1b00000000000000L, 0x1ab0000000000000L,
		0x1860000000000000L, 0x19d0000000000000L, 0x1dc0000000000000L,
		0x1c70000000000000L, 0x1ea0000000000000L, 0x1f10000000000000L,
		0x1680000000000000L, 0x1730000000000000L, 0x15e0000000000000L,
		0x1450000000000000L, 0x1040000000000000L, 0x11f0000000000000L,
		0x1320000000000000L, 0x1290000000000000L, 0x3600000000000000L,
		0x37b0000000000000L, 0x3560000000000000L, 0x34d0000000000000L,
		0x30c0000000000000L, 0x3170000000000000L, 0x33a0000000000000L,
		0x3210000000000000L, 0x3b80000000000000L, 0x3a30000000000000L,
		0x38e0000000000000L, 0x3950000000000000L, 0x3d40000000000000L,
		0x3cf0000000000000L, 0x3e20000000000000L, 0x3f90000000000000L,
		0x2d00000000000000L, 0x2cb0000000000000L, 0x2e60000000000000L,
		0x2fd0000000000000L, 0x2bc0000000000000L, 0x2a70000000000000L,
		0x28a0000000000000L, 0x2910000000000000L, 0x2080000000000000L,
		0x2130000000000000L, 0x23e0000000000000L, 0x2250000000000000L,
		0x2640000000000000L, 0x27f0000000000000L, 0x2520000000000000L,
		0x2490000000000000L, 0x6c00000000000000L, 0x6db0000000000000L,
		0x6f60000000000000L, 0x6ed0000000000000L, 0x6ac0000000000000L,
		0x6b70000000000000L, 0x69a0000000000000L, 0x6810000000000000L,
		0x6180000000000000L, 0x6030000000000000L, 0x62e0000000000000L,
		0x6350000000000000L, 0x6740000000000000L, 0x66f0000000000000L,
		0x6420000000000000L, 0x6590000000000000L, 0x7700000000000000L,
		0x76b0000000000000L, 0x7460000000000000L, 0x75d0000000000000L,
		0x71c0000000000000L, 0x7070000000000000L, 0x72a0000000000000L,
		0x7310000000000000L, 0x7a80000000000000L, 0x7b30000000000000L,
		0x79e0000000000000L, 0x7850000000000000L, 0x7c40000000000000L,
		0x7df0000000000000L, 0x7f20000000000000L, 0x7e90000000000000L,
		0x5a00000000000000L, 0x5bb0000000000000L, 0x5960000000000000L,
		0x58d0000000000000L, 0x5cc0000000000000L, 0x5d70000000000000L,
		0x5fa0000000000000L, 0x5e10000000000000L, 0x5780000000000000L,
		0x5630000000000000L, 0x54e0000000000000L, 0x5550000000000000L,
		0x5140000000000000L, 0x50f0000000000000L, 0x5220000000000000L,
		0x5390000000000000L, 0x4100000000000000L, 0x40b0000000000000L,
		0x4260000000000000L, 0x43d0000000000000L, 0x47c0000000000000L,
		0x4670000000000000L, 0x44a0000000000000L, 0x4510000000000000L,
		0x4c80000000000000L, 0x4d30000000000000L, 0x4fe0000000000000L,
		0x4e50000000000000L, 0x4a40000000000000L, 0x4bf0000000000000L,
		0x4920000000000000L, 0x4890000000000000L, 0xd800000000000000L,
		0xd9b0000000000000L, 0xdb60000000000000L, 0xdad0000000000000L,
		0xdec0000000000000L, 0xdf70000000000000L, 0xdda0000000000000L,
		0xdc10000000000000L, 0xd580000000000000L, 0xd430000000000000L,
		0xd6e0000000000000L, 0xd750000000000000L, 0xd340000000000000L,
		0xd2f0000000000000L, 0xd020000000000000L, 0xd190000000000000L,
		0xc300000000000000L, 0xc2b0000000000000L, 0xc060000000000000L,
		0xc1d0000000000000L, 0xc5c0000000000000L, 0xc470000000000000L,
		0xc6a0000000000000L, 0xc710000000000000L, 0xce80000000000000L,
		0xcf30000000000000L, 0xcde0000000000000L, 0xcc50000000000000L,
		0xc840000000000000L, 0xc9f0000000000000L, 0xcb20000000000000L,
		0xca90000000000000L, 0xee00000000000000L, 0xefb0000000000000L,
		0xed60000000000000L, 0xecd0000000000000L, 0xe8c0000000000000L,
		0xe970000000000000L, 0xeba0000000000000L, 0xea10000000000000L,
		0xe380000000000000L, 0xe230000000000000L, 0xe0e0000000000000L,
		0xe150000000000000L, 0xe540000000000000L, 0xe4f0000000000000L,
		0xe620000000000000L, 0xe790000000000000L, 0xf500000000000000L,
		0xf4b0000000000000L, 0xf660000000000000L, 0xf7d0000000000000L,
		0xf3c0000000000000L, 0xf270000000000000L, 0xf0a0000000000000L,
		0xf110000000000000L, 0xf880000000000000L, 0xf930000000000000L,
		0xfbe0000000000000L, 0xfa50000000000000L, 0xfe40000000000000L,
		0xfff0000000000000L, 0xfd20000000000000L, 0xfc90000000000000L,
		0xb400000000000000L, 0xb5b0000000000000L, 0xb760000000000000L,
		0xb6d0000000000000L, 0xb2c0000000000000L, 0xb370000000000000L,
		0xb1a0000000000000L, 0xb010000000000000L, 0xb980000000000000L,
		0xb830000000000000L, 0xbae0000000000000L, 0xbb50000000000000L,
		0xbf40000000000000L, 0xbef0000000000000L, 0xbc20000000000000L,
		0xbd90000000000000L, 0xaf00000000000000L, 0xaeb0000000000000L,
		0xac60000000000000L, 0xadd0000000000000L, 0xa9c0000000000000L,
		0xa870000000000000L, 0xaaa0000000000000L, 0xab10000000000000L,
		0xa280000000000000L, 0xa330000000000000L, 0xa1e0000000000000L,
		0xa050000000000000L, 0xa440000000000000L, 0xa5f0000000000000L,
		0xa720000000000000L, 0xa690000000000000L, 0x8200000000000000L,
		0x83b0000000000000L, 0x8160000000000000L, 0x80d0000000000000L,
		0x84c0000000000000L, 0x8570000000000000L, 0x87a0000000000000L,
		0x8610000000000000L, 0x8f80000000000000L, 0x8e30000000000000L,
		0x8ce0000000000000L, 0x8d50000000000000L, 0x8940000000000000L,
		0x88f0000000000000L, 0x8a20000000000000L, 0x8b90000000000000L,
		0x9900000000000000L, 0x98b0000000000000L, 0x9a60000000000000L,
		0x9bd0000000000000L, 0x9fc0000000000000L, 0x9e70000000000000L,
		0x9ca0000000000000L, 0x9d10000000000000L, 0x9480000000000000L,
		0x9530000000000000L, 0x97e0000000000000L, 0x9650000000000000L,
		0x9240000000000000L, 0x93f0000000000000L, 0x9120000000000000L,
		0x9090000000000000L
	};

	private UInt64 seed;
	private UInt64 hash;

	public Crc64()
	{
		seed = DefaultSeed;
		Initialize();
	}

	public Crc64(UInt64 seed)
	{
		this.seed = seed;
		Initialize();
	}

	public override void Initialize()
	{
		hash = seed;
	}

	protected override void HashCore(byte[] buffer, int start, int length)
	{
		hash = CalculateHash(hash, buffer, start, length);
	}

	protected override byte[] HashFinal()
	{
		byte[] hashBuffer = UInt64ToBigEndianBytes(hash);
		this.HashValue = hashBuffer;
		return hashBuffer;
	}

	public override int HashSize
	{
		get { return 64; }
	}

	public static UInt64 Compute(UInt64 seed, byte[] buffer)
	{
		return CalculateHash(seed, buffer, 0, buffer.Length);
	}

	private static UInt64 CalculateHash(UInt64 seed, byte[] buffer, int start, int size)
	{
		UInt64 crc = seed;

		for (int i = start; i < size; i++)
			unchecked {
				crc = (crc >> 8) ^ table[(buffer[i] ^ crc) & 0xff];
			}

		return crc;
	}

	private byte[] UInt64ToBigEndianBytes(UInt64 x)
	{
		return new byte[] {
			(byte)((x >> 56) & 0xff),
			(byte)((x >> 48) & 0xff),
			(byte)((x >> 40) & 0xff),
			(byte)((x >> 32) & 0xff),
			(byte)((x >> 24) & 0xff),
			(byte)((x >> 16) & 0xff),
			(byte)((x >> 8) & 0xff),
			(byte)(x & 0xff) };
	}
}

To use this or the CRC-32 class to compute the hash for a file simply:

Crc64 crc64 = new Crc64();
String hash = String.Empty;

using (FileStream fs = File.Open("c:\\myfile.txt", FileMode.Open))
	foreach (byte b in crc64.ComputeHash(fs)) hash += b.ToString("x2").ToLower();

Console.WriteLine("CRC-64 is {0}", hash);

Whilst writing this I considered if I should implement some more advanced hashing algorithms missing from .NET like RIPEMD320 only to stumble across The Legion of Bouncy Castles C# Cryptography APIs which also includes generating PKCS #12 files and a whole bunch of encryption algorithms (but nothing as weak as CRC-64 ;-)

[)amien

08
Aug

Calculating CRC-32 in C# and .NET

Just a few days ago I found myself needing to calculate a CRC-32 in .NET. With so many facilities available I was a little shocked that there was nothing built-in to do it so knocked up something myself.

Because unsigned ints aren't CLS compliant it won't play well with VB.Net and implementing the HashAlgorithm might lead people to believe it's suitable for signing - it isn't. CRC-32's are only any good for checksums along the lines of WinZIP, RAR etc. and certainly shouldn't come near a password and instead consider SHA-512 or similar.

As well as using it as a HashAlgorithm with block processing you can also access the static method Compute although there is an overhead with every call building the table with that. If neither option suits you needs cut 'n splice it to something that does.

using System;
using System.Security.Cryptography;

public class Crc32 : HashAlgorithm
{
	public const UInt32 DefaultPolynomial = 0xedb88320;
	public const UInt32 DefaultSeed = 0xffffffff;

	private UInt32 hash;
	private UInt32 seed;
	private UInt32[] table;

	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(UInt32 polynomial, UInt32 seed, byte[] buffer)
	{
		return CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
	}

	private static UInt32[] InitializeTable(UInt32 polynomial)
	{
		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[i] = entry;
		}
		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[i] ^ 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)
		};
	}
}

To compute the hash for a file simply:

Crc32 crc32 = new Crc32();
String hash = String.Empty;

using (FileStream fs = File.Open("c:\\myfile.txt", FileMode.Open))
	foreach (byte b in crc32.ComputeHash(fs)) hash += b.ToString("x2").ToLower();

Console.WriteLine("CRC-32 is {0}", hash);

[)amien




Feed subscription

Blog topics