From Python to PHP. An example
PHP es poco amigable cuando queremos trabajar con "big integers". Lo que se muestra poco menos que insufrible cuando queremos adaptar códigos de otros lenguajes más potentes en ello como Python. Aquí pongo algunos ejemplos para ayudar a adaptar de uno a otro lenguaje.
1- struct.pack & ord
def pack(data):
target = []
for i in data:
target.extend(struct.pack('>I', i))
target = [ord(c) for c in target]
return target
En este caso PHP nos permite realizar el proceso en un solo bucle.
El proceso Python realiza en un primer bucle un struct.pack('>I', i) de cada elemento del array data, y en un segundo bucle convierte cada uno de los elementos (caracteres) anteriores a su valor numérico ASCII. Con PHP tenemos el solo comando
array_values(unpack("C*",pack("N",$i)))
function packk($data) { $target = array(); foreach ($data as $i) {$target=array_merge($target,array_values(unpack("C*",pack("N",$i))));} return $target; }
2- trabajando con bitwise XOR y shifts.
Ejemplo Python
def tea_encrypt(v, key): | |
s = 0 | |
key = unpack(key) | |
v = unpack(v) | |
for i in range(ROUNDS): | |
s += DELTA | |
s &= 0xffffffff | |
v[0] += (v[1]+s) ^ ((v[1]>>5)+key[1]) ^ ((v[1]<<4)+key[0]) | |
v[0] &= 0xffffffff | |
v[1] += (v[0]+s) ^ ((v[0]>>5)+key[3]) ^ ((v[0]<<4)+key[2]) | |
v[1] &= 0xffffffff | |
return pack(v) |
En este caso PHP ofrece demasiados problemas y la implementación es más complicada.
Necesitamos codificar las siguientes funciones por separado:
- la conversión a 32 bits sin signo: to32
- el right shift (>>): _rshift
- el left shift (<<): simplemente usando pow, a << b es a*2^b (aquí ^ es potencia)
- el XOR (^), con la función binxor
function to32($integer) { if (0xffffffff < $integer || -0xffffffff > $integer) $integer = fmod($integer, 0xffffffff + 1); if (0x7fffffff < $integer) $integer -= 0xffffffff + 1.0; elseif (-0x80000000 > $integer) $integer += 0xffffffff + 1.0; return $integer; }
function _rshift($integer, $n) { $integer=to32($integer); if (0 > $integer) { $integer &= 0x7fffffff; $integer >>= $n; $integer |= 1 << (31 - $n); } else $integer >>= $n; return $integer; }
function binxor($w1,$w2) { $x=base_convert($w1, 10, 2); $y=base_convert($w2, 10, 2); if (strlen($y)<strlen($x)) $y=str_repeat(0,strlen($x)-strlen($y)).$y; if (strlen($x)<strlen($y)) $x=str_repeat(0,strlen($y)-strlen($x)).$x; $x=str_split($x);$y=str_split($y); $z=""; for ($k=0;$k<sizeof($x);$k++) { $z.=(int)($x[$k])^(int)($y[$k]); } return base_convert($z,2,10); } function bigint($a) {return bindec(decbin($a));}
function tea_encrypt($v, $key) { $s = 0; $key = unpackk($key); $v = unpackk($v); for ($i=0;$i<16;$i++) { $s+= hexdec("9e3779b9");
/*
el código python es
v[0] += (v[1]+s) ^ ((v[1]>>5)+key[1]) ^ ((v[1]<<4)+key[0])
v[0] &= 0xffffffff
ejemplos de cómo computan diferente a- right shift 3688618752 >> 5 python 115269336 php -18948392 b- left shift 3688618752 << 5 python 118035800064 php 2071683072 en este caso basta con aplicar 3688618752*pow(2,5) c- bitwise XOR 3688618752 ^ 5 python 3688618757 php -606348539 usamos binxor, haciendo el xor bit a bit en binario. Pero hay que usar base_convert y no decbin porque éste último corta a 32 bits. |
Great !>
ResponderEliminarPost!>
well!>
done!>