异或位串

XOR'ing bitstrings

我正在尝试实现明文的 RC4 encrypt/decrypt,我已经在异或步骤上停留了一段时间。

我的代码如下所示:

def byteXOR(a, b):
    #TODO take two lists of byte string and return a list with the xor product of them
    u = a.split()
    v = b.split()
    print('Fst: \t {}'.format(u))
    print('Snd: \t {} \n'.format(v))

    '''Fill inn 0' if a bit is shorter than the other'''
    for x,y in zip(u, v):
        if len(x) != len(y):
            if len(x) < len(y):
                x.zfill(len(y) - len(x))
            elif len(x) > len(y):
                y.zfill(len(x) - len(y))

    xor = [ord(x) ^ ord(y) for (x, y) in zip(a, b)]
    print('Fst: \t {}'.format(u))
    print('Snd: \t {}'.format(v))
    print('XOR: \t {}'.format(xor))
    return xor

p = "1111 1010001 10111111 11111010 10101011"
q = "1101000 1100101 1101100 1101100 1101111"
byteXOR(p, q)

我得到这个输出:

Fst:     ['1111', '1010001', '10111111', '11111010', '10101011']
Snd:     ['1101000', '1100101', '1101100', '1101100', '1101111'] 

Fst:     ['1111', '1010001', '10111111', '11111010', '10101011']
Snd:     ['1101000', '1100101', '1101100', '1101100', '1101111']
XOR:     [0, 0, 1, 0, 16, 1, 0, 17, 1, 1, 0, 1, 17, 1, 1, 17, 0, 0, 1, 0, 0, 16, 1, 17, 0, 0, 1, 1, 0, 0, 16, 17, 1, 0, 0, 0, 1, 0, 0]

我似乎无法解决的第一个问题是如何确保位串的长度相同, 我使用了内置方法 zfill() 但是当我打印列表时它们没有改变。

我遇到的第二个问题是如何从每个列表中获得第 n 个元素的 XOR 乘积的所需输出,如下所示:

Fst:      ['0001111', '1010001', '10111111', '11111010', '10101011']
Snd:      ['1101000', '1100101', '01101100', '01101100', '01101111']
XOR:      ['0110011', '0110100', '11010011', '10010110', '11000100']

关于 XOR-ing 你需要将 strs 转换为 ints,使用 ^,然后转换为 bin 表示,使其在相应元素之间您可能会使用的列表 map 即:

Fst = ['0001111', '1010001', '10111111', '11111010', '10101011']
Snd = ['1101000', '1100101', '01101100', '01101100', '01101111']
result = list(map(lambda x,y: bin(int(x,2)^int(y,2)), Fst, Snd))
print(result)

输出

['0b1100111', '0b110100', '0b11010011', '0b10010110', '0b11000100']

注意 bin returns 表示以 0b 开头并且数字尽可能少,所以如果你想要没有 0b 的固定宽度你需要抛弃两个第一个字符,然后使用 zfill

final_result = [i[2:].zfill(8) for i in result]
print(final_result)

输出:

['01100111', '00110100', '11010011', '10010110', '11000100']

注意 int 函数的第二个可选参数允许指定数字的基数,它可以是从 236 的任何值。例如:

print(int('FFF',16))

输出:

4095

等等

这对你有用吗?

def byteXOR(a, b):
    u = [int(bits, 2) for bits in a.split()]
    v = [int(bits, 2) for bits in b.split()]
    xor =  [f ^ s for (f, s) in zip(u, v)]
    print(" ".join([bin(bits).replace("0b", "") for bits in xor]))
    return xor

p = "1111 1010001 10111111 11111010 10101011"
q = "1101000 1100101 1101100 1101100 1101111"
byteXOR(p, q)

对于你的第一个问题,str.zfill() returns 一个新字符串,它不会修改原始字符串。因此,您必须将其重新分配给您的变量:

for x,y in zip(u, v):
    if len(x) != len(y):
        if len(x) < len(y):
            x = x.zfill(len(y) - len(x))
        elif len(x) > len(y):
            y = y.zfill(len(x) - len(y))

对于你的第二个问题,你可以将字符串转换为 int() 并传递一个 base=2 参数来表示它的二进制形式。然后,您可以对整数执行 XOR '^',然后使用 bin()

将其转换回二进制字符串
x = '0001111'
y = '1101000'

x = int(x, base=2)
y = int(y, base=2)

z = str(bin(x ^ y))[2:]  # remove the trailing 0b from the string
print(z)

输出:

1100111

话虽这么说,因为 int(string, base=2) 将字符串转换为整数,你真的不需要先 zfill() 个字节,你可以使用 zip() 在一行如下:

p = "1111 1010001 10111111 11111010 10101011"
q = "1101000 1100101 1101100 1101100 1101111"

r = [bin(int(x, base=2) ^ int(y, base=2))[2:].zfill(8) for x, y in zip(p.split(' '), q.split(' '))]

print(' '.join(r))

输出:

01100111 00110100 11010011 10010110 11000100