#!/usr/bin/env python
import random
from numpy import *
# un byte : entier sur 8 bits
# un char : caractere sur 8 bits
# un block : 4 bytes
class Crypt:
a2b={}
b2a={}
def __init__(self):
i=0
# Chaine de 64 caracteres utilises pour les codages ASCII
for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_":
self.a2b[c]=i
i=i+1
for k,v in self.a2b.items():
self.b2a[v]=k
def str2bytes(self,s):
t=[]
for c in s:
t.append(ord(c))
return t
def bytes2str(self,t):
s=""
for x in t.values():
s+=chr(x)
return s
def blocks2bytes(self,blocks):
bytes={}
iby=0
ibl=0
for a in range(len(blocks)):
bytes[iby]=255 & blocks[ibl] >> 24
iby+=1
bytes[iby]=255 & blocks[ibl] >> 16
iby+=1
bytes[iby]=255 & blocks[ibl] >> 8
iby+=1
bytes[iby]=255 & blocks[ibl]
iby+=1
ibl+=1
return bytes
def bytes2blocks(self,bytes):
# retour un tableau de long (sur 8 octets)
blocks={}
iby=0
ibl=0
while True:
blocks[ibl]=(255 & bytes[iby]) << 24
iby+=1
if iby>=len(bytes):
break
blocks[ibl] |= (255 & bytes[iby]) << 16
iby+=1
if iby>=len(bytes):
break
blocks[ibl] |= (255 & bytes[iby]) << 8
iby+=1
if iby>=len(bytes):
break
blocks[ibl] |= (255 & bytes[iby])
iby+=1
if iby>=len(bytes):
break
ibl+=1
return blocks
def binary2str(self,bks):
return self.bytes2str(self.blocks2bytes(bks))
def str2binary(self,s):
return self.bytes2blocks(self.str2bytes(s))
def xor_blocks(self,blk1,blk2):
# xor of two 8-byte blocks
blk={}
blk[0]=blk1[0]^blk2[0]
blk[1]=blk1[1]^blk2[1]
return blk
def binarydigest(self,str1,keystr=""):
key=[1633837924L,1650680933L,1667523942L,1684366951L]
c0=[1633837924L,1650680933L]
c1=c0
v0={}
v1={}
blocks=self.bytes2blocks(self.digest_pad(self.str2bytes(str1)))
ibl=0
swap=0
while ibl<len(blocks):
v0[0]=blocks[ibl]
ibl+=1
v0[1]=blocks[ibl]
ibl+=1
v1[0]=blocks[ibl]
ibl+=1
v1[1]=blocks[ibl]
ibl+=1
c0=self.tea_code(self.xor_blocks(v0,c0),key)
c1=self.tea_code(self.xor_blocks(v1,c1),key)
swap=c0[0]
c0[0]=c0[1]
c0[1]=c1[0]
c1[0]=c1[1]
c1[1]=swap
# mix up the two cipher blocks with a 32-bit left rotation...
swap={}
swap[0]=c0[0]
swap[1]=c0[1]
swap[2]=c1[0]
swap[3]=c1[1]
return swap
def asciidigest(s):
return self.binary2ascii(self.binarydigest(s))
def digest_pad(self,bytearray):
newarray={}
npads=15-(len(bytearray)%16)
newarray[0]=npads
ina=1
iba=0
for a in range(len(bytearray)):
newarray[ina]=bytearray[iba]
ina+=1
iba+=1
for a in range(npads,0,-1):
newarray[ina]=0
ina+=1
return newarray
def rand_byte(self):
return random.randint(0,255)
def pad(self,bytearray):
newarray={}
npads=7-len(bytearray)%8
# 248 | 7 = 255 ou encore F8 | 07 = FF
# ainsi les premiers bits de la premiere case du tableau n'ont pas d'interet
# d'ou l'utilisation de rand_byte()
# les 7 derniers bits permettent de retrouver le nombre d'octets de bourrage
newarray[0]=248 & self.rand_byte() | 7 & npads
ina=1
iba=0
for a in range(len(bytearray)):
newarray[ina]=bytearray[iba]
ina+=1
iba+=1
for a in range(npads,0,-1):
newarray[ina]=self.rand_byte()
ina+=1
return newarray
def unpad(self,bytearray):
newarray={}
# on calcule la taille effective du tablea sans les octets de bourrage
nba=len(bytearray) - (7 & bytearray[0])
ina=0
iba=1
while iba<nba:
newarray[ina]=bytearray[iba]
ina+=1
iba+=1
return newarray
def bytes2ascii(self,b):
s=""
ib=0
b1=0
b2=0
b3=0
carry=0
# on prend 3 octets (soit 24 bits) que l'on decoupe en 4 blocks de 6 bits
# soit 64 valeurs possibles qui servent comme index pour un caractere ASCII
while True:
if ib>=len(b):
break
b1=255 & b[ib]
# 63 = masque 0x3F - elimine les deux premiers bits (poids fort)
s+=self.b2a[63 & b1 >> 2]
# carry prend les deux derniers bits (poids faible)
carry=3 & b1
ib+=1
if ib>=len(b):
s+=self.b2a[carry << 4]
break
b2=255 & b[ib]
# 240 = masque 0xF0 - elimine les quatres derniers bits
s+=self.b2a[240 & carry << 4 | b2 >> 4]
# carry prend les quatres derniers bits (poids faible)
carry=15 & b2
ib+=1
if ib>=len(b):
s+=self.b2a[carry << 2]
break
b3=255 & b[ib]
# 60 = masque 0x3C - elimine les deux premiers et deux derniers bits
# 63 = masque 0x3F - elimine les deux premiers bits (poids fort)
s+=self.b2a[60 & carry << 2 | b3 >> 6]+self.b2a[63 & b3]
ib+=1
if ib%36==0:
s+="\n"
return s
def ascii2bytes(self,a):
la=len(a)
ia=-1 # pointeur sur chaine
ib=0 # pointeur sur tableau
b={} # tableau de retour
carry=0
while True:
while True:
ia+=1
if ia>=la:
return b
if a[ia] in self.a2b.keys():
break
b[ib]=self.a2b[a[ia]] << 2
while True:
ia+=1
if ia>=la:
return b
if a[ia] in self.a2b.keys():
break
carry=self.a2b[a[ia]]
b[ib] |= carry >> 4
ib+=1
carry &= 15
if carry==0 and ia==la-1:
return b
b[ib]=carry<<4
while True:
ia+=1
if ia>=la:
return b
if a[ia] in self.a2b.keys():
break
carry=self.a2b[a[ia]]
b[ib] |= carry >> 2
ib+=1
carry &= 3
if carry==0 and ia==la-1:
return b
b[ib]=carry << 6
while True:
ia+=1
if ia>=la:
return b
if a[ia] in self.a2b.keys():
break
b[ib] |= self.a2b[a[ia]]
ib+=1
return b
def ascii2binary(self,s):
return self.bytes2blocks(self.ascii2bytes(s))
def binary2ascii(self,t):
return self.bytes2ascii(self.blocks2bytes(t))
# cf. priorite des operateurs
# http://docs.python.org/reference/expressions.html
def tea_code(self,v,k):
# c'est du XTEA : http://en.wikipedia.org/wiki/XTEA
# TEA. 2-int (64-bit) (2x 4 octets) cyphertext block in v. 4-int (128-bit) key in k.
v0=uint32(v[0])
v1=uint32(v[1])
sum=0
tmp=0
tmp2=0
for i in range(0,32):
tmp=uint32( add( (self.SHL(v1,4) ^ self.USHR(v1,5)) , uint32(v1) ) )
tmp2=uint32( sum+k[sum&3])
v0=uint32( add(v0, tmp^tmp2))
sum= uint32(sum - 1640531527) # TEA magic number 0x9e3779b9
tmp=uint32( add( (self.SHL(v0,4) ^ self.USHR(v0,5)) , uint32(v0) ) )
tmp2=uint32( sum+k[(sum >> 11) & 3])
v1=uint32( add(v1,tmp^tmp2))
#print "v0:",v0,"v1:",v1
return [v0,v1]
def tea_decode(self,v,k):
v0=uint32(v[0])
v1=uint32(v[1])
sum=uint32(-957401312) # TEA magic number 0x9e3779b9<<5
for i in range(0,32):
tmp=uint32( add( (self.SHL(v0,4) ^ self.USHR(v0,5)) , uint32(v0) ) )
tmp2=uint32( sum+k[(sum >> 11) & 3])
v1 = uint32( subtract(v1, tmp^tmp2))
sum=uint32(sum + 1640531527) # TEA magic number 0x9e3779b9
tmp=uint32( add( (self.SHL(v1,4) ^ self.USHR(v1,5)) , uint(v1) ) )
tmp2=uint32( sum+k[sum&3])
v0 = uint32( subtract(v0, tmp^tmp2))
return [v0,v1]
def decrypt(self,M,K=""):
if K=="":
print "No key!!"
return False
if M=="":
return ""
bd=self.binarydigest(K)
bin=self.ascii2binary(M)
i=0
j=0
t0=[1633837924,1650680933]
t1=[]
t2={}
t3={}
while i<len(bin):
t2[0]=bin[i]
i+=1
t2[1]=bin[i]
i+=1
t1=self.xor_blocks(t0,self.tea_decode(t2,bd))
t3[j]=t1[0]
j+=1
t3[j]=t1[1]
j+=1
t0[0]=t2[0]
t0[1]=t2[1]
return self.bytes2str(self.unpad(self.blocks2bytes(t3)))
def encrypt(self,M="",K=""):
if K=="":
print "No key!!"
return False
if M=="":
return ""
bd=self.binarydigest(K)
bks=self.bytes2blocks(self.pad(self.str2bytes(M)))
i=0
j=0
t0=[1633837924,1650680933]
t1={}
t2={}
while i<len(bks):
t1[0]=bks[i]
i+=1
t1[1]=bks[i]
i+=1
t0=self.tea_code(self.xor_blocks(t1,t0),bd)
t2[j]=t0[0]
j+=1
t2[j]=t0[1]
j+=1
return self.binary2ascii(t2)
# fonctions faits maisons pour les decalages de bits sur entier de 32 bits non signes
def USHR(self,n,d):
if n>=0:
return n>>d
else:
return (n>>d)&(0xffffffff>>d)
def SHL(self,n,d):
mask=n&(0xffffffff>>d)
return mask<<d
# fonction trouve sur le web, affiche un chiffre sous sa forme binaire
def Denary2Binary(self,n):
'''convert denary (base 10) integer n to binary string bStr'''
bStr = ''
if n < 0: raise ValueError, "must be a positive"
if n == 0: return '0'
while n > 0:
bStr = str(n % 2) + bStr
n = n >> 1
return bStr
if __name__ == "__main__":
p="plop"
ep="ep"
v="1"
salt=""
for i in range(0,8):
salt+=str(random.randint(0,9))
json = '{"p":"'+p+'","ep":"'
json+=ep+'","v":"'+v+'","s":"'+salt+'"}'
c=Crypt()
print c.decrypt("q-mbHsiVngxbuIpQwvSCkEKSpfhfhNM7ujQB4fUcLXDbyF4cZABwsi8Vxa2n62deHjbDeZrqXTdGN4UkLDdogiiiOdpYWO9i68hX_AKZpeGtlOmyviP4JOxh13eKM7JWVXzjU3CtHefbvHiFrURTU4u6m8mmGZbuAadfnQ6UR4cqSC6bVipieCnTSpLpFQAcoXx8X86R5SmBpQ6FzQDfLXZJZhQ4MP_A4R3tBgdjSoCtbRlr7XAUV2DPe8ezkoxCq2YduYa_uOmGmB-TABOa--PMXf_XyueJi3puKyuwoJCZFfo1VFR0oA","I:NTnd7;+)WK?[:@S2ov")