Хэш-алгоритм для динамического роста /потоковой передачи данных?

Есть ли какой-нибудь алгоритм, который вы можете продолжить хэшировать из известного хеш-дайджеста? Например, клиент загружает кусок файла на сервер A, я могу получить сумму md5 загруженного контента, затем клиент загрузит оставшаяся часть файлового блока на ServerB, могу ли я передать состояние внутренних компонентов md5 на ServerB и завершить хеширование?

Был классный хак с черной магией основанный на md5, который я нашел несколько лет назад на comp.lang.python, но он использует ctypes для конкретной версии md5.so или _md5.dll, поэтому это не совсем переносимый код для другого интерпретатора Python версии или другие языки программирования, кроме модуля md5 в стандартной библиотеке python, начиная с версии 2.5, поэтому мне нужно найти более общее решение.

Более того, можно ли состояние хеширования сохранить в самом шестнадцатеричном дайджесте? (Таким образом, я могу продолжить хэширование потока данных с помощью существующего хэш-дайджеста, а не грязного внутреннего хака.

Любая идея приветствуется. Заранее спасибо:)

7 голосов | спросил est 3 Mayam11 2011, 10:22:08

3 ответа


0

Не из известного дайджеста, а из известного состояния. Вы можете использовать чистую реализацию Python MD5 и сохранить ее состояние. Вот пример использования _md5.py из PyPy :

import _md5

def md5_getstate(md):
    return (md.A, md.B, md.C, md.D, md.count + [], md.input + [], md.length)

def md5_continue(state):
    md = _md5.new()
    (md.A, md.B, md.C, md.D, md.count, md.input, md.length) = state
    return md

m1 = _md5.new()
m1.update("hello, ")
state = md5_getstate(m1)
m2 = md5_continue(state)
m2.update("world!")
print m2.hexdigest()

m = _md5.new()
m.update("hello, world!")
print m.hexdigest()

Как отметил e.dan, вы также можете использовать практически любой алгоритм проверки контрольных сумм (CRC, Adler, Fletcher), но он плохо защищает вас от преднамеренного изменения данных, только от случайных ошибок.

РЕДАКТИРОВАТЬ: конечно, вы также можете повторно реализовать метод сериализации, используя ctypes из потока, на который вы ссылались, более переносимым способом (без магических констант). Я считаю, что это не должно зависеть от версии /архитектуры (протестировано на python 2.4-2.7, i386 и x86_64):

# based on idea from http://groups.google.com/group/comp.lang.python/msg/b1c5bb87a3ff5e34

try:
    import _md5 as md5
except ImportError:
    # python 2.4
    import md5
import ctypes

def md5_getstate(md):
    if type(md) is not md5.MD5Type:
        raise TypeError, 'not an MD5Type instance'
    return ctypes.string_at(id(md) + object.__basicsize__,
                            md5.MD5Type.__basicsize__ - object.__basicsize__)

def md5_continue(state):
    md = md5.new()
    assert len(state) == md5.MD5Type.__basicsize__ - object.__basicsize__, \
           'invalid state'    
    ctypes.memmove(id(md) + object.__basicsize__,
                   ctypes.c_char_p(state),
                   len(state))
    return md

m1 = md5.new()
m1.update("hello, ")
state = md5_getstate(m1)
m2 = md5_continue(state)
m2.update("world!")
print m2.hexdigest()

m = md5.new()
m.update("hello, world!")
print m.hexdigest()

Он не совместим с Python 3, так как у него нет модуля _md5 /md5.

К сожалению, реализация hashlib openssl_md5 не подходит для таких хаков, поскольку OpenSSL EVP API не предоставляет никаких вызовов /методов для надежной сериализации объектов EVP_MD_CTX.

ответил abbot 3 Mayam11 2011, 11:14:32
0

Это теоретически возможно (пока md5 должен содержать все состояния , которые вам нужно продолжить), но похоже, что обычные API не предоставляют то, что вам нужно , Если вместо этого вы можете использовать CRC, это, вероятно, будет намного проще, поскольку они чаще используются для «потоковых» случаев, которые вам нужны. Смотрите здесь:

binascii.crc32 (data [, crc])

crc32() принимает необязательный crc ввод, который является контрольной суммой для продолжения.

Надеюсь, это поможет.

ответил e.dan 3 Mayam11 2011, 10:43:00
0

Я тоже столкнулся с этой проблемой и не нашел существующего решения, поэтому я написал библиотеку, которая использует ctypes для деконструкции структуры данных OpenSSL, содержащей состояние хэша: https://github.com/kislyuk/rehash . Пример:

import pickle, rehash
hasher = rehash.sha256(b"foo")
state = pickle.dumps(hasher)

hasher2 = pickle.loads(state)
hasher2.update(b"bar")

assert hasher2.hexdigest() == rehash.sha256(b"foobar").hexdigest()
ответил weaver 12 J000000Wednesday17 2017, 21:37:14

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132