Вычисление md5-хэша файла

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#1
Привет всем!

Надо понять, изменился файл или нет. Анализ даты и версии не подходит. нужен только хэш.
Хотелось бы что-то родное, на LS, т.к. скорость здесь критична.
HashPassword + VerifyPassword не подходят, т.к. они работают для слишком уж маленьких файлов.. мой файл в 55kb уже не проверяется - всегда возвращается True.
Или придётся всё-таки крутить MD5 и LS2J?

Поделитесь соображениями, плз! От кода тоже не стану отказываться :lovecodeby:
 

ToxaRat

Чёрный маг
Lotus team
06.11.2007
3 231
17
#2
бери виндусовый хешер, он кажется даже в ЕЦП использовался
 

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#4
Ясно.. - куча кода.. тогда лучше действительно Java.

Странности..
1.
stream.Open(sFilePathFull, "Binary")
берёт всего лишь 172 символа из моего бинарника

stream.Open(sFilePathFull, "ASCII")
берёт всё содержимое файла

2. При получении строки из файла используя ASCII при добавлении в файл в конец одного пробела размер изменяется, а хэш (код отсюда) нет. Есть подозрение, что хоть строка и вся, но для обсчёта берётся только какой-то кусок.

Одни, блин, сюрпризы...
 

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#6
lmike
Тоже как-то смутило, когда код копипастил, но потом забыл :lovecodeby:
Что посоветуешь туда втулить? ASCII не помогло, - возвращает тот же хэш.
 

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#8
Файл в данный момент обычная dll, но в принципе хотелось бы вычислять хэш любого файла.
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#9
с кодировкой вопрос открытый, бинарный следует использовать для бинарных файлов, а вот файлы в кодировке - это совсем другой момент...
когда открываем файл стримом (например в ЮТФ) - оно ещё не понимабельно нотуснёю (если пытаться вывести как стринг)
и надо конвертить, непример, через майм
др. словами - луче открывать файл в джава, а не передавать стринг открытый в LS из ёваного стрима

Добавлено: вот экзампел для файла http://www.javalobby.org/java/forums/t84420.html
 

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#10
Спасибо, буду разбираться!
В этом примере не увидел, где задаётся кодировка.. И хотелось бы, чтобы код автоматом определял, что оно, бинарник или нет; такое возможно? Или это оно и есть?
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#11
is.read(buffer) читает байты - там кодировка не нужна
 
13.03.2009
625
1
#12
От кода тоже не стану отказываться :lovecodeby:
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Java LIbrary: MD5Digest</div></div><div class="sp-body"><div class="sp-content">
Код:
package ru.turumbay.forum;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Digest {
public static String digest(String plaintext){
MessageDigest md5 = getMessageDigest();
md5.update(plaintext.getBytes());
return toHexString(md5.digest());
}

private static MessageDigest getMessageDigest(){
try {
return MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}

public static String digest(InputStream is) throws IOException {
MessageDigest md5 = getMessageDigest();
DigestInputStream din = new DigestInputStream(is, md5);
byte[] buffer = new byte[8192];
while ((din.read(buffer)) != -1);
din.close();
return toHexString(md5.digest());
}	

public static String digest(File file) throws IOException{
InputStream is = new FileInputStream(file);
try{
return digest(is);
}finally{
is.close();
}
}

public static String toHexString(byte bytes[]){
StringBuffer hexString = new StringBuffer();
for (int i=0;i<bytes.length;i++) {
hexString.append(Integer.toHexString((bytes[i] >>> 4) & 0x0F));
hexString.append(Integer.toHexString(0x0F & bytes[i]));
}
return hexString.toString();
}
}
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Обертка. LS Library: MD5Digest.LS</div></div><div class="sp-body"><div class="sp-content">
Код:
Option Public
Option Declare

Uselsx "*javacon"
Use "MD5Digest"

Class MD5Digest
Public Function getFileHash(fileName As String)
getFileHash = getMD5DigestClass().digest( getFileObj(fileName) )
End Function

Public Function getStringHash( st As String )
getStringHash = getMD5DigestClass().digest( st )
End Function

Private Function getMD5DigestClass As JavaClass
Dim jSession As New JAVASESSION
Set getMD5DigestClass = jSession.GetClass("ru/turumbay/forum/MD5Digest")
End Function

Private Function getFileObj(fileName As String) As JavaObject
Dim jSession As New JAVASESSION
Dim fileClass As JAVACLASS
Set fileClass = jSession.GetClass("java/io/File")
Set getFileObj = fileClass.CreateObject("(Ljava/lang/String;)V", fileName )
End Function
End Class
вызов:
Код:
Sub Initialize
Dim md5 As New MD5Digest()
Print md5.getFileHash("c:\killme.jpg")
End Sub
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#13
небольшой акцент - бинарное сопоставление файлов не всегда пригодно...
например надо сопоставить текст, а букивки разного регистра...
с т.з. текста - мало изменений (или можно на них забить), а вот бинарно - разная инфа
 

TIA

:-)
Lotus team
15.05.2009
790
3
#14
>Надо понять, изменился файл или нет.

Решение на чистом LS:
1. Поле с файлом копируем во временный док (физически скопируется лишь ярлык, так что быстро даже для больших файлов).
2. Ставим полю isSigned, если в исходном документе не было
3. Подписываем временный док
4. Удаляем все поля кроме $Signature
5. Пользователь меняет/не меняет файл
6. Поле с файлом копируем в тот же временный док
7. Ставим полю isSigned, если в исходном документе не было
8. Проверяем подпись. Если верна -- файл не менялся (doc.Siger<>""), иначе менялся
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#15
это если файл в домине...
а не "внешний" (типа с ресурса в тырнете или диска)
возможны и др. ограничения - типа файл требуется выложить на диск, где с ним будут работать др. приложения (не факт что писать)
 
13.03.2009
625
1
#16
...
8. Проверяем подпись. Если верна -- файл не менялся (doc.Siger<>""), иначе менялся
а дата модификации не участвует в подписи? выгружаю файл, открываю текстовым редактором, жму ctrl+s, цепляю назад. контент не изменился. подпись будет верна?
 

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#17
lmike, turumbay, TIA
Ребята, спасибо всем! Щедро поделился плюсиками ))
типа с ресурса в тырнете или диска
именно

И вопрос напоследок: всё-таки, почему при открытии
stream.Open(sFilePathFull, "Binary")
stream.ReadText() берёт всего лишь 172 символа из бинарника? Кстати Unicode взял 1010 ))

P.S. turumbay
В LS-классе везде вставил "Me." для дополнительного контроля при НЕиспользовании Option Declare.
Т.е. такой код:
Код:
getFileHash = getMD5DigestClass().digest( getFileObj(fileName) )
стал таким:
Код:
Me.getFileHash = Me.getMD5DigestClass().digest(Me.getFileObj(fileName))
а дата модификации не участвует в подписи?
Вообще атрибуты файла в подписи не участвуют, а как оно в Лотусе, это большой вопрос...)
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#18
ключевое здесь - stream.ReadText()
суваем длл, а читаем техт, кот. не воспринимает, адекватно, бинарные данные, и EOF тесктового файла может "отличаться" от физического (если файл бинарный)
просто часть данных - нечитабельные символы, часть командные (как их интетрипирует реализация от ИИБМ - ненаю)
 

VladSh

начинающий
Lotus team
11.12.2009
1 260
5
#19
Какой тогда нужен для правильного чтения бинарника? EOL_NONE (5)?
 

lmike

нет, пердело совершенство
Премиум
27.08.2008
6 567
263
#20
вот этого не подскажу, но главное нужен не ReadText, а Read