Bottleneck: easy obscurity "encryption" via xor

Oren Tirosh oren-py-l at hishome.net
Wed Jul 30 11:57:28 CEST 2003


On Wed, Jul 30, 2003 at 12:03:06AM +0200, Tino Lange wrote:
> Hi!
> 
> I identified a bottleneck in my programs.
> 
> I just want to "encrypt" data by easy xoring. Ok - that's no
> encryption at all -  I know. But it's hardly readable - and that's
> enough :-) Just some quick obscurity.
> 
> It turns out not to be quick at all. I really didn't expect this to be
> a bottleneck, but it takes quite some time.

If you want higher performance always try to use things that operate
on larger chunks. When you do things byte-by-byte you start to notice the
fact that Python is really an interpreter.

As noted by Bengt Richter xoring with a constant value can be done by 
str.translate.  It doesn't work for variable values, though.

This code does around 250kb/second on a Pentium 800. XORing is done 32
bits at a time. Conversion to and from character strings is done in even 
larger chunks using the array module instead of using ord() and chr().

    Oren


from __future__ import generators

import sha

def xor_stream_to_arrays(fin, seed, hashfunc=sha):
    """ fin is a file-like object. 
    yields arrays that may be written to a stream """
    from array import array 

    h = hashfunc.new(seed)
    maskchunk = h.digest()
    chunksize = len(maskchunk)

    while True:
        datachunk = fin.read(chunksize)
        if len(datachunk) < chunksize:
            break
        yield array('l', [x^y for (x,y) in zip(
            array('l', maskchunk), 
            array('l', datachunk))])

        h.update('x')
        maskchunk = h.digest()

    maskchunk = maskchunk[:len(datachunk)] # trim to length of remainder

    # do the rest by bytes:
    yield array('b', [x^y for (x,y) in zip(
        array('b', maskchunk), 
        array('b', datachunk))])

def xor_stream_to_stream(fin, fout, seed):
    """ fin, fout are file-like objects """
    for a in xor_stream_to_arrays(fin, seed):
        fout.write(buffer(a))

def xor_string_to_string(s, seed):
    """ gets a string, returns a string """
    from cStringIO import StringIO
    fin = StringIO(s)
    fout = StringIO()
    xor_stream_to_stream(fin, fout, seed)
    return fout.getvalue()






More information about the Python-list mailing list