Menu

[r108]: / xtea.py  Maximize  Restore  History

Download this file

135 lines (111 with data), 4.7 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""
XTEA Block Encryption Algorithm
Author: Paul Chakravarti (paul_dot_chakravarti_at_gmail_dot_com)
License: Public Domain
This module provides a Python implementation of the XTEA block encryption
algorithm (http://www.cix.co.uk/~klockstone/xtea.pdf).
The module implements the basic XTEA block encryption algortithm
(`xtea_encrypt`/`xtea_decrypt`) and also provides a higher level `crypt`
function which symmetrically encrypts/decrypts a variable length string using
XTEA in OFB mode as a key generator. The `crypt` function does not use
`xtea_decrypt` which is provided for completeness only (but can be used
to support other stream modes - eg CBC/CFB).
This module is intended to provide a simple 'privacy-grade' Python encryption
algorithm with no external dependencies. The implementation is relatively slow
and is best suited to small volumes of data. Note that the XTEA algorithm has
not been subjected to extensive analysis (though is believed to be relatively
secure - see http://en.wikipedia.org/wiki/XTEA). For applications requiring
'real' security please use a known and well tested algorithm/implementation.
The security of the algorithm is entirely based on quality (entropy) and
secrecy of the key. You should generate the key from a known random source and
exchange using a trusted mechanism. In addition, you should always use a random
IV to seed the key generator (the IV is not sensitive and does not need to be
exchanged securely)
>>> import os
>>> iv = 'ABCDEFGH'
>>> z = crypt('0123456789012345','Hello There',iv)
>>> z.encode('hex')
'fe196d0a40d6c222b9eff3'
>>> crypt('0123456789012345',z,iv)
'Hello There'
"""
import struct
def crypt(key,data,iv='\00\00\00\00\00\00\00\00',n=32):
"""
Encrypt/decrypt variable length string using XTEA cypher as
key generator (OFB mode)
* key = 128 bit (16 char)
* iv = 64 bit (8 char)
* data = string (any length)
>>> import os
>>> key = os.urandom(16)
>>> iv = os.urandom(8)
>>> data = os.urandom(10000)
>>> z = crypt(key,data,iv)
>>> crypt(key,z,iv) == data
True
"""
def keygen(key,iv,n):
while True:
iv = xtea_encrypt(key,iv,n)
for k in iv:
yield ord(k)
xor = [ chr(x^y) for (x,y) in zip(map(ord,data),keygen(key,iv,n)) ]
return "".join(xor)
def xtea_encrypt(key,block,n=32,endian="!"):
"""
Encrypt 64 bit data block using XTEA block cypher
* key = 128 bit (16 char)
* block = 64 bit (8 char)
* n = rounds (default 32)
* endian = byte order (see 'struct' doc - default big/network)
>>> z = xtea_encrypt('0123456789012345','ABCDEFGH')
>>> z.encode('hex')
'b67c01662ff6964a'
Only need to change byte order if sending/receiving from
alternative endian implementation
>>> z = xtea_encrypt('0123456789012345','ABCDEFGH',endian="<")
>>> z.encode('hex')
'ea0c3d7c1c22557f'
"""
v0,v1 = struct.unpack(endian+"2L",block)
k = struct.unpack(endian+"4L",key)
sum,delta,mask = 0L,0x9e3779b9L,0xffffffffL
for round in range(n):
v0 = (v0 + (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
sum = (sum + delta) & mask
v1 = (v1 + (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
return struct.pack(endian+"2L",v0,v1)
def xtea_decrypt(key,block,n=32,endian="!"):
"""
Decrypt 64 bit data block using XTEA block cypher
* key = 128 bit (16 char)
* block = 64 bit (8 char)
* n = rounds (default 32)
* endian = byte order (see 'struct' doc - default big/network)
>>> z = 'b67c01662ff6964a'.decode('hex')
>>> xtea_decrypt('0123456789012345',z)
'ABCDEFGH'
Only need to change byte order if sending/receiving from
alternative endian implementation
>>> z = 'ea0c3d7c1c22557f'.decode('hex')
>>> xtea_decrypt('0123456789012345',z,endian="<")
'ABCDEFGH'
"""
v0,v1 = struct.unpack(endian+"2L",block)
k = struct.unpack(endian+"4L",key)
delta,mask = 0x9e3779b9L,0xffffffffL
sum = (delta * n) & mask
for round in range(n):
v1 = (v1 - (((v0<<4 ^ v0>>5) + v0) ^ (sum + k[sum>>11 & 3]))) & mask
sum = (sum - delta) & mask
v0 = (v0 - (((v1<<4 ^ v1>>5) + v1) ^ (sum + k[sum & 3]))) & mask
return struct.pack(endian+"2L",v0,v1)
if __name__ == "__main__":
import doctest
doctest.testmod()
import os
iv = 'OXCENTER'
z = crypt('0001001203123','Hello There',iv)
print z.encode('hex')
print crypt('0123456789012345',z,iv)
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.