72 lines
2.0 KiB
Python
72 lines
2.0 KiB
Python
# https://stackoverflow.com/questions/8356689/python-equivalent-of-phps-mcrypt-rijndael-256-cbc
|
|
|
|
class zeropad:
|
|
|
|
def __init__(self, block_size):
|
|
assert block_size > 0 and block_size < 256
|
|
self.block_size = block_size
|
|
|
|
def pad(self, pt):
|
|
ptlen = len(pt)
|
|
padsize = self.block_size - ((ptlen + self.block_size - 1) % self.block_size + 1)
|
|
return pt + "\0" * padsize
|
|
|
|
def unpad(self, ppt):
|
|
assert len(ppt) % self.block_size == 0
|
|
offset = len(ppt)
|
|
if (offset == 0):
|
|
return ''
|
|
end = offset - self.block_size + 1
|
|
while (offset > end):
|
|
offset -= 1;
|
|
if (ppt[offset] != "\0"):
|
|
return ppt[:offset + 1]
|
|
assert false
|
|
|
|
class cbc:
|
|
|
|
def __init__(self, padding, cipher, iv):
|
|
assert padding.block_size == cipher.block_size;
|
|
assert len(iv) == cipher.block_size;
|
|
self.padding = padding
|
|
self.cipher = cipher
|
|
self.iv = iv
|
|
|
|
def encrypt(self, pt):
|
|
ppt = self.padding.pad(pt)
|
|
offset = 0
|
|
ct = ''
|
|
v = self.iv
|
|
while (offset < len(ppt)):
|
|
block = ppt[offset:offset + self.cipher.block_size]
|
|
block = self.xorblock(block, v)
|
|
block = self.cipher.encrypt(block)
|
|
ct += block
|
|
offset += self.cipher.block_size
|
|
v = block
|
|
return ct;
|
|
|
|
def decrypt(self, ct):
|
|
assert len(ct) % self.cipher.block_size == 0
|
|
ppt = ''
|
|
offset = 0
|
|
v = self.iv
|
|
while (offset < len(ct)):
|
|
block = ct[offset:offset + self.cipher.block_size]
|
|
decrypted = self.cipher.decrypt(block)
|
|
ppt += self.xorblock(decrypted, v)
|
|
offset += self.cipher.block_size
|
|
v = block
|
|
pt = self.padding.unpad(ppt)
|
|
return pt;
|
|
|
|
def xorblock(self, b1, b2):
|
|
# sorry, not very Pythonesk
|
|
i = 0
|
|
r = '';
|
|
while (i < self.cipher.block_size):
|
|
r += chr(ord(b1[i]) ^ ord(b2[i]))
|
|
i += 1
|
|
return r
|
|
|