Назад | Перейти на главную страницу

Хэши вложений Couchdb не соответствуют содержимому вложений

Выполняя некоторый аудит базы данных, я обнаружил, что содержимое некоторых вложений не соответствует хешам, указанным в документе _attachments карта.

Я проверил это, загрузив документ и вычислив его хэш. Сравнение с couchdb показало, что они не совпадают. Затем я заметил, что несовпадающие вложения были настроены для сжатия couchdb. Похоже, что мой идентификатор дивана настроен на использование мгновенного сжатия:

foobox# grep -E 'file_compression|compressible_types' /etc/couchdb/{default,local}.ini 
/etc/couchdb/default.ini:file_compression = snappy
/etc/couchdb/default.ini:compressible_types = text/*, application/javascript, application/json, application/xml

Однако, когда я пытаюсь сжать содержимое вложения, используя резкий, и вычислить хэш сжатых данных, он по-прежнему не соответствует хешу couchdb. В моем примере ниже document-25977 несжатый (введите application / pdf), а несжатый хэш соответствует предоставленному couchdb. 2-й, document-78608, является сжимаемым типом (текст / простой), и хеши не совпадают:

foobox$ python hashcompare.py
document-25977
couch len:  142918
couch hash:  028540dd92e1982bcb65c29d32e9617e (md5)
local uncompressed len:  142918
local uncompressed hash:  028540dd92e1982bcb65c29d32e9617e
local compressed len:  132333
local compressed hash:  3157583223dc1a53e1a3386d6abc312d

document-78608
couch len:  2180
couch hash:  e613ab6d7f884b835142979489170499 (md5)
local uncompressed len:  2180
local uncompressed hash:  0ab2516c820f5d7afb208e3be7b924dd
local compressed len:  1382
local compressed hash:  d9e79232662f57e6af262fc9f867eaf2

Это сценарий, который я использовал для сравнения:

import couchdb
import snappy
import md5
import base64

server = couchdb.Server('http://localhost:9999')

db = server['program1']

for doc_id in ['document-25977', 'document-78608']:
    print doc_id
    doc = db[doc_id]
    att_stub = doc['_attachments'][doc_id]
    hash_type, tmpdigest = att_stub['digest'].split('-', 1)
    att = db.get_attachment(doc, doc_id)
    data = att.read()
    # CouchDB is using snappy compression
    compressed_data = snappy.compress(data)

    print 'couch len: ', att_stub['length']
    print 'couch hash: ', base64.b64decode(tmpdigest).encode('hex'), '(%s)' % hash_type
    print 'local uncompressed len: ', len(data)
    print 'local uncompressed hash: ', md5.md5(data).digest().encode('hex')
    print 'local compressed len: ', len(compressed_data)
    print 'local compressed hash: ', md5.md5(compressed_data).digest().encode('hex')
    print

Я убедился, что документы не повреждены при получении. Так что мне не хватает? Я недостаточно разбираюсь в Erlang, чтобы читать исходники couchdb и понимать, что происходит. Почему в документах должен быть дайджест, который не соответствует его содержимому в сжатом виде или иным образом?

Не уверен, что вы разобрались с этим, но я пошел по тому же пути. Посмотрев немного на источник, выяснилось, что расчеты дайджеста происходят до сжатия, поэтому я не верю, что сжатие будет иметь отношение к значению дайджеста.

Мне удалось воспроизвести дайджест md5, созданный CouchDB для вложений, используя следующее в узле:

var crypto = require('crypto');

var attachmentData = "base64-encoded-data"

var buf = new Buffer(attachmentData, 'base64')
  , md5 = crypto.createHash('md5').update(buf).digest('base64');

Надеюсь, это поможет вам или кому-то, кто ищет подробности в будущем.

CouchDB действительно вычисляет хеш после сжатия для сжимаемых файлов.

Но вложения сжимаются с помощью zlib, и мне не удалось сопоставить то, что они делают, поэтому единственное решение, кажется, получить их дайджест после загрузки и сохранить его где-нибудь.