XOR cipher
Template:Short description In cryptography, the simple XOR cipher is a type of additive cipher,<ref>Template:Harvnb</ref> an encryption algorithm that operates according to the principles:
- A <math>\oplus</math> 0 = A,
- A <math>\oplus</math> A = 0,
- A <math>\oplus</math> B = B <math>\oplus</math> A,
- (A <math>\oplus</math> B) <math>\oplus</math> C = A <math>\oplus</math> (B <math>\oplus</math> C),
- (B <math>\oplus</math> A) <math>\oplus</math> A = B <math>\oplus</math> 0 = B
For example where <math>\oplus</math> denotes the exclusive disjunction (XOR) operation.Template:Sfn This operation is sometimes called modulus 2 addition (or subtraction, which is identical).<ref>Template:Harvnb</ref> With this logic, a string of text can be encrypted by applying the bitwise XOR operator to every character using a given key. To decrypt the output, merely reapplying the XOR function with the key will remove the cipher.
ExampleEdit
The string "Wiki" (Template:Mono in 8-bit ASCII) can be encrypted with the repeating key Template:Mono as follows:
Template:Mono <math>\oplus</math> Template:Mono = Template:Mono
And conversely, for decryption:
Template:Mono <math>\oplus</math> Template:Mono = Template:Mono
Use and securityEdit
The XOR operator is extremely common as a component in more complex ciphers. By itself, using a constant repeating key, a simple XOR cipher can trivially be broken using frequency analysis. If the content of any message can be guessed or otherwise known then the key can be revealed. Its primary merit is that it is simple to implement, and that the XOR operation is computationally inexpensive. A simple repeating XOR (i.e. using the same key for xor operation on the whole data) cipher is therefore sometimes used for hiding information in cases where no particular security is required. The XOR cipher is often used in computer malware to make reverse engineering more difficult.
If the key is random and is at least as long as the message, the XOR cipher is much more secure than when there is key repetition within a message.<ref>Template:Harvnb</ref> When the keystream is generated by a pseudo-random number generator, the result is a stream cipher. With a key that is truly random, the result is a one-time pad, which is unbreakable in theory.
The XOR operator in any of these ciphers is vulnerable to a known-plaintext attack, since plaintext <math>\oplus</math> ciphertext = key. It is also trivial to flip arbitrary bits in the decrypted plaintext by manipulating the ciphertext. This is called malleability.
Usefulness in cryptographyEdit
The primary reason XOR is so useful in cryptography is because it is "perfectly balanced"; for a given plaintext input 0 or 1, the ciphertext result is equally likely to be either 0 or 1 for a truly random key bit.Template:Sfn
The table below shows all four possible pairs of plaintext and key bits. It is clear that if nothing is known about the key or plaintext, nothing can be determined from the ciphertext alone.Template:Sfn
Plaintext | Key | Ciphertext |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Other logical operations such and AND or OR do not have such a mapping (for example, AND would produce three 0's and one 1, so knowing that a given ciphertext bit is a 0 implies that there is a 2/3 chance that the original plaintext bit was a 0, as opposed to the ideal 1/2 chance in the case of XOR)Template:Efn
Example implementationEdit
Example using the Python programming language.Template:Efn <syntaxhighlight lang="python"> from os import urandom
def generate_key(length: int) -> bytes:
"""Generate encryption key.""" return urandom(length)
def xor_strings(s, t) -> bytes:
"""Concatenate xor two strings together.""" if isinstance(s, str): # Text strings contain single characters return "".join(chr(ord(a) ^ b) for a, b in zip(s, t)).encode("utf8") else: # Bytes objects contain integer values in the range 0-255 return bytes([a ^ b for a, b in zip(s, t)])
message = "This is a secret message"
print("Message:", message)
key = generate_key(len(message)) print("Key:", key)
cipherText = xor_strings(message.encode("utf8"), key) print("cipherText:", cipherText) print("decrypted:", xor_strings(cipherText, key).decode("utf8"))
- Verify
if xor_strings(cipherText, key).decode("utf8") == message:
print("Unit test passed")
else:
print("Unit test failed")
</syntaxhighlight>
A shorter example using the R programming language, based on a puzzle posted on Instagram by GCHQ. <syntaxhighlight lang="R"> secret_key <- c(0xc6, 0xb5, 0xca, 0x01) |> as.raw()
secret_message <- "I <3 Wikipedia" |>
charToRaw() |> xor(secret_key) |> base64enc::base64encode()
secret_message_bytes <- secret_message |>
base64enc::base64decode()
xor(secret_message_bytes, secret_key) |> rawToChar() </syntaxhighlight>
See alsoEdit
ReferencesEdit
NotesEdit
CitationsEdit
SourcesEdit
- Template:Cite journal
- Template:Citation
- Template:Cite journal
- Template:Cite journal
- Template:Cite journal
- Template:Cite book
- Template:Citation
- Template:Citation Transcript of a lecture given by Prof. Tutte at the University of Waterloo