xpra icon
Bug tracker and wiki

Ticket #866: integrity-hash-v2.patch

File integrity-hash-v2.patch, 4.9 KB (added by Antoine Martin, 5 years ago)

adds the ability to verify that the data we get before and after decompression matches what the server meant to send

  • xpra/client/window_backing_base.py

     
    55# later version. See the file COPYING for details.
    66
    77import os
     8import hashlib
    89from xpra.log import Logger
    910log = Logger("paint")
    1011deltalog = Logger("delta")
     
    2122from xpra.codecs.argb.argb import unpremultiply_argb, unpremultiply_argb_in_place   #@UnresolvedImport
    2223
    2324DELTA_BUCKETS = int(os.environ.get("XPRA_DELTA_BUCKETS", "5"))
     25INTEGRITY_HASH = os.environ.get("XPRA_INTEGRITY_HASH", "1")=="1"
    2426
    2527#ie:
    2628#CSC_OPTIONS = { "YUV420P" : {"RGBX" : [opencl.spec, swscale.spec], "BGRX" : ...} }
     
    163165        """
    164166        img_data = raw_data
    165167        if options:
     168            if INTEGRITY_HASH:
     169                l = options.get("z.len")
     170                if l:
     171                    assert l==len(raw_data), "compressed pixel data failed length integrity check: expected %i bytes but got %i" % (l, len(raw_data))
     172                md5 = options.get("z.md5")
     173                if md5:
     174                    h = hashlib.md5(raw_data)
     175                    hd = h.hexdigest()
     176                    assert md5==hd, "pixel data failed compressed md5 integrity check: expected %s but got %s" % (md5, hd)
     177                deltalog("passed compressed checks: len=%s, md5=%s (type=%s)", l, md5, type(raw_data))
    166178            #check for one of the compressors:
    167179            comp = [x for x in compression.ALL_COMPRESSORS if options.intget(x, 0)]
     180            deltalog("process delta: compressors(%s)=%s", options, comp)
    168181            if comp:
    169182                assert len(comp)==1, "more than one compressor specified: %s" % str(comp)
    170183                img_data = compression.decompress_by_name(raw_data, algo=comp[0])
     184                if INTEGRITY_HASH:
     185                    l = options.get("raw.len")
     186                    if l:
     187                        assert l==len(img_data), "decompressed pixel data failed length integrity check: expected %i bytes but got %i" % (l, len(img_data))
     188                    md5 = options.get("raw.md5")
     189                    if md5:
     190                        h = hashlib.md5(raw_data)
     191                        hd = h.hexdigest()
     192                        assert md5==hd, "pixel data failed decompressed md5 integrity check: expected %s but got %s (type=%s)" % (md5, hd, type(img_data))
     193                        deltalog("passed md5 raw check")
     194                    deltalog("passed decompressed checks: len=%s, md5=%s", l, md5)
    171195        if len(img_data)!=rowstride * height:
    172196            deltalog.error("invalid img data length: expected %s but got %s (%s: %s)", rowstride * height, len(img_data), type(img_data), str(img_data)[:256])
    173197            raise Exception("expected %s bytes for %sx%s with rowstride=%s but received %s (%s compressed)" %
  • xpra/server/picture_encode.py

     
    44# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
    55# later version. See the file COPYING for details.
    66
    7 import time
     7import time, os
    88from math import sqrt
     9import hashlib
    910
    1011from xpra.log import Logger
    11 log = Logger("window", "encoding")
     12log = Logger("window", "compress")
    1213
    1314from xpra.net import compression
    1415from xpra.codecs.argb.argb import bgra_to_rgb, bgra_to_rgba, argb_to_rgb, argb_to_rgba  #@UnresolvedImport
     
    2526PIL = get_codec("PIL")
    2627PIL_VERSION = get_codec_version("PIL")
    2728PIL_can_optimize = PIL_VERSION>="2.2"
     29INTEGRITY_HASH = os.environ.get("XPRA_INTEGRITY_HASH", "1")=="1"
    2830
     31
    2932#give warning message just once per key then ignore:
    3033encoding_warnings = set()
    3134def warn_encoding_once(key, message):
     
    112115    raw_data = memoryview_to_bytes(pixels)
    113116    level = 0
    114117    algo = "not"
     118    if INTEGRITY_HASH:
     119        h = hashlib.md5(raw_data)
     120        options["raw.md5"] = h.hexdigest()
     121        options["raw.len"] = len(raw_data)
     122        log("added len and hash of raw pixel data %s: %s / %s", type(raw_data), len(raw_data), h.hexdigest())
    115123    if len(pixels)>=256 and (rgb_zlib and compression.use_zlib) or (rgb_lz4 and compression.use_lz4) or (rgb_lzo and compression.use_lzo):
    116124        level = max(0, min(5, int(115-speed)/20))
    117125        if len(pixels)<1024:
     
    137145        else:
    138146            #add compressed marker:
    139147            options[algo] = level
     148            if INTEGRITY_HASH:
     149                h = hashlib.md5(cwrapper.data)
     150                options["z.md5"] = h.hexdigest()
     151                options["z.len"] = len(cwrapper)
     152                log("added len and hash of compressed data %s: %s / %s", type(cwrapper.data), len(cwrapper), h.hexdigest())
    140153    if level==0:
    141154        #can't pass a raw buffer to bencode / rencode:
    142155        cwrapper = compression.Compressed(coding, buffer_to_bytes(raw_data), True)