Python equivalent of PHP's MCRYPT_RIJNDAEL_256 CBC - php
I need a Python implementation of this function - I want to use it on appengine.
I am not so good in Python so please help.
function encrypt($data) {
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256 ,'oqufXQ(?bc=6_hR2I3sMZChDpb6dDlw4', $data , MCRYPT_MODE_CBC, utf8_encode('fOaiIOkD8*9Xeu_s4_bb87Ox_UG+D9GA')));
}
Have you tried this one (also included below)? It implements the Rijndael block cipher for 16, 24 or 32 bytes. You are using the 256 bit (32 byte) version of the block cipher.
"""
A pure python (slow) implementation of rijndael with a decent interface
To include -
from rijndael import rijndael
To do a key setup -
r = rijndael(key, block_size = 16)
key must be a string of length 16, 24, or 32
blocksize must be 16, 24, or 32. Default is 16
To use -
ciphertext = r.encrypt(plaintext)
plaintext = r.decrypt(ciphertext)
If any strings are of the wrong length a ValueError is thrown
"""
# ported from the Java reference code by Bram Cohen, April 2001
# this code is public domain, unless someone makes
# an intellectual property claim against the reference
# code, in which case it can be made public domain by
# deleting all the comments and renaming all the variables
import copy
import string
shifts = [[[0, 0], [1, 3], [2, 2], [3, 1]],
[[0, 0], [1, 5], [2, 4], [3, 3]],
[[0, 0], [1, 7], [3, 5], [4, 4]]]
# [keysize][block_size]
num_rounds = {16: {16: 10, 24: 12, 32: 14}, 24: {16: 12, 24: 12, 32: 14}, 32: {16: 14, 24: 14, 32: 14}}
A = [[1, 1, 1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 1, 1, 1],
[1, 1, 0, 0, 0, 1, 1, 1],
[1, 1, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 0, 0, 1]]
# produce log and alog tables, needed for multiplying in the
# field GF(2^m) (generator = 3)
alog = [1]
for i in range(255):
j = (alog[-1] << 1) ^ alog[-1]
if j & 0x100 != 0:
j ^= 0x11B
alog.append(j)
log = [0] * 256
for i in range(1, 255):
log[alog[i]] = i
# multiply two elements of GF(2^m)
def mul(a, b):
if a == 0 or b == 0:
return 0
return alog[(log[a & 0xFF] + log[b & 0xFF]) % 255]
# substitution box based on F^{-1}(x)
box = [[0] * 8 for i in range(256)]
box[1][7] = 1
for i in range(2, 256):
j = alog[255 - log[i]]
for t in range(8):
box[i][t] = (j >> (7 - t)) & 0x01
B = [0, 1, 1, 0, 0, 0, 1, 1]
# affine transform: box[i] <- B + A*box[i]
cox = [[0] * 8 for i in range(256)]
for i in range(256):
for t in range(8):
cox[i][t] = B[t]
for j in range(8):
cox[i][t] ^= A[t][j] * box[i][j]
# S-boxes and inverse S-boxes
S = [0] * 256
Si = [0] * 256
for i in range(256):
S[i] = cox[i][0] << 7
for t in range(1, 8):
S[i] ^= cox[i][t] << (7-t)
Si[S[i] & 0xFF] = i
# T-boxes
G = [[2, 1, 1, 3],
[3, 2, 1, 1],
[1, 3, 2, 1],
[1, 1, 3, 2]]
AA = [[0] * 8 for i in range(4)]
for i in range(4):
for j in range(4):
AA[i][j] = G[i][j]
AA[i][i+4] = 1
for i in range(4):
pivot = AA[i][i]
if pivot == 0:
t = i + 1
while AA[t][i] == 0 and t < 4:
t += 1
assert t != 4, 'G matrix must be invertible'
for j in range(8):
AA[i][j], AA[t][j] = AA[t][j], AA[i][j]
pivot = AA[i][i]
for j in range(8):
if AA[i][j] != 0:
AA[i][j] = alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255]
for t in range(4):
if i != t:
for j in range(i+1, 8):
AA[t][j] ^= mul(AA[i][j], AA[t][i])
AA[t][i] = 0
iG = [[0] * 4 for i in range(4)]
for i in range(4):
for j in range(4):
iG[i][j] = AA[i][j + 4]
def mul4(a, bs):
if a == 0:
return 0
r = 0
for b in bs:
r <<= 8
if b != 0:
r = r | mul(a, b)
return r
T1 = []
T2 = []
T3 = []
T4 = []
T5 = []
T6 = []
T7 = []
T8 = []
U1 = []
U2 = []
U3 = []
U4 = []
for t in range(256):
s = S[t]
T1.append(mul4(s, G[0]))
T2.append(mul4(s, G[1]))
T3.append(mul4(s, G[2]))
T4.append(mul4(s, G[3]))
s = Si[t]
T5.append(mul4(s, iG[0]))
T6.append(mul4(s, iG[1]))
T7.append(mul4(s, iG[2]))
T8.append(mul4(s, iG[3]))
U1.append(mul4(t, iG[0]))
U2.append(mul4(t, iG[1]))
U3.append(mul4(t, iG[2]))
U4.append(mul4(t, iG[3]))
# round constants
rcon = [1]
r = 1
for t in range(1, 30):
r = mul(2, r)
rcon.append(r)
del A
del AA
del pivot
del B
del G
del box
del log
del alog
del i
del j
del r
del s
del t
del mul
del mul4
del cox
del iG
class rijndael:
def __init__(self, key, block_size = 16):
if block_size != 16 and block_size != 24 and block_size != 32:
raise ValueError('Invalid block size: ' + str(block_size))
if len(key) != 16 and len(key) != 24 and len(key) != 32:
raise ValueError('Invalid key size: ' + str(len(key)))
self.block_size = block_size
ROUNDS = num_rounds[len(key)][block_size]
BC = block_size // 4
# encryption round keys
Ke = [[0] * BC for i in range(ROUNDS + 1)]
# decryption round keys
Kd = [[0] * BC for i in range(ROUNDS + 1)]
ROUND_KEY_COUNT = (ROUNDS + 1) * BC
KC = len(key) // 4
# copy user material bytes into temporary ints
tk = []
for i in range(0, KC):
tk.append((ord(key[i * 4]) << 24) | (ord(key[i * 4 + 1]) << 16) |
(ord(key[i * 4 + 2]) << 8) | ord(key[i * 4 + 3]))
# copy values into round key arrays
t = 0
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t // BC][t % BC] = tk[j]
Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
j += 1
t += 1
tt = 0
rconpointer = 0
while t < ROUND_KEY_COUNT:
# extrapolate using phi (the round key evolution function)
tt = tk[KC - 1]
tk[0] ^= (S[(tt >> 16) & 0xFF] & 0xFF) << 24 ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 16 ^ \
(S[ tt & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) ^ \
(rcon[rconpointer] & 0xFF) << 24
rconpointer += 1
if KC != 8:
for i in range(1, KC):
tk[i] ^= tk[i-1]
else:
for i in range(1, KC // 2):
tk[i] ^= tk[i-1]
tt = tk[KC // 2 - 1]
tk[KC // 2] ^= (S[ tt & 0xFF] & 0xFF) ^ \
(S[(tt >> 8) & 0xFF] & 0xFF) << 8 ^ \
(S[(tt >> 16) & 0xFF] & 0xFF) << 16 ^ \
(S[(tt >> 24) & 0xFF] & 0xFF) << 24
for i in range(KC // 2 + 1, KC):
tk[i] ^= tk[i-1]
# copy values into round key arrays
j = 0
while j < KC and t < ROUND_KEY_COUNT:
Ke[t // BC][t % BC] = tk[j]
Kd[ROUNDS - (t // BC)][t % BC] = tk[j]
j += 1
t += 1
# inverse MixColumn where needed
for r in range(1, ROUNDS):
for j in range(BC):
tt = Kd[r][j]
Kd[r][j] = U1[(tt >> 24) & 0xFF] ^ \
U2[(tt >> 16) & 0xFF] ^ \
U3[(tt >> 8) & 0xFF] ^ \
U4[ tt & 0xFF]
self.Ke = Ke
self.Kd = Kd
def encrypt(self, plaintext):
if len(plaintext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(plaintext)))
Ke = self.Ke
BC = self.block_size // 4
ROUNDS = len(Ke) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][0]
s2 = shifts[SC][2][0]
s3 = shifts[SC][3][0]
a = [0] * BC
# temporary work array
t = []
# plaintext to ints + key
for i in range(BC):
t.append((ord(plaintext[i * 4 ]) << 24 |
ord(plaintext[i * 4 + 1]) << 16 |
ord(plaintext[i * 4 + 2]) << 8 |
ord(plaintext[i * 4 + 3]) ) ^ Ke[0][i])
# apply round transforms
for r in range(1, ROUNDS):
for i in range(BC):
a[i] = (T1[(t[ i ] >> 24) & 0xFF] ^
T2[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T3[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T4[ t[(i + s3) % BC] & 0xFF] ) ^ Ke[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in range(BC):
tt = Ke[ROUNDS][i]
result.append((S[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((S[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((S[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((S[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return ''.join(map(chr, result))
def decrypt(self, ciphertext):
if len(ciphertext) != self.block_size:
raise ValueError('wrong block length, expected ' + str(self.block_size) + ' got ' + str(len(ciphertext)))
Kd = self.Kd
BC = self.block_size // 4
ROUNDS = len(Kd) - 1
if BC == 4:
SC = 0
elif BC == 6:
SC = 1
else:
SC = 2
s1 = shifts[SC][1][1]
s2 = shifts[SC][2][1]
s3 = shifts[SC][3][1]
a = [0] * BC
# temporary work array
t = [0] * BC
# ciphertext to ints + key
for i in range(BC):
t[i] = (ord(ciphertext[i * 4 ]) << 24 |
ord(ciphertext[i * 4 + 1]) << 16 |
ord(ciphertext[i * 4 + 2]) << 8 |
ord(ciphertext[i * 4 + 3]) ) ^ Kd[0][i]
# apply round transforms
for r in range(1, ROUNDS):
for i in range(BC):
a[i] = (T5[(t[ i ] >> 24) & 0xFF] ^
T6[(t[(i + s1) % BC] >> 16) & 0xFF] ^
T7[(t[(i + s2) % BC] >> 8) & 0xFF] ^
T8[ t[(i + s3) % BC] & 0xFF] ) ^ Kd[r][i]
t = copy.copy(a)
# last round is special
result = []
for i in range(BC):
tt = Kd[ROUNDS][i]
result.append((Si[(t[ i ] >> 24) & 0xFF] ^ (tt >> 24)) & 0xFF)
result.append((Si[(t[(i + s1) % BC] >> 16) & 0xFF] ^ (tt >> 16)) & 0xFF)
result.append((Si[(t[(i + s2) % BC] >> 8) & 0xFF] ^ (tt >> 8)) & 0xFF)
result.append((Si[ t[(i + s3) % BC] & 0xFF] ^ tt ) & 0xFF)
return ''.join(map(chr, result))
def encrypt(key, block):
return rijndael(key, len(block)).encrypt(block)
def decrypt(key, block):
return rijndael(key, len(block)).decrypt(block)
Note that the rijndael.py file only implements the block cipher. The encrypt / decrypt functions only handle plaintexts that are precisely the block size. This means that the caller of these functions will have to provide the block cipher mode of operation and the zero padding himself.
Example python code (from a Java programmer, beware):
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
Related
Implementation of a Python encription code in PHP or NodeJS
I am trying to implement a python encription code based on gzip and crypto library but i dont know the equivalent modules or functions in either php or node js from Crypto.Cipher import DES, AES def enclen(p): return ((16 - p % 16) & 0xF) + p + 4 def rsb(a, b): return (0 - a + b) & 0xffffffff def ands(a, b): return (a & b) & 0xffffffff def _ror(val, bits, bit_size): return ((val & (2 ** bit_size - 1)) >> bits % bit_size) | \ (val << (bit_size - (bits % bit_size)) & (2 ** bit_size - 1)) def __ROR4__(a, b): return _ror(a, b, 32) def eor(a, b): return (a ^ b) & 0xffffffff class Crypto(object): def __init__(self): self.key = b'!*ss!_defaul%t54' self.kl = 0x10 self.sbox0 = bytes.fromhex( '637C777BF26B6FC53001672BFED7AB76CA82C97DFA5947F0ADD4A2AF9CA472' 'C0B7FD9326363FF7CC34A5E5F171D8311504C723C31896059A071280E2EB27' 'B27509832C1A1B6E5AA0523BD6B329E32F8453D100ED20FCB15B6ACBBE394A' '4C58CFD0EFAAFB434D338545F9027F503C9FA851A3408F929D38F5BCB6DA21' '10FFF3D2CD0C13EC5F974417C4A77E3D645D197360814FDC222A908846EEB8' '14DE5E0BDBE0323A0A4906245CC2D3AC629195E479E7C8376D8DD54EA96C56' 'F4EA657AAE08BA78252E1CA6B4C6E8DD741F4BBD8B8A703EB5664803F60E61' '3557B986C11D9EE1F8981169D98E949B1E87E9CE5528DF8CA1890DBFE64268' '41992D0FB054BB16') self.plen = 0 def crypt(self, payload): if not isinstance(payload, bytes): payload = payload.encode('utf8') self.plen = len(payload) i = 0 r = [00] * 16 while i < self.kl: a = self.key[i] r[i] = self.sbox0[a] i += 1 t = int.from_bytes(r[:4], 'big') r[:4] = int.to_bytes(t, 4, 'little') t = int.from_bytes(r[4:8], 'big') r[4:8] = int.to_bytes(t, 4, 'little') t = int.from_bytes(r[8:12], 'big') r[8:12] = int.to_bytes(t, 4, 'little') t = int.from_bytes(r[12:16], 'big') r[12:16] = int.to_bytes(t, 4, 'little') b = rsb(self.plen, 0) b = ands(b, 0xf) c = b + self.plen + 4 result = [00] * enclen(self.plen) result[0] = 0x74 result[1] = 0x63 result[2] = 0x02 result[3] = b result[4:len(payload) + 4] = payload i = 4 while i != c: a = result[i] result[i] = self.sbox0[a] i += 1 a = c - 4 b = 0 a = a >> 4 d = 4 while b < a: c = int.from_bytes(result[d:d + 4], 'big') e = int.from_bytes(r[:4], 'little') c ^= e result[d:d + 4] = int.to_bytes(c, 4, 'big') c = int.from_bytes(result[d + 4:d + 8], 'big') e = int.from_bytes(r[4:8], 'little') c = eor(e, __ROR4__(c, 24)) result[d + 4:d + 8] = int.to_bytes(c, 4, 'big') c = int.from_bytes(result[d + 8:d + 12], 'big') e = int.from_bytes(r[8:12], 'little') c = eor(e, __ROR4__(c, 16)) result[d + 8:d + 12] = int.to_bytes(c, 4, 'big') c = int.from_bytes(result[d + 12:d + 16], 'big') e = int.from_bytes(r[12:16], 'little') c = eor(e, __ROR4__(c, 8)) result[d + 12:d + 16] = int.to_bytes(c, 4, 'big') b += 1 d += 0x10 return bytes(result) I dont have much idea what really goes behind this code some byte size operations but i dont know what exactly happens Either nodejs or php equivalent of this code or any idea to how to implement it in those lang or if those languages are supported this kind of operations I dont know
Node.js has really good modules that can handle compression and encryption. Crypto for cryptography related operations. It supports many algorithms to encrypt/hash stuff Zlib for compression. Supports algorithms like gzip, deflate, zip, etc... The docs also include examples on how to use these modules, so make sure to check them
Equivalent to java "Color.decode" in php or mysql
I have a mysql database with a string field called "color" from java I keep the value so: // (2=color field) pst.setString (2, objeto.getBackground (). getRGB ()) and then I read it like this: objeto.setBackground (Color.decode (rs.getString ("color"))) Is there any function in mysql or php to read the color?
What do you want exactly? Convert a int to a color in #RRGGBB format? sprintf('#%06X', $color); or get the R, G, B values? $r = ($color >> 16) & 0xFF; $g = ($color >> 8) & 0xFF; $b = ($color >> 0) & 0xFF; or create a int from rgb values $color = ($r & 0xFF) << 16 | ($g & 0xFF) << 8 | $b & 0xFF
using binary operator in Python... translating if (c1 >= "\xc0" & c1 <= "\xdf")
i am converting an external class from PHP to Python, it does some tricks like : if ($c1 >= "\xc0" & $c1 <= "\xdf") [...] $cc1 = (chr(ord($c1) / 64) | "\xc0"); [...] $cc2 = ($c1 & "\x3f") | "\x80"; where $c1,^$cc1, $cc2 are characters and i just realized that i cannot use it as such with python, as characters are string, and not duplicately seen as "binary representation of a character" where operators & and | make sense... please, how would you translate any of these in a Pythonic way ? >>> c1 = "a" >>> (c1 & "\x3f") | "\x80" Traceback (most recent call last): File "<pyshell#202>", line 1, in <module> (c1 & "\x3f") | "\x80" TypeError: unsupported operand type(s) for &: 'str' and 'str' EDIT: actually, it seems that this PHP class do not work, so it will not fit my needs either. Many thanks for your help.
Use the ord function to get the value and then use actual numbers to do the masking. >>> c1 = "a" >>> (ord(c1) & 0x3f) | 0x80 161 >>> hex((ord(c1) & 0x3f) | 0x80) '0xa1'
That's a primitive UTF-8 encoding function. c1.encode('utf-8') Note that unless you use unicodes natively (and why aren't you?) you'll need to decode from 'latin-1' first.
Python 2.7.3 (default, Sep 26 2012, 21:51:14) >>> c1 = 'd' >>> # if ($c1 >= "\xc0" & $c1 <= "\xdf") ... >>> ord(c1) >= 0xc0 and ord(c1) <= 0xdf False >>> # $cc1 = (chr(ord($c1) / 64) | "\xc0"); ... >>> chr(ord(c1) / 64 | 0xc0) '\xc1' >>> # $cc2 = ($c1 & "\x3f") | "\x80"; ... >>> ord(c1) & 0x3f | 0x80 164 >>>
PHP Bit shifting in code?
Can someone help me understand this ancient code? $a = 00040000000002; $n = sscanf($a,"%02x%02x%02x%02x%02x%02x%02x",$r[7],$r[6],$r[5],$r[4],$r[3],$r[2],$r[1]); $ptemp = $r[1] + (($r[2] & 0x1F) << 8); $l[$i] = (($r[2] & 0xE0) >> 5) + ($r[3] << 3); $m[$i] = $r[4] + (($r[5] & 0x03) << 8); $h[$i] = (($r[5] & 0xFC) >> 2) + (($r[6] & 0x03) << 6); $dist[$i] = (($r[6] & 0xFC) >> 2) + (($r[7] & 0x0F) << 6); $fruittoday[$i] = ($r[7] & 0xF0) >> 4; I understand the sscanf, but I'm not sure what is going on with the & 0x1f << 8, etc. Any ideas?
They're using Bitwise Operators to check if specific bits are turned on. In the example you've provided, they're confirming the first 5 bits are 1's then shifting all bits to the left 8 places. (Although it seems like in this case they're starting with 0 (00000000), checking if 0x1F are on (00011111) which would still be 0, then shifting them left 8 places (put in to the 2^8th position) For reference, I would check out php's manual on bitwise operators. They list some example of what's going on here. If you're really curious, just echo the variables as they are manipulated (or break it out in to separate operations) and then examine them).
PHP Bytes 2 DWord
I have an array: $arr[0] = 95 $arr[1] = 8 $arr[2] = 0 $arr[3] = 0 That are bytes. I need a DWORD. I tried: $dword = $arr[0]+$arr[1]*265+$arr[2]*265*265+$arr[3]*265*265*265; Is that right or am I doing it wrong?
Try: $dword = (($arr[3] & 0xFF) << 24) | (($arr[2] & 0xFF) << 16) | (($arr[1] & 0xFF) << 8) | ($arr[0] & 0xFF); It can also be done your way with some corrections: $dword = $arr[0] + $arr[1]*0x100 + $arr[2]*0x10000 + $arr[3]*0x1000000; Or using pack/unpack: $dword = array_shift(unpack("L", pack("CCCC", $arr[0], $arr[1], $arr[2], $arr[3])));
Or try<?php $arr = array(95,8,0,0); $bindata = join('', array_map('chr', $arr)); var_dump(unpack('L', $bindata));both (Emil H's and my code) give you 2143 as the result.
Or at the very least use 256 rather than 265.
Your code should work correctly, but you should multiply with 256, not 265. (in 8 bits, there are 2^8 = 256 unique values). It works, because multiplying with 256 is the same as shifting the bits 8 places to the left. Perhaps you should consider using the bitwise operators instead, to better convey the intent. See http://theopensourcery.com/phplogic.htm