Skip to main content

xxtea is a simple block cipher

Project description

XXTEA implemented as a Python extension module, licensed under 2-clause BSD.

The XXTEA algorithm takes a 128-bit key and operates on an array of 32-bit integers (at least 2 integers), but it doesn’t define the conversions between bytes and array. Due to this reason, many XXTEA implementations out there are not compatible with each other.

In this implementation, the conversions between bytes and array are taken care of by longs2bytes and bytes2longs. PKCS#7 padding is also used to make sure that the input bytes are padded to multiple of 4-byte (the size of a 32-bit integer) and at least 8-byte long (the size of two 32-bit integer, which is required by the XXTEA algorithm). As a result of these measures, you can encrypt not only texts, but also any binary bytes of any length.

Installation

$ pip install xxtea -U

Usage

This module provides four functions: encrypt(), decrypt(), encrypt_hex(), and decrypt_hex().

Python 2:

>>> import os
>>> import xxtea
>>>
>>> key = os.urandom(16)  # Key must be a 16-byte string.
>>> s = "xxtea is good"
>>>
>>> enc = xxtea.encrypt(s, key)
>>> dec = xxtea.decrypt(enc, key)
>>> s == dec
True
>>>
>>> hexenc = xxtea.encrypt_hex(s, key)
>>> hexenc
'd1d8e82461dd5828397c32ad265ee225'
>>> s == xxtea.decrypt_hex(hexenc, key)
True
>>>
>>> enc.encode('hex') == hexenc
True

Python 3:

>>> import os
>>> import xxtea
>>> import binascii
>>>
>>> key = os.urandom(16)  # Key must be a 16-byte string.
>>> s = b"xxtea is good"
>>>
>>> enc = xxtea.encrypt(s, key)
>>> dec = xxtea.decrypt(enc, key)
>>> s == dec
True
>>>
>>> hexenc = xxtea.encrypt_hex(s, key)
>>> hexenc
b'7ad85672d770fb5cf636c49d57e732ae'
>>> s == xxtea.decrypt_hex(hexenc, key)
True
>>>
>>> binascii.hexlify(enc) == hexenc
True

encrypt_hex() and decrypt_hex() operate on ciphertext in a hexadecimal representation. They are exactly equivalent to:

Python 2:

>>> hexenc = xxtea.encrypt(s, key).encode('hex')
>>> s == xxtea.decrypt(hexenc.decode('hex'), key)
True

Python 3:

>>> hexenc = binascii.hexlify(xxtea.encrypt(s, key))
>>> s == xxtea.decrypt(binascii.unhexlify(hexenc), key)
True

Padding

Padding is enabled by default, in this case you can encode any bytes of any length.

>>> xxtea.encrypt_hex('', key)
'd63256eb59134f1f'
>>> xxtea.decrypt_hex(_, key)
''
>>> xxtea.encrypt_hex(' ', key)
'97009bd24074a7a5'
>>> xxtea.decrypt_hex(_, key)
' '

You can disable padding by setting padding parameter to False. In this case data will not be padded, so data length must be a multiple of 4 bytes and must not be less than 8 bytes. Otherwise ValueError will be raised.

>>> xxtea.encrypt_hex('', key, padding=False)
ValueError: Data length must be a multiple of 4 bytes and must not be less than 8 bytes
>>> xxtea.encrypt_hex('xxtea is good', key, padding=False)
ValueError: Data length must be a multiple of 4 bytes and must not be less than 8 bytes
>>> xxtea.encrypt_hex('12345678', key, padding=False)
'64f4e969ba90d386'
>>> xxtea.decrypt_hex(_, key, padding=False)
'12345678'

Rounds

By default xxtea manipulates the input data for 6 + 52 / n rounds, where n denotes how many 32-bit integers data can fit in. We can specify it manually by setting rounds parameter.

Python2:

>>> import xxtea
>>> import string
>>> data = string.digits
>>> key = string.ascii_letters[:16]
>>> xxtea.encrypt_hex(data, key)
'5b80b08a5d1923e4cd992dd5'
>>> xxtea.encrypt_hex(data, key, rounds=23)
'5b80b08a5d1923e4cd992dd5'
>>> xxtea.encrypt_hex(data, key, rounds=1024)
'1577bbf28c43ced93bd50720'

Python3:

>>> import xxtea
>>> import string
>>> data = string.digits
>>> key = string.ascii_letters[:16]
>>> xxtea.encrypt_hex(data, key)
b'5b80b08a5d1923e4cd992dd5'
>>> xxtea.encrypt_hex(data, key, rounds=23)
b'5b80b08a5d1923e4cd992dd5'
>>> xxtea.encrypt_hex(data, key, rounds=1024)
b'1577bbf28c43ced93bd50720'

Catching Exceptions

It is possible to throw a ValueError or a TypeError during calling decrypt() and decrypt_hex(). Better to catch them, or your program will exit.

>>> from __future__ import print_function
>>> import xxtea
>>>
>>> def try_catch(func, *args, **kwargs):
...     try:
...         func(*args, **kwargs)
...     except Exception as e:
...         print(e.__class__.__name__, ':', e)
...
...
...
>>> try_catch(xxtea.decrypt, '', key='')
ValueError : Need a 16-byte key.
>>> try_catch(xxtea.decrypt, '', key=' '*16)
ValueError : Invalid data, data length is not a multiple of 4, or less than 8.
>>> try_catch(xxtea.decrypt, ' '*8, key=' '*16)
ValueError : Invalid data, illegal PKCS#7 padding. Could be using a wrong key.
>>> try_catch(xxtea.decrypt_hex, ' '*8, key=' '*16)
TypeError : Non-hexadecimal digit found
>>> try_catch(xxtea.decrypt_hex, 'abc', key=' '*16)
TypeError : Odd-length string
>>> try_catch(xxtea.decrypt_hex, 'abcd', key=' '*16)
ValueError : Invalid data, data length is not a multiple of 4, or less than 8.

CHANGELOG

v1.3.0 2018/10/24

  • Fixed a memory leak in decrypt_hex

  • Deployed wheels automatically

v1.2.0 2018/05/09

  • Added an option to disable padding

v1.1.0 2018/02/03

  • Test on appveyor

  • Use unsigned int instead of uint32_t

v1.0.2 2015/12/15

  • Check padding char

v1.0.1 2015/12/10

  • Check upper bound in longs2bytes

v1.0 2015/12/10

  • Fixed: unbound write

  • Changed: raises ValueError instead of TypeError

v0.2.1 2015/03/07

  • Fixed: memory leaks

  • Use binascii module to encode/decode hex, instead of writing our own C functions.

v0.2.0 2015/02/28

This release is _NOT_ compatible with previous versions.

  • [NEW] Added PKCS#7 Padding.

  • [NEW] Added encrypt_hex() and decrypt_hex().

  • [CHANGE] Removed xxtea.RESULT_TYPE_HEX, xxtea.RESULT_TYPE_RAW, and xxtea.RESULT_TYPE_DEFAULT. encrypt() and decrypt() now only accept two parameters: input data and key.

v0.1.5 2011/01/23

  • fix msvc compiler error

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xxtea-1.3.0.tar.gz (8.1 kB view hashes)

Uploaded Source

Built Distributions

xxtea-1.3.0-cp38-cp38-manylinux2010_x86_64.whl (27.7 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64

xxtea-1.3.0-cp38-cp38-manylinux2010_i686.whl (23.7 kB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.12+ i686

xxtea-1.3.0-cp38-cp38-manylinux1_x86_64.whl (27.7 kB view hashes)

Uploaded CPython 3.8

xxtea-1.3.0-cp38-cp38-manylinux1_i686.whl (23.7 kB view hashes)

Uploaded CPython 3.8

xxtea-1.3.0-cp37-cp37m-win_amd64.whl (11.5 kB view hashes)

Uploaded CPython 3.7m Windows x86-64

xxtea-1.3.0-cp37-cp37m-win32.whl (10.3 kB view hashes)

Uploaded CPython 3.7m Windows x86

xxtea-1.3.0-cp37-cp37m-manylinux2010_x86_64.whl (28.3 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64

xxtea-1.3.0-cp37-cp37m-manylinux2010_i686.whl (24.2 kB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.12+ i686

xxtea-1.3.0-cp37-cp37m-manylinux1_x86_64.whl (20.9 kB view hashes)

Uploaded CPython 3.7m

xxtea-1.3.0-cp37-cp37m-manylinux1_i686.whl (20.1 kB view hashes)

Uploaded CPython 3.7m

xxtea-1.3.0-cp37-cp37m-macosx_10_6_intel.whl (12.0 kB view hashes)

Uploaded CPython 3.7m macOS 10.6+ intel

xxtea-1.3.0-cp36-cp36m-win_amd64.whl (11.5 kB view hashes)

Uploaded CPython 3.6m Windows x86-64

xxtea-1.3.0-cp36-cp36m-win32.whl (10.3 kB view hashes)

Uploaded CPython 3.6m Windows x86

xxtea-1.3.0-cp36-cp36m-manylinux2010_x86_64.whl (27.4 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.12+ x86-64

xxtea-1.3.0-cp36-cp36m-manylinux2010_i686.whl (23.4 kB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.12+ i686

xxtea-1.3.0-cp36-cp36m-manylinux1_x86_64.whl (19.9 kB view hashes)

Uploaded CPython 3.6m

xxtea-1.3.0-cp36-cp36m-manylinux1_i686.whl (19.0 kB view hashes)

Uploaded CPython 3.6m

xxtea-1.3.0-cp36-cp36m-macosx_10_6_intel.whl (12.0 kB view hashes)

Uploaded CPython 3.6m macOS 10.6+ intel

xxtea-1.3.0-cp35-cp35m-win_amd64.whl (11.5 kB view hashes)

Uploaded CPython 3.5m Windows x86-64

xxtea-1.3.0-cp35-cp35m-win32.whl (10.2 kB view hashes)

Uploaded CPython 3.5m Windows x86

xxtea-1.3.0-cp35-cp35m-manylinux2010_x86_64.whl (27.2 kB view hashes)

Uploaded CPython 3.5m manylinux: glibc 2.12+ x86-64

xxtea-1.3.0-cp35-cp35m-manylinux2010_i686.whl (23.1 kB view hashes)

Uploaded CPython 3.5m manylinux: glibc 2.12+ i686

xxtea-1.3.0-cp35-cp35m-manylinux1_x86_64.whl (19.8 kB view hashes)

Uploaded CPython 3.5m

xxtea-1.3.0-cp35-cp35m-manylinux1_i686.whl (18.9 kB view hashes)

Uploaded CPython 3.5m

xxtea-1.3.0-cp35-cp35m-macosx_10_6_intel.whl (12.0 kB view hashes)

Uploaded CPython 3.5m macOS 10.6+ intel

xxtea-1.3.0-cp34-cp34m-win_amd64.whl (9.1 kB view hashes)

Uploaded CPython 3.4m Windows x86-64

xxtea-1.3.0-cp34-cp34m-win32.whl (8.9 kB view hashes)

Uploaded CPython 3.4m Windows x86

xxtea-1.3.0-cp34-cp34m-manylinux1_x86_64.whl (19.5 kB view hashes)

Uploaded CPython 3.4m

xxtea-1.3.0-cp34-cp34m-manylinux1_i686.whl (18.7 kB view hashes)

Uploaded CPython 3.4m

xxtea-1.3.0-cp34-cp34m-macosx_10_6_intel.whl (12.0 kB view hashes)

Uploaded CPython 3.4m macOS 10.6+ intel

xxtea-1.3.0-cp27-cp27mu-manylinux2010_x86_64.whl (25.9 kB view hashes)

Uploaded CPython 2.7mu manylinux: glibc 2.12+ x86-64

xxtea-1.3.0-cp27-cp27mu-manylinux2010_i686.whl (21.8 kB view hashes)

Uploaded CPython 2.7mu manylinux: glibc 2.12+ i686

xxtea-1.3.0-cp27-cp27mu-manylinux1_x86_64.whl (19.3 kB view hashes)

Uploaded CPython 2.7mu

xxtea-1.3.0-cp27-cp27mu-manylinux1_i686.whl (18.4 kB view hashes)

Uploaded CPython 2.7mu

xxtea-1.3.0-cp27-cp27m-win_amd64.whl (9.0 kB view hashes)

Uploaded CPython 2.7m Windows x86-64

xxtea-1.3.0-cp27-cp27m-win32.whl (8.9 kB view hashes)

Uploaded CPython 2.7m Windows x86

xxtea-1.3.0-cp27-cp27m-manylinux2010_x86_64.whl (25.9 kB view hashes)

Uploaded CPython 2.7m manylinux: glibc 2.12+ x86-64

xxtea-1.3.0-cp27-cp27m-manylinux2010_i686.whl (21.8 kB view hashes)

Uploaded CPython 2.7m manylinux: glibc 2.12+ i686

xxtea-1.3.0-cp27-cp27m-manylinux1_x86_64.whl (19.3 kB view hashes)

Uploaded CPython 2.7m

xxtea-1.3.0-cp27-cp27m-manylinux1_i686.whl (18.4 kB view hashes)

Uploaded CPython 2.7m

xxtea-1.3.0-cp27-cp27m-macosx_10_6_intel.whl (12.0 kB view hashes)

Uploaded CPython 2.7m macOS 10.6+ intel

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page