2012-06-20 19 views
32

cómo podemos usar números hexadecimales XOR en python ej. Quiero xor 'ABCD' a '12EF'. la respuesta debe ser B922.bit a bit XOR de números hexadecimales en python

i utiliza a continuación el código pero está volviendo valor de 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) 
+1

Solo una sugerencia para 'zip': elimina el argumento más largo automáticamente. De todos modos, @unwind está bien con su solución corta. – eumiro

+0

Solo quiero señalar que este código está tomado de la clase de Criptografía de Stanford en Coursera. El cartel original no se dio cuenta, pero su problema no estaba con el código. Su problema fue que no reconoció que el intérprete le estaba dando un ASCII que no era inglés en respuesta. –

+0

¿Qué significa "ASCII no inglés"? No hay tal cosa. – alexis

Respuesta

94

Whoa. Realmente estás complicando demasiado por una distancia muy larga. Proveedores:

>>> print hex(0x12ef^0xabcd) 
0xb922 

usted parece estar haciendo caso omiso de estos hechos a mano, por lo menos:

  • Python tiene soporte nativo para literales enteros hexadecimales, con el 0x prefijo.
  • "Hexadecimal" es solo un detalle de presentación; la aritmética se hace en binario, y luego el resultado se imprime como hexadecimal.
  • No existe conexión entre el formato de las entradas (los literales hexadecimales) y el resultado, no existe un "número hexadecimal" en una variable de Python.
  • La función hex() se puede utilizar para convertir cualquier número en una cadena hexadecimal para su visualización.

Si ya tiene los números como cadenas, puede utilizar la función int() convertir en números, proporcionando la base esperada (16 para los números hexadecimales):

>>> print int("12ef", 16) 
4874 

Así que se puede hacer de dos conversiones, realizan la XOR, y luego volver a convertir a hexadecimal:

>>> print hex(int("12ef", 16)^int("abcd", 16)) 
0xb922 
+4

Por supuesto, si @pratibha solo tiene literales de cadena, entonces una alternativa es 'hex (int (' 12ef ', 16)^int (' abcd ', 16)) ' –

+0

@unwind, el segundo número debe ser 0xabcd, de ahí la respuesta esperada de 0xB922. – DaV

+0

hola, gracias por responder. sin embargo, lo conseguí trabajando de la siguiente manera: – pratibha

10

Si las dos cadenas hexagonales tienen la misma longitud y que desea una salida de cadena hexadecimal entonces usted podría tratar 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)]) 
3

aquí 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)])]) 
+7

Parece el código exacto de una de las asignaciones del curso Crypto 1 en Coursera. ;) –

3

Si las cadenas son de la misma longitud, entonces me gustaría ir para '%x' %() de la incorporada en el XOR (^).

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 son de la misma longitud, truncar la cadena más larga que la longitud de la más corta usando una rebanada longer = longer[:len(shorter)]

1

con fines rendimiento, aquí hay un poco de código de referencia 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.