2012-06-20 12 views
32

come possiamo noi numeri esadecimale XOR in python es. Voglio xor 'ABCD' a '12EF'. la risposta dovrebbe essere B922.XOR bit a bit di numeri esadecimali in pitone

ho usato sotto codice, ma sta tornando valore immondizia

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 un suggerimento per 'zip': lo fa lo stripping dell'argomento più automaticamente. Ad ogni modo, @unwind ha ragione con la sua soluzione breve. – eumiro

+0

Voglio solo far notare che questo codice è preso dalla classe di crittografia di Stanford su Coursera. Il poster originale non se ne rese conto, ma il suo problema non era con il codice. Il suo problema era che non riconosceva che l'interprete gli dava ASCII non inglese in risposta. –

+0

Che cosa significa "ASCII non inglese"? Non c'è niente del genere. – alexis

risposta

94

Whoa. Lo stai davvero complicando troppo a lungo. Prova:

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

È sembrano ignorare questi fatti a portata di mano, almeno:

  • Python ha il supporto nativo per letterali interi esadecimali, con il prefisso 0x.
  • "Esadecimale" è solo un dettaglio di presentazione; l'aritmetica viene eseguita in binario e quindi il risultato viene stampato come esadecimale.
  • Non c'è collegamento tra il formato degli ingressi (i letterali esadecimali) e l'uscita, non v'è alcuna cosa come un "numero esadecimale" in una variabile Python.
  • La funzione hex() può essere utilizzato per convertire qualsiasi numero in una stringa esadecimale per la visualizzazione.

Se si hanno già i numeri come stringhe, è possibile utilizzare la funzione int() da convertire in numeri, fornendo la base previsto (16 per i numeri esadecimali):

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

Così si può fare due conversioni, eseguono la XOR, e poi di nuovo a convertire esadecimale:

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

Ovviamente se @pratibha ha solo stringhe letterali, un'alternativa è 'hex (int (' 12ef ', 16)^int (' abcd ', 16)) ' –

+0

@unwind, il secondo numero dovrebbe essere 0xabcd, quindi la risposta prevista di 0xB922. – DaV

+0

ciao, grazie per la risposta. tuttavia ho funzionato come di seguito: – pratibha

10

Se le due stringhe esadecimali sono della stessa lunghezza e si desidera un'uscita stringa esadecimale allora si potrebbe provare questo.

 
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

ecco una migliore funzione

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

Sembra il codice esatto da uno dei compiti in corso Crypto 1 su Coursera. ;) –

3

Se le stringhe sono della stessa lunghezza, quindi vorrei andare per '%x' %() del built-in xor (^).

Esempi -

>>>a = '290b6e3a' 
>>>b = 'd6f491c5' 
>>>'%x' % (int(a,16)^int(b,16)) 
'ffffffff' 
>>>c = 'abcd' 
>>>d = '12ef' 
>>>'%x' % (int(a,16)^int(b,16)) 
'b922' 

Se le stringhe non sono la stessa lunghezza, troncare la stringa più lungo per la lunghezza del più breve con una fetta longer = longer[:len(shorter)]

1

fini delle prestazioni, ecco un po 'di codice al benchmark queste due alternative:

#!/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') 

Ecco i risultati:

Time-it 100k iterations : 
    hexxorA: 8.139988073991844s 
    hexxorB: 0.240523161992314s 

Sembra che '%x' % (int(a,16)^int(b,16)) sia più veloce della versione zip.