/*
* Copyright (C) 2007 Eskil Bylund
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace DCSharp.Security.Cryptography{
public class TigerUnmanaged : Tiger
{
private enum Algorithm
{
Tiger = 6
}
private IntPtr handle;
private static object gcryptLock;
static TigerUnmanaged()
{
gcryptLock = new object();
}
public TigerUnmanaged() : base()
{
handle = IntPtr.Zero;
Initialize();
}
#region Properties
public override bool CanTransformMultipleBlocks
{
get
{
return true;
}
}
#endregion
#region Methods
[DllImport("gcrypt")]
private static extern IntPtr gcry_md_open(out IntPtr handle,
Algorithm algo, uint flags);
public override void Initialize()
{
CleanUp();
lock (gcryptLock)
{
IntPtr err = gcry_md_open(out handle, Algorithm.Tiger, 0);
if (err != IntPtr.Zero)
{
throw new ApplicationException();
}
}
}
protected override void Dispose(bool disposing)
{
CleanUp();
base.Dispose(disposing);
}
[DllImport("gcrypt")]
private static unsafe extern void gcry_md_write(IntPtr handle, byte* buffer,
int length);
protected override unsafe void HashCore(byte[] array, int offset, int count)
{
if (count <= 0)
{
return;
}
fixed (byte* buffer = array)
{
lock (gcryptLock)
{
gcry_md_write(handle, buffer + offset, count);
}
}
}
[DllImport("gcrypt")]
private static extern IntPtr gcry_md_read(IntPtr handle,
Algorithm algo);
[DllImport("gcrypt")]
private static extern void gcry_md_close(IntPtr handle);
protected override byte[] HashFinal()
{
IntPtr result;
lock (gcryptLock)
{
result = gcry_md_read(handle, Algorithm.Tiger);
}
byte[] digest = new byte[24];
Marshal.Copy(result, digest, 0, digest.Length);
if (BitConverter.IsLittleEndian)
{
FixByteOrder(ref digest);
}
CleanUp();
return digest;
}
private void FixByteOrder(ref byte[] digest)
{
// Byte-reverse each 8-byte chunk. Not using Array.Reverse for
// performance reasons.
byte temp;
for (int offset = 0; offset < digest.Length; offset += 8)
{
for (int i = 0; i < 4; i++)
{
temp = digest[offset + i];
digest[offset + i] = digest[offset + 7 - i];
digest[offset + 7 - i] = temp;
}
}
}
private void CleanUp()
{
if (handle != IntPtr.Zero)
{
lock (gcryptLock)
{
gcry_md_close(handle);
}
handle = IntPtr.Zero;
}
}
#endregion
}
}
|