Je voudrais effectuer une exclusivité de bitwise ou de deux chaînes en python, mais xor de chaînes ne sont pas autorisés en python. Comment puis-je le faire ?
Vous pouvez convertir les caractères en entiers et xor ceux-ci à la place:
l = [ord(a) ^ ord(b) for a,b in Zip(s1,s2)]
Voici une fonction mise à jour au cas où vous auriez besoin d'une chaîne à la suite du XOR:
def sxor(s1,s2):
# convert strings to a list of character pair tuples
# go through each Tuple, converting them to ASCII code (ord)
# perform exclusive or on the ASCII code
# then convert the result back to ASCII (chr)
# merge the resulting array of characters as a string
return ''.join(chr(ord(a) ^ ord(b)) for a,b in Zip(s1,s2))
Regardez le travail en ligne: ideone
Si vous voulez utiliser des octets ou des mots, vous feriez mieux d'utiliser le type de tableau de Python au lieu d'une chaîne. Si vous travaillez avec des blocs de longueur fixe, vous pourrez peut-être utiliser le format H ou L pour utiliser des mots plutôt que des octets, mais je viens d'utiliser "B" pour cet exemple:
>>> import array
>>> a1 = array.array('B', 'Hello, World!')
>>> a1
array('B', [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33])
>>> a2 = array.array('B', ('secret'*3))
>>> for i in range(len(a1)):
a1[i] ^= a2[i]
>>> a1.tostring()
';\x00\x0f\x1e\nXS2\x0c\x00\t\x10R'
Pour les bytearrays, vous pouvez directement utiliser XOR:
>>> b1 = bytearray("test123")
>>> b2 = bytearray("321test")
>>> b = bytearray(len(b1))
>>> for i in range(len(b1)):
... b[i] = b1[i] ^ b2[i]
>>> b
bytearray(b'GWB\x00TAG')
Voici votre chaîne XOR'er, probablement pour une forme de cryptage légère:
>>> src = "Hello, World!"
>>> code = "secret"
>>> xorWord = lambda ss,cc: ''.join(chr(ord(s)^ord(c)) for s,c in Zip(ss,cc*100))
>>> encrypt = xorWord(src, code)
>>> encrypt
';\x00\x0f\x1e\nXS2\x0c\x00\t\x10R'
>>> decrypt = xorWord(encrypt,code)
>>> print decrypt
Hello, World!
Notez que ceci est une forme de chiffrement extrêmement faible. Regardez ce qui se passe quand une chaîne vide à encoder:
>>> codebreak = xorWord(" ", code)
>>> print codebreak
SECRET
la doublure pour python3 est:
def bytes_xor(a, b) :
return bytes(x ^ y for x, y in Zip(a, b))
où a
, b
et la valeur renvoyée sont bytes()
au lieu de str()
of course
ça ne peut pas être plus facile, j'adore python3 :)
def strxor (s0, s1):
l = [ chr ( ord (a) ^ ord (b) ) for a,b in Zip (s0, s1) ]
return ''.join (l)
(Basé sur la réponse de Mark Byers.)
Si les chaînes ne sont même pas de même longueur, vous pouvez utiliser ceci
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)])])
Voulez-vous dire quelque chose comme ça:
s1 = '00000001'
s2 = '11111110'
int(s1,2) ^ int(s2,2)
La figure ci-dessous illustre la chaîne XORing s avec m, puis à nouveau pour inverser le processus:
>>> s='hello, world'
>>> m='markmarkmark'
>>> s=''.join(chr(ord(a)^ord(b)) for a,b in Zip(s,m))
>>> s
'\x05\x04\x1e\x07\x02MR\x1c\x02\x13\x1e\x0f'
>>> s=''.join(chr(ord(a)^ord(b)) for a,b in Zip(s,m))
>>> s
'hello, world'
>>>
def xor_strings(s1, s2):
max_len = max(len(s1), len(s2))
s1 += chr(0) * (max_len - len(s1))
s2 += chr(0) * (max_len - len(s2))
return ''.join([chr(ord(c1) ^ ord(c2)) for c1, c2 in Zip(s1, s2)])
J'ai trouvé que la méthode '' .join (chr (ord (a) ^ ord (b))) pour a, b dans Zip (s, m)) est assez lente. Au lieu de cela, j'ai fait ceci:
fmt = '%dB' % len(source)
s = struct.unpack(fmt, source)
m = struct.unpack(fmt, xor_data)
final = struct.pack(fmt, *(a ^ b for a, b in izip(s, m)))
D'après la réponse de William McBrine, voici une solution pour les chaînes de longueur fixe qui est 9% plus rapide pour mon cas d'utilisation:
import itertools
import struct
def make_strxor(size):
def strxor(a, b, izip=itertools.izip, pack=struct.pack, unpack=struct.unpack, fmt='%dB' % size):
return pack(fmt, *(a ^ b for a, b in izip(unpack(fmt, a), unpack(fmt, b))))
return strxor
strxor_3 = make_strxor(3)
print repr(strxor_3('foo', 'bar'))