using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Md5_Calculator
{
class Md5FileDigest
{
String path;
long FileLength;
// Inizializzo il processore MD5
Md5Base md5;
public Md5FileDigest(String FilePath)
{
path = FilePath;
processFile();
}
private uint[] ByteToWordBlock(byte[] block)
{
uint[] wordBlock
= new uint[16
];
for (int i = 0, k = 0; i < 64; i += 4, k++)
wordBlock[k] = (uint)block[i + 3] << 24 | (uint)block[i + 2] << 16 | (uint)block[i + 1] << 8 | (uint)block[i];
return wordBlock;
}
public void processFile()
{
FileStream file
= new FileStream
(path,
System.IO.
FileMode.
Open, FileAccess.
Read);
FileLength = file.Length * 8;
long TempFileLength = file.Length;
// Creo l'array di byte che contiene la lunghezza originale
byte[] FileLengthArray
= new byte[8
];
for (int i = 0, k = 0; i < 64; i += 8, k++)
FileLengthArray[k] = (byte) (FileLength >> i);
// Leggo blocchi di 64 byte alla volta (512 bit). Nell'ultimo blocco processo il padding
long fromRead = 0;
int NumberOfByteRead = 0;
byte[] block
= new byte[64
];
uint[] wordBlock
= new uint[16
];
while (TempFileLength >= 0)
{
Array.Clear(block, 0, 64);
NumberOfByteRead = file.Read(block, 0, 64);
fromRead += NumberOfByteRead;
TempFileLength -= 64;
// Creo il blocco di word
uint[] word = ByteToWordBlock(block);
// Se questo non è stato l'ultimo blocco
if (NumberOfByteRead == 64 && TempFileLength > 0)
md5.ProcessBlock(word);
if (TempFileLength <= 0)
break;
}
blockPadding(ref block, ref FileLengthArray, NumberOfByteRead);
file.Close();
}
private void blockPadding(ref byte[] block, ref byte[] FileLengthArray, int NumberOfByteLasted)
{
/*
* - Se il numero di byte dell'ultimo blocco lascia più di 5 byte
* disponibili processo solo quest'ultimo blocco: ( 1 byte 0x80 e 4 byte per la lunghezza del file iniziale)
* - Altrimenti, utilizzo un altro blocco di 64 byte;
*/
int k = 56;
if (NumberOfByteLasted <= 55)
{
block[NumberOfByteLasted] = 0x80;
foreach (byte val in FileLengthArray)
{
block[k] = val;
k++;
}
md5.ProcessBlock(ByteToWordBlock(block));
}
else
{
byte[] newBlock
= new byte[64
];
foreach(byte val in FileLengthArray)
{
newBlock[k] = val;
k++;
}
if (NumberOfByteLasted != 64)
block[NumberOfByteLasted] = 0x80;
else
newBlock[0] = 0x80;
// Finito il secondo caso di padding, processo i due blocchi;
md5.ProcessBlock(ByteToWordBlock(block));
md5.ProcessBlock(ByteToWordBlock(newBlock));
}
}
public String getDigest()
{
return md5.returnDigest();
}
}
}