Search code examples
pythonencryptionxor

xor unsupported operand error in case of using yield instead of return in key generation function


I have a script that take a file and considering its size, (in the following code less than 416 bytes) using series of hash operations, a mask is generated (using keygen function below) to be XORed with the input file (below in cipher function). I want the keys to be generated on demand for better memory efficiency. but in the keygen function when I use yield instead of return my cipher function returns the error:

CD = bytearray((x ^ y for (x, y) in zip(file, key)))
TypeError: unsupported operand type(s) for ^: 'int' and 'bytearray'

here is the code:

from hashlib import md5
def keygen(f, pk): #takes file f as input (here data size is less than 4126bytes)
    ck=bytearray(b'')
    l=len(f)
    if l <= 28*16:
        for i in pk:
            a=md5(i.encode())
            ck += a.digest()
    yield ck

the following function does the encryption:

def cipher(file, key):
    out=bytearray(b'')
    out = bytearray((x ^ y for (x, y) in zip(file, key)))
    return out

at the end of my script I have:

if __name__=='__main__':
    file = bytearray(open('C:\\code\\Test.txt', 'rb').read()) 
    pk = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    key = keygen(file, pk)
    output = cipher(file, key)
    final=open('out.data', 'wb')
    final.write(output)
    final.close()

the whole process works just fine if I use return in keygen function instead of yield, but fails otherwise. I want the keys be generated on demand considering the data size inside the cipher function. but the keygen function seem not to be compatible if I use yield instead of return.

I read the file bytearray format and defined the ck in keygen as bytearray too. in I tried yield bytearray(ck) in keygen but that does not work either.

what point am I missing? How can I generate the keys on-demand considering the data size?


Solution

  • Long story short:

    def keygen(f, pk): #takes file f as input (here data size is less than 4126bytes)
        l=len(f)
        if l <= 28*16:
            for i in pk:
                a=md5(i.encode())
                yield a.digest()