significant - python bit manipulation
XOR bit a bit de nĂºmeros hexadecimales en python (5)
¿cómo podemos XOR números hexadecimales en python, por ejemplo. Quiero xor ''ABCD'' a ''12EF''. la respuesta debe ser B922.
Utilicé el código siguiente pero está devolviendo el valor de la basura
def strxor(a, b): # xor two strings of different lengths
if len(a) > len(b):
return "".join(["%s" % (ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])
else:
return "".join(["%s" % (ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])
key =''12ef''
m1=''abcd''
print strxor(key,m1)
Para fines de rendimiento, aquí hay un pequeño código para comparar estas dos alternativas:
#!/bin/python
def hexxorA(a, b):
if len(a) > len(b):
return "".join(["%x" % (int(x,16) ^ int(y,16)) for (x, y) in zip(a[:len(b)], b)])
else:
return "".join(["%x" % (int(x,16) ^ int(y,16)) for (x, y) in zip(a, b[:len(a)])])
def hexxorB(a, b):
if len(a) > len(b):
return ''%x'' % (int(a[:len(b)],16)^int(b,16))
else:
return ''%x'' % (int(a,16)^int(b[:len(a)],16))
def testA():
strstr = hexxorA("b4affa21cbb744fa9d6e055a09b562b87205fe73cd502ee5b8677fcd17ad19fce0e0bba05b1315e03575fe2a783556063f07dcd0b9d15188cee8dd99660ee751", "5450ce618aae4547cadc4e42e7ed99438b2628ff15d47b20c5e968f086087d49ec04d6a1b175701a5e3f80c8831e6c627077f290c723f585af02e4c16122b7e2")
if not int(strstr, 16) == int("e0ff3440411901bd57b24b18ee58fbfbf923d68cd88455c57d8e173d91a564b50ce46d01ea6665fa6b4a7ee2fb2b3a644f702e407ef2a40d61ea3958072c50b3", 16):
raise KeyError
return strstr
def testB():
strstr = hexxorB("b4affa21cbb744fa9d6e055a09b562b87205fe73cd502ee5b8677fcd17ad19fce0e0bba05b1315e03575fe2a783556063f07dcd0b9d15188cee8dd99660ee751", "5450ce618aae4547cadc4e42e7ed99438b2628ff15d47b20c5e968f086087d49ec04d6a1b175701a5e3f80c8831e6c627077f290c723f585af02e4c16122b7e2")
if not int(strstr, 16) == int("e0ff3440411901bd57b24b18ee58fbfbf923d68cd88455c57d8e173d91a564b50ce46d01ea6665fa6b4a7ee2fb2b3a644f702e407ef2a40d61ea3958072c50b3", 16):
raise KeyError
return strstr
if __name__ == ''__main__'':
import timeit
print("Time-it 100k iterations :")
print("/thexxorA: ", end='''')
print(timeit.timeit("testA()", setup="from __main__ import testA", number=100000), end=''s/n'')
print("/thexxorB: ", end='''')
print(timeit.timeit("testB()", setup="from __main__ import testB", number=100000), end=''s/n'')
Aquí están los resultados :
Time-it 100k iterations :
hexxorA: 8.139988073991844s
hexxorB: 0.240523161992314s
Parece que ''%x'' % (int(a,16)^int(b,16))
es más rápido que la versión zip.
Si las cadenas tienen la misma longitud, entonces elegiría ''%x'' % ()
del xor incorporado ( ^
).
Ejemplos:
>>>a = ''290b6e3a''
>>>b = ''d6f491c5''
>>>''%x'' % (int(a,16)^int(b,16))
''ffffffff''
>>>c = ''abcd''
>>>d = ''12ef''
>>>''%x'' % (int(a,16)^int(b,16))
''b922''
Si las cadenas no tienen la misma longitud, trunca la cadena más larga a la longitud de la más corta usando una porción longer = longer[:len(shorter)]
Si las dos cadenas hexagonales tienen la misma longitud y quieres una salida de cadena hexagonal, puedes probar esto.
def hexxor(a, b): # xor two hex strings of the same length return "".join(["%x" % (int(x,16) ^ int(y,16)) for (x, y) in zip(a, b)])
Whoa. Realmente estás complicando demasiado por una distancia muy larga. Tratar:
>>> print hex(0x12ef ^ 0xabcd)
0xb922
Parece que ignoras estos hechos útiles, al menos:
- Python tiene soporte nativo para literales enteros hexadecimales, con el prefijo
0x
. - "Hexadecimal" es solo un detalle de presentación; la aritmética se hace en binario, y luego el resultado se imprime como hexadecimal.
- No hay conexión entre el formato de las entradas (los literales hexadecimales) y la salida, no existe un "número hexadecimal" en una variable de Python.
- La función
hex()
se puede usar para convertir cualquier número en una cadena hexadecimal para su visualización.
Si ya tiene los números como cadenas, puede usar la función int()
para convertir a números, proporcionando la base esperada (16 para números hexadecimales):
>>> print int("12ef", 16)
4874
Entonces puede hacer dos conversiones, realizar el XOR y luego convertir de nuevo a hexadecimal:
>>> print hex(int("12ef", 16) ^ int("abcd", 16))
0xb922
aquí hay una mejor función
def strxor(a, b): # xor two strings of different lengths
if len(a) > len(b):
return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a[:len(b)], b)])
else:
return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b[:len(a)])])