Calculating Elf-32 in C# and .NET

GitHub has the latest version of Elf32

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

4 responses to Calculating Elf-32 in C# and .NET

  1. Avatar for

    Information is only used to show your comment. See my Privacy Policy.

  2. Avatar for Damien Guard

    All hash functions can return the same hash code for a different input sets. If they didn't they would instead be very effective compression algorithms.

  3. Avatar for QuangCanh

    hi Damien,

    Can this algorithm duplicate?

    private static uint GetELF(string str)
    {
           int i;
           uint x;
           uint result = 10;
           byte[] b = ASCIIEncoding.Unicode.GetBytes(str);
           for (i = 0; i < b.Length; i++)
           {
                  unchecked
                  {
                         result = (result <> 24);
                         result &amp;= ~x;
                         }
                  }
           return result;
    }
    

    hash code of "mj9d" and "oj9f" is the same.

    regards, Canh

  4. Avatar for bitRAKE
    if (work != 0) hash ^= (work >> 24);
    

    Makes me wonder if it costs more to avoid this than to just do it anyway when work==0? As it has no effect on hash when work==0, and I'm almost certain it'll always be slower to branch.