From 98d6b4f2493d2fd54a3088c058d5c37958e40cf2 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Mon, 2 Feb 2015 14:33:53 +0000 Subject: [PATCH] Added Fletcher16 and Fletcher32 algorithms --- SharpHash/Checksums/FletcherContext.cs | 443 +++++++++++++++++++++++++ SharpHash/SharpHash.csproj | 1 + 2 files changed, 444 insertions(+) create mode 100644 SharpHash/Checksums/FletcherContext.cs diff --git a/SharpHash/Checksums/FletcherContext.cs b/SharpHash/Checksums/FletcherContext.cs new file mode 100644 index 0000000..17094b1 --- /dev/null +++ b/SharpHash/Checksums/FletcherContext.cs @@ -0,0 +1,443 @@ +// +// FletcherContext.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2015 © Claunia.com +// +// 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 3 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, see . +using System; +using System.Text; +using System.IO; + +namespace SharpHash.Checksums +{ + public class Fletcher32Context + { + private UInt16 sum1, sum2; + private byte oddValue; + private bool inodd; + + /// + /// Initializes the Fletcher32 sums + /// + public void Init() + { + sum1 = 0xFFFF; + sum2 = 0xFFFF; + oddValue = 0; + inodd = false; + } + + /// + /// Updates the hash with data. + /// + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + UInt16 block; + if (!inodd) + { + // Odd size + if (len % 2 != 0) + { + oddValue = data[len - 1]; + inodd = true; + + for (int i = 0; i < len - 1; i += 2) + { + block = BigEndianBitConverter.ToUInt16(data, i); + sum1 = (UInt16)((sum1 + block) % 0xFFFF); + sum2 = (UInt16)((sum2 + sum1) % 0xFFFF); + } + } + else + { + inodd = false; + for (int i = 0; i < len; i += 2) + { + block = BigEndianBitConverter.ToUInt16(data, i); + sum1 = (UInt16)((sum1 + block) % 0xFFFF); + sum2 = (UInt16)((sum2 + sum1) % 0xFFFF); + } + } + } + // Carrying odd + else + { + byte[] oddData = new byte[2]; + oddData[0] = oddValue; + oddData[1] = data[0]; + + block = BigEndianBitConverter.ToUInt16(oddData, 0); + sum1 = (UInt16)((sum1 + block) % 0xFFFF); + sum2 = (UInt16)((sum2 + sum1) % 0xFFFF); + + // Even size, carrying odd + if (len % 2 == 0) + { + oddValue = data[len - 1]; + inodd = true; + + for (int i = 1; i < len - 1; i += 2) + { + block = BigEndianBitConverter.ToUInt16(data, i); + sum1 = (UInt16)((sum1 + block) % 0xFFFF); + sum2 = (UInt16)((sum2 + sum1) % 0xFFFF); + } + } + else + { + inodd = false; + for (int i = 1; i < len; i += 2) + { + block = BigEndianBitConverter.ToUInt16(data, i); + sum1 = (UInt16)((sum1 + block) % 0xFFFF); + sum2 = (UInt16)((sum2 + sum1) % 0xFFFF); + } + } + } + } + + /// + /// Updates the hash with data. + /// + /// Data buffer. + public void Update(byte[] data) + { + Update(data, (uint)data.Length); + } + + /// + /// Returns a byte array of the hash value. + /// + public byte[] Final() + { + UInt32 finalSum = (UInt32)(sum1 + (sum2 << 16)); + return BigEndianBitConverter.GetBytes(finalSum); + } + + /// + /// Returns a hexadecimal representation of the hash value. + /// + public string End() + { + UInt32 finalSum = (UInt32)(sum1 + (sum2 << 16)); + StringBuilder fletcherOutput = new StringBuilder(); + + for (int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) + { + fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); + } + + return fletcherOutput.ToString(); + } + + /// + /// Gets the hash of a file + /// + /// File path. + public static byte[] File(string filename) + { + byte[] hash; + File(filename, out hash); + return hash; + } + + /// + /// Gets the hash of a file in hexadecimal and as a byte array. + /// + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + FileStream fileStream = new FileStream(filename, FileMode.Open); + UInt16 localSum1, localSum2, block; + UInt32 finalSum; + byte[] blockBytes; + + localSum1 = 0xFFFF; + localSum2 = 0xFFFF; + block = 0; + + if (fileStream.Length % 2 == 0) + { + for (int i = 0; i < fileStream.Length; i+=2) + { + blockBytes = new byte[2]; + fileStream.Read(blockBytes, i, 2); + block = BigEndianBitConverter.ToUInt16(blockBytes, 0); + localSum1 = (UInt16)((localSum1 + block) % 0xFFFF); + localSum2 = (UInt16)((localSum2 + localSum1) % 0xFFFF); + } + } + else + { + for (int i = 0; i < fileStream.Length-1; i+=2) + { + blockBytes = new byte[2]; + fileStream.Read(blockBytes, i, 2); + block = BigEndianBitConverter.ToUInt16(blockBytes, 0); + localSum1 = (UInt16)((localSum1 + block) % 0xFFFF); + localSum2 = (UInt16)((localSum2 + localSum1) % 0xFFFF); + } + + byte[] oddData = new byte[2]; + blockBytes = new byte[1]; + fileStream.Read(blockBytes, (int)(fileStream.Length-2), 1); + oddData[0] = blockBytes[0]; + oddData[1] = 0; + + block = BigEndianBitConverter.ToUInt16(oddData, 0); + localSum1 = (UInt16)((localSum1 + block) % 0xFFFF); + localSum2 = (UInt16)((localSum2 + localSum1) % 0xFFFF); + } + + finalSum = (UInt32)(localSum1 + (localSum2 << 16)); + + hash = BitConverter.GetBytes(finalSum); + + StringBuilder fletcherOutput = new StringBuilder(); + + for (int i = 0; i < hash.Length; i++) + { + fletcherOutput.Append(hash[i].ToString("x2")); + } + + return fletcherOutput.ToString(); + } + + /// + /// Gets the hash of the specified data buffer. + /// + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public string Data(byte[] data, uint len, out byte[] hash) + { + UInt16 localSum1, localSum2, block; + UInt32 finalSum; + + localSum1 = 0xFFFF; + localSum2 = 0xFFFF; + block = 0; + + if (len % 2 == 0) + { + for (int i = 0; i < len; i+=2) + { + block = BigEndianBitConverter.ToUInt16(data, i); + localSum1 = (UInt16)((localSum1 + block) % 0xFFFF); + localSum2 = (UInt16)((localSum2 + localSum1) % 0xFFFF); + } + } + else + { + for (int i = 0; i < len-1; i+=2) + { + block = BigEndianBitConverter.ToUInt16(data, i); + localSum1 = (UInt16)((localSum1 + block) % 0xFFFF); + localSum2 = (UInt16)((localSum2 + localSum1) % 0xFFFF); + } + + byte[] oddData = new byte[2]; + oddData[0] = data[len - 1]; + oddData[1] = 0; + + block = BigEndianBitConverter.ToUInt16(oddData, 0); + localSum1 = (UInt16)((localSum1 + block) % 0xFFFF); + localSum2 = (UInt16)((localSum2 + localSum1) % 0xFFFF); + } + + finalSum = (UInt32)(localSum1 + (localSum2 << 16)); + + hash = BitConverter.GetBytes(finalSum); + + StringBuilder fletcherOutput = new StringBuilder(); + + for (int i = 0; i < hash.Length; i++) + { + fletcherOutput.Append(hash[i].ToString("x2")); + } + + return fletcherOutput.ToString(); + } + + /// + /// Gets the hash of the specified data buffer. + /// + /// Data buffer. + /// Byte array of the hash value. + public string Data(byte[] data, out byte[] hash) + { + return Data(data, (uint)data.Length, out hash); + } + } + + public class Fletcher16Context + { + private byte sum1, sum2; + + /// + /// Initializes the Fletcher16 sums + /// + public void Init() + { + sum1 = 0xFF; + sum2 = 0xFF; + } + + /// + /// Updates the hash with data. + /// + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for (int i = 0; i < len; i++) + { + sum1 = (byte)((sum1 + data[i]) % 0xFF); + sum2 = (byte)((sum2 + sum1) % 0xFF); + } + } + + /// + /// Updates the hash with data. + /// + /// Data buffer. + public void Update(byte[] data) + { + Update(data, (uint)data.Length); + } + + /// + /// Returns a byte array of the hash value. + /// + public byte[] Final() + { + UInt16 finalSum = (UInt16)(sum1 + (sum2 << 8)); + return BigEndianBitConverter.GetBytes(finalSum); + } + + /// + /// Returns a hexadecimal representation of the hash value. + /// + public string End() + { + UInt16 finalSum = (UInt16)(sum1 + (sum2 << 8)); + StringBuilder fletcherOutput = new StringBuilder(); + + for (int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) + { + fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); + } + + return fletcherOutput.ToString(); + } + + /// + /// Gets the hash of a file + /// + /// File path. + public static byte[] File(string filename) + { + byte[] hash; + File(filename, out hash); + return hash; + } + + /// + /// Gets the hash of a file in hexadecimal and as a byte array. + /// + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + FileStream fileStream = new FileStream(filename, FileMode.Open); + byte localSum1, localSum2, block; + UInt16 finalSum; + + localSum1 = 0xFF; + localSum2 = 0xFF; + block = 0; + + for (int i = 0; i < fileStream.Length; i+=2) + { + block = (byte)fileStream.ReadByte(); + localSum1 = (byte)((localSum1 + block) % 0xFF); + localSum2 = (byte)((localSum2 + localSum1) % 0xFF); + } + + finalSum = (UInt16)(localSum1 + (localSum2 << 8)); + + hash = BitConverter.GetBytes(finalSum); + + StringBuilder fletcherOutput = new StringBuilder(); + + for (int i = 0; i < hash.Length; i++) + { + fletcherOutput.Append(hash[i].ToString("x2")); + } + + return fletcherOutput.ToString(); + } + + /// + /// Gets the hash of the specified data buffer. + /// + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public string Data(byte[] data, uint len, out byte[] hash) + { + byte localSum1, localSum2; + UInt16 finalSum; + + localSum1 = 0xFF; + localSum2 = 0xFF; + + for (int i = 0; i < len; i++) + { + localSum1 = (byte)((localSum1 + data[i]) % 0xFF); + localSum2 = (byte)((localSum2 + localSum1) % 0xFF); + } + + finalSum = (UInt16)(localSum1 + (localSum2 << 8)); + + hash = BitConverter.GetBytes(finalSum); + + StringBuilder fletcherOutput = new StringBuilder(); + + for (int i = 0; i < hash.Length; i++) + { + fletcherOutput.Append(hash[i].ToString("x2")); + } + + return fletcherOutput.ToString(); + } + + /// + /// Gets the hash of the specified data buffer. + /// + /// Data buffer. + /// Byte array of the hash value. + public string Data(byte[] data, out byte[] hash) + { + return Data(data, (uint)data.Length, out hash); + } + } +} + diff --git a/SharpHash/SharpHash.csproj b/SharpHash/SharpHash.csproj index cda74d1..08b58ea 100644 --- a/SharpHash/SharpHash.csproj +++ b/SharpHash/SharpHash.csproj @@ -49,6 +49,7 @@ +