Temat: Obliczanie MD5 dla przesyłanych bloków danych
Twoja klasa jest zaimplementowana niepoprawnie. Nie powiem Ci gdzie jest błąd, sam popracuj. Poniżej test (mam nadzieję, że poprawny), który pomoże ci w badaniu problemu.
package md5;
import java.util.Arrays;
import java.util.Random;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Test;
public class MD5Test extends TestCase {
byte[] dataToSend;
MD5 md5;
int blockSize = 4096;
Random gen;
@Override
protected void setUp() throws Exception {
md5 = new MD5(blockSize);
gen = new Random();
dataToSend = new byte[65536];
gen.nextBytes(dataToSend);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
@Test
public void testCheck() {
int index = 0;
int nextSize = gen.nextInt(1000)+1000;
if (nextSize>blockSize) {
nextSize = blockSize;
}
byte[] curBytes = null;
do {
// twoje md5
curBytes = new byte[nextSize+gen.nextInt(200)];
System.arraycopy(dataToSend, index, curBytes, 0, nextSize);
String md5checksum = md5.check(curBytes, nextSize);
if (md5checksum!=null) {
// nasze md5
curBytes = new byte[blockSize];
System.arraycopy(dataToSend, (index/blockSize)*blockSize, curBytes, 0, curBytes.length);
String md5_expected = MD5.calcMD5(curBytes);
System.out.println(Arrays.toString(md5.prevBuffer));
System.out.println(Arrays.toString(curBytes));
Assert.assertEquals(md5.prevBuffer.length, curBytes.length);
Assert.assertTrue(Arrays.equals(md5.prevBuffer, curBytes));
Assert.assertEquals(md5_expected, md5checksum);
}
index+=nextSize;
nextSize = gen.nextInt(1000)+1000;
} while (index+nextSize<dataToSend.length);
}
}
Poniżej lekko zmodyfikowana wersja twojej klasy
package md5;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
byte[] buffer;
byte[] prevBuffer;
int blockSize,
curIndex,
count = 0,
rememberPos = 0;
public MD5(int size) {
this.buffer = new byte[size];
this.blockSize = size;
}
// readBytes to liczba która określa ilosc odebranych bajtów
// dataBlock.length jest zawsze takie samo, a liczba odebranych z
// socketa bajtów jest różna
// tzn: readBytes = input.read(fileBytes, 0, fileBytes.length);
public String check(byte[] dataBlock, int readBytes) {
this.curIndex += readBytes;
if (this.curIndex > this.blockSize) {
String md5 = calcMD5(this.buffer);
prevBuffer = buffer;
this.buffer = new byte[this.blockSize];
// po obliczeniu md5 curIndex rowna sie juz
// tylko dlugosci ostatnio odebranego bloku
this.curIndex = readBytes;
// zerowanie zmiennej ktora wskazuje od ktorego
// momentu zapisywac dane w buforze
this.rememberPos = 0;
appendToBuffer(dataBlock, readBytes);
return md5;
} else {
appendToBuffer(dataBlock, readBytes);
}
return null;
}
private void appendToBuffer(byte[] dataBlock, int readBytes) {
// metoda ktora dodaje bloki danych do bufora
// zmienna rememberPos na poczatku rowna sie zero
// a potem dlugosci wczytanego bloku.
// dzieki temu dane w buforze nie sa nadpisywane
System.arraycopy(dataBlock, 0, this.buffer, this.rememberPos, readBytes);
this.rememberPos = readBytes;
}
public static String calcMD5(byte[] blokDanych) {
// obliczanie skrotu MD5
String skrotMD5 = null;
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
if (blokDanych.length > 0){
digest.update(blokDanych, 0, blokDanych.length); }
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
skrotMD5 = bigInt.toString(16);
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
return skrotMD5;
}
}
Dariusz Wawer edytował(a) ten post dnia 30.03.10 o godzinie 10:19