Two-Way Cipher
September 20, 2016
This sounds hard but is actually easy to arrange. We use a one-time pad (that is, a key that is as long as the ciphertext) and an encryption operation that adds and subtracts letters, wrapping around the end of the alphabet.
Consider encryption and decryption as mathematical operations. With P as the plaintext, K as the key, and C as the ciphertext, encryption is P + K = C, where the plus sign performs the encryption operation, and decryption is C – K = P, where the minus sign performs the decryption operation. By rearranging terms, we can easily find the key that corresponds to a given ciphertext and plaintext: C – P = K. And we can find the two different keys that correspond to two different plaintexts as C – P1 = K1 and C – P2 = K2. We begin with the plus and minus operations, which assume that the strings contain only upper-case letters:
(define (plus str1 str2) (list->string (map (lambda (x y) (integer->char (+ (modulo (+ (- (char->integer x) 65) (- (char->integer y) 65)) 26) 65))) (string->list str1) (string->list str2))))
(define (minus str1 str2) (list->string (map (lambda (x y) (integer->char (+ (modulo (- (- (char->integer x) 65) (- (char->integer y) 65)) 26) 65))) (string->list str1) (string->list str2))))
The two plaintext strings are PROGRAMMING and PRAXIS. We have to pad the shorter of the two so both are the same length:
(define plaintext1 "PROGRAMMING") (define plaintext2 "PRAXISXXXXX")
Then we choose a random ciphertext (well, not too random) as long as the longer of the two plaintexts:
(define ciphertext "ABCDEFGHIJK")
Finally, we compute the two keys:
(define key1 (minus ciphertext plaintext1)) (define key2 (minus ciphertext plaintext2))
> key1 "LKOXNFUVAWE" > key2 "LKCGWNJKLMN"
The decryption works in the normal way:
> (minus ciphertext key1) "PROGRAMMING" > (minus ciphertext key2) "PRAXISXXXXX"
You can run the program at http://ideone.com/vAvTa9.
Nice! Reminds me of “angecryption”:
https://events.ccc.de/congress/2014/Fahrplan/events/5930.html
Just leaving a comment would be poor form; here’s my Haskell solution.