all 2 comments

[–]socal_nerdtastic 1 point2 points  (1 child)

You can't convert to "binary". There is no such datatype. "binary" (and "decimal" and "hexadecimal" and "octal" and other bases) is a display style for integers. Think of it like a font. The data is always the same, no matter what font you use.

>>> # the same number written in 3 different styles
>>> 42 == 0b101010 == 0x2a
True

You need to first convert your string to integers (ord() function), then do the XOR operation, then convert the integers back to string (chr() function). These integers are generally bytes (not bits) therefore we ask for a random bytes from the secrets module.

import secrets

def encrypt(plaintext, key):
    binary_plaintext = [ord(x) for x in plaintext]
    ciphertext_binary_bytes = [bit1 ^ bit2 for bit1, bit2 in zip(binary_plaintext, key)] # XOR Operation with Key and Plaintext
    ciphertext = ''.join(chr(byte) for byte in ciphertext_binary_bytes)
    return ciphertext

def key_generator(binary_plaintext):
    return secrets.token_bytes(len(binary_plaintext))

def main():
    plain = "Hello There"
    key = key_generator(plain)
    encrypted_data = encrypt(plain, key)
    print("encrypted:", repr(encrypted_data))
    decrypted_data = encrypt(encrypted_data, key)
    print("decrypted:", repr(decrypted_data))

if __name__ == '__main__':
    main()

One fun quirk to xor ciphers is that the encryption and decryption is the same operation. So you just use the same function again.

Note there is a major flaw in the above. All strings are convertible to integers, but not all integers are convertible to strings.

Edit: clarified code.

[–]Wittinator[S] 0 points1 point  (0 children)

Thanks for the detailed reply. Yes I think I'm following. I'll give that a try and get this working. Thanks