diff --git a/README.md b/README.md index e41db2c..a07f479 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ The Solitaire cipher is included for completeness, though it is perhaps not stri * [Enigma (M3 Army)][Enigma] * [Solitaire] * [Rail Fence] -* [Substitution] * [Atbash] ## Gotchas @@ -384,28 +383,6 @@ julia> decrypt_railfence("WECRFACERDSOEE.LETNEAIVDEO", 3) "wearediscovered.fleeatonce" ``` -### Substitution cipher - -```julia -julia> encrypt_substitution("Hello, this is plaintext", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm") -"ITSSG, ZIOL OL HSQOFZTBZ" - -julia> encrypt_substitution("Hello, this is plaintext", "qwertyuiopasdfghjklzxcvbnm") -"ITSSG, ZIOL OL HSQOFZTBZ" - -julia> encrypt_substitution("xyz", Dict('x' => 'd', 'y' => 'e', 'z' => 't')) -"DET" - -julia> decrypt_substitution("ITSSG, ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm", reverse_dict = true) -"hello, this is plaintext" - -julia> encrypt_atbash("some text", "abcdefghijklmnopqrstuvwxyz") -"HLNV GVCG" - -julia> decrypt_atbash("HLNV GVCG", "abcdefghijklmnopqrstuvwxyz") -"some text" -``` - ### Atbash ```julia @@ -422,5 +399,4 @@ encrypt_atbash("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz") == encry [Playfair]: https://en.wikipedia.org/wiki/Playfair_cipher [Enigma]: https://en.wikipedia.org/wiki/Enigma_machine [Rail Fence]: https://en.wikipedia.org/wiki/Rail_fence_cipher -[Substitution]: https://en.wikipedia.org/wiki/Substitution_cipher [Atbash]: https://en.wikipedia.org/wiki/Atbash diff --git a/docs/make.jl b/docs/make.jl index fd4ccb5..6b5d961 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -10,7 +10,7 @@ Documenter.makedocs( sitename = "ClassicalCiphers Documentation", expandfirst = [], pages = [ - "Index" => "index.md", + "Home" => "index.md", "Usage" => "usage.md" ] ) diff --git a/docs/src/index.md b/docs/src/index.md index da429ff..bb76154 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -15,7 +15,6 @@ Currently implemented ciphers: - [Enigma (M3 Army)](https://en.wikipedia.org/wiki/Enigma_machine) - [Solitaire](https://en.wikipedia.org/wiki/Solitaire_(cipher)) - [Rail Fence](https://en.wikipedia.org/wiki/Rail_fence_cipher) - - [Substitution](https://en.wikipedia.org/wiki/Substitution_cipher) - [Atbash](https://en.wikipedia.org/wiki/Atbash) diff --git a/src/ClassicalCiphers.jl b/src/ClassicalCiphers.jl index ffe44e6..9b6ef24 100644 --- a/src/ClassicalCiphers.jl +++ b/src/ClassicalCiphers.jl @@ -13,9 +13,8 @@ include("hill.jl") include("playfair.jl") include("enigma.jl") include("railfence.jl") -include("substitution.jl") -export encrypt_monoalphabetic, decrypt_monoalphabetic, crack_monoalphabetic, +export encrypt_monoalphabetic, decrypt_monoalphabetic, crack_monoalphabetic, encrypt_atbash, decrypt_atbash, encrypt_caesar, decrypt_caesar, crack_caesar, encrypt_affine, decrypt_affine, crack_affine, encrypt_vigenere, decrypt_vigenere, crack_vigenere, @@ -25,7 +24,6 @@ export encrypt_monoalphabetic, decrypt_monoalphabetic, crack_monoalphabetic, encrypt_playfair, decrypt_playfair, encrypt_enigma, decrypt_enigma, string_fitness, index_of_coincidence, - construct_railfence, encrypt_railfence, decrypt_railfence, - encrypt_substitution, decrypt_substitution, encrypt_atbash, decrypt_atbash + construct_railfence, encrypt_railfence, decrypt_railfence end # module diff --git a/src/enigma.jl b/src/enigma.jl index c84fb31..146bba7 100644 --- a/src/enigma.jl +++ b/src/enigma.jl @@ -149,7 +149,7 @@ function encrypt_enigma(plaintext, end # validate reflector settings - reflector = keystr_to_dict(parse_reflector(reflector_id)) + reflector = _keystr_to_dict(parse_reflector(reflector_id)) # sanitise plaintext plaintext = uppercase(letters_only(plaintext)) @@ -162,11 +162,11 @@ function encrypt_enigma(plaintext, "VZBRGITYUPSDNHLXAWMJQOFECK"] notches = Int[17,5,22,10,26] - rotor1 = keystr_to_dict(rotor_layouts[rotors[1]]) + rotor1 = _keystr_to_dict(rotor_layouts[rotors[1]]) notch1 = notches[rotors[1]] - rotor2 = keystr_to_dict(rotor_layouts[rotors[2]]) + rotor2 = _keystr_to_dict(rotor_layouts[rotors[2]]) notch2 = notches[rotors[2]] - rotor3 = keystr_to_dict(rotor_layouts[rotors[3]]) + rotor3 = _keystr_to_dict(rotor_layouts[rotors[3]]) notch3 = notches[rotors[3]] rotor1_inv = Dict{Char, Char}(Pair{Char, Char}[reverse(a) for a in rotor1]) diff --git a/src/monoalphabetic.jl b/src/monoalphabetic.jl index 0671198..802e548 100644 --- a/src/monoalphabetic.jl +++ b/src/monoalphabetic.jl @@ -1,21 +1,45 @@ -function keystr_to_dict(keystr::AbstractString) - return Dict{Char, Char}(map(x -> (Char(x[1] + 64), x[2]), enumerate(uppercase(keystr)))) -end +#= +julia> @btime encrypt_monoalphabetic("THIS CODE WAS INVENTED BY JULIUS CAESAR", "DEFGHIJKLMNOPQRSTUVWXYZABC") + 2.746 μs (21 allocations: 2.31 KiB) +"WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU" -""" +julia> @btime decrypt_monoalphabetic("WKLV FRGH ZDV LQYHQWHG EB MXOLXV FDHVDU", "DEFGHIJKLMNOPQRSTUVWXYZABC") + 3.817 μs (31 allocations: 3.81 KiB) +"this code was invented by julius caesar" +=# + +_keystr_to_dict(keystr::AbstractString) = + Dict{Char, Char}(Char(i + 64) => c for (i, c) in enumerate(uppercase(keystr))) +_keystr_to_dict(A::AbstractString, B::AbstractString) = + Dict{eltype(A), eltype(B)}(a => b for (a, b) in zip(uppercase(A), uppercase(B))) # policy decision: all dictionaries are uppercase +Base.reverse(D::Dict{T, S}) where {T, S} = + Dict{S, T}(reverse(p) for p in D) +_monoalphabetic_substitution(text, sub_dict::Dict{T, S}) where {T, S} = + S[get(sub_dict, c, c) for c in text] + +# if using sub_dict directly, do not convert case +@doc raw""" +Arguably the most simple of the classical ciphers, the substitution cipher works by creating an arbitrary substitution dictionary; e.g., ```julia -encrypt_monoalphabetic(plaintext, key::Dict{Char, Char}) +'a' => 'x' +'b' => 'g' +'c' => 'l' +... +``` +This dictionary then replaces every corresponding letter in the plaintext input with a different letter (as specified by the dictionary input.) + +The function `encrypt_substitution` will either take this dictionary as its second parameter, _or_ it can construct the dictionary itself: +```julia +encrypt_substitution(plaintext, Dict(...)) +encrypt_substitution(plaintext, "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba") # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' +encrypt_substitution(plaintext, "zyxwvutsrqponmlkjihgfedcba") # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' by assuming the keys in the substitution dictionary ``` -Encrypts the given plaintext according to the monoalphabetic substitution cipher. -The key may be given as a Dict of replacements `Dict('a' => 'b', 'c' => 'd')`, etc, -or as a 26-length string "keystringbcdfhjlmopqruvwxz", which is shorthand for -`Dict('a' => 'k', 'e' => 'b', ...)` +*All characters undefined in the dictionary are preserved by default; this includes punctionation, spaces, and cases.* This means that, when using a dictionary, strings are not automatically converted into uppercase. -If the key is given as a string, it is assumed that each character occurs only -once, and the string is converted to lowercase. -If the key is given as a Dict, the only substitutions made are those in the Dict; -in particular, the string is not converted to lowercase automatically. +As per convention, the output will always be uppercase. + +For more information, see [`https://en.wikipedia.org/wiki/Substitution_cipher`](https://en.wikipedia.org/wiki/Substitution_cipher). --- @@ -27,58 +51,70 @@ julia> encrypt_monoalphabetic("Hello, World!", "DEFGHIJKLMNOPQRSTUVWXYZABC") julia> encrypt_monoalphabetic("aBcbDd", Dict{Char, Char}('a' => '5', 'B' => '@', 'b' => 'o')) "5@coDd" + +julia> encrypt_monoalphabetic("Hello, this is plaintext", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm") +"ITSSG, ZIOL OL HSQOFZTBZ" + +julia> encrypt_monoalphabetic("Hello, this is plaintext", "qwertyuiopasdfghjklzxcvbnm") +"ITSSG, ZIOL OL HSQOFZTBZ" + +julia> encrypt_monoalphabetic("xyz", Dict('x' => 'd', 'y' => 'e', 'z' => 't')) +"det" ``` """ -function encrypt_monoalphabetic(plaintext, key::Dict{Char, Char}) - # plaintext: string; key: dictionary of {'a' => 'b'}, etc, for replacing 'a' with 'b' - return join(eltype(keys(key))[get(key, i, i) for i in plaintext]) -end +encrypt_monoalphabetic(plaintext, sub_dict::Dict{T, S}) where {T, S} = + join(_monoalphabetic_substitution(plaintext, sub_dict)) +encrypt_monoalphabetic(plaintext, A, B::AbstractString) = + encrypt_monoalphabetic(uppercase(plaintext), _keystr_to_dict(A, B)) +# Fall back on using english alphabet as keys +encrypt_monoalphabetic(plaintext, B::AbstractString) = + encrypt_monoalphabetic(uppercase(plaintext), _keystr_to_dict(B)) -""" +@doc raw""" +Arguably the most simple of the classical ciphers, the substitution cipher works by creating an arbitrary substitution dictionary; e.g., ```julia -decrypt_monoalphabetic(ciphertext, key::Dict{Char, Char}) +'a' => 'x' +'b' => 'g' +'c' => 'l' +... +``` +This dictionary then replaces every corresponding letter in the plaintext input with a different letter (as specified by the dictionary input.) + +The function `decrypt_substitution` will either take this dictionary as its second parameter, _or_ it can construct the dictionary itself: +```julia +decrypt_substitution(ciphertext, Dict(...); reverse_dict = true) +decrypt_substitution(ciphertext, "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true) # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' +decrypt_substitution(ciphertext, "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true) # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' by assuming the keys in the substitution dictionary ``` -Decrypts the given ciphertext according to the monoalphabetic substitution cipher. -The key may be given as a Dict of replacements `Dict('a' => 'b', 'c' => 'd')`, etc, -or as a 26-length string "keystringbcdfhjlmopqruvwxz", which is shorthand for -`Dict('a' => 'k', 'e' => 'b', ...)` +*All characters undefined in the dictionary are preserved by default; this includes punctionation, spaces, and cases.* This means that, when using a dictionary, strings are not automatically converted into lowercase. -If the key is given as a string, it is assumed that each character occurs only -once, and the string is converted to lowercase. -If the key is given as a Dict, the only substitutions made are those in the Dict; -in particular, the string is not converted to lowercase automatically. +*If `reverse_dict` is set to true (as it is by default), the input dictionary is assumed to be the same used to _en_crypt, meaning it is reversed in order to _decrypt_ the ciphertext.* + +As per convention, the output will always be lowercase. + +For more information, see [`https://en.wikipedia.org/wiki/Substitution_cipher`](https://en.wikipedia.org/wiki/Substitution_cipher). --- ### Examples ```julia +julia> decrypt_monoalphabetic("ITSSG, ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm", reverse_dict = true) +"hello, this is plaintext" + julia> decrypt_monoalphabetic("Khoor, Zruog!", "DEFGHIJKLMNOPQRSTUVWXYZABC") "hello, world!" ``` """ -function decrypt_monoalphabetic(ciphertext, key::Dict{Char, Char}) - # ciphertext: string; key: dictionary of {'a' => 'b'}, etc, where the plaintext 'a' was - # replaced by ciphertext 'b'. No character should appear more than once - # as a value in {key}. - return encrypt_monoalphabetic(ciphertext, Dict{Char, Char}(reverse(a) for a in key)) -end - -function encrypt_monoalphabetic(plaintext, key::AbstractString) - # plaintext: string; key: string of length 26, first character is the image of 'a', etc - # working in lowercase; key is assumed only to have each element appearing once - return encrypt_monoalphabetic(uppercase(plaintext), keystr_to_dict(key)) -end - -function decrypt_monoalphabetic(ciphertext, key::AbstractString) - # ciphertext: string; key: string of length 26, first character is the image of 'a', etc - # working in lowercase; key is assumed only to have each element appearing once - # and to be in lowercase - # so decrypt_monoalphabetic("cb", "cbade…") is "ab" - dict = Dict{Char, Char}(a => Char(96 + findfirst(==(a), lowercase(key))) for a in lowercase(key)) - return encrypt_monoalphabetic(lowercase(ciphertext), dict) +function decrypt_monoalphabetic(ciphertext, sub_dict::Dict{T, S}; reverse_dict::Bool = true) where {T, S} + sub_dict = reverse_dict ? reverse(sub_dict) : sub_dict + return join(_monoalphabetic_substitution(ciphertext, sub_dict)) end +decrypt_monoalphabetic(ciphertext, A, B; reverse_dict::Bool = true) = + lowercase(decrypt_monoalphabetic(uppercase(ciphertext), _keystr_to_dict(A, B); reverse_dict = reverse_dict)) +decrypt_monoalphabetic(ciphertext, B; reverse_dict::Bool = true) = + lowercase(decrypt_monoalphabetic(uppercase(ciphertext), _keystr_to_dict(B); reverse_dict = reverse_dict)) # Cracking @@ -231,3 +267,50 @@ function crack_monoalphabetic( return decrypt_monoalphabetic(ciphertext, key), key end + +""" +```julia +encrypt_atbash(plaintext, alphabet) +``` + +A special case of the substitution cipher, the Atbash cipher substitutes a given alphabet with its reverse: +```julia +encrypt_atbash(plaintext, "abcdefghijklmnopqrstuvwxyz") == encrypt_substitution(plaintext, "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba") +``` + +*Omitting the alphabet, it will assume you are using the English alphabet.* +""" +encrypt_atbash(plaintext, alphabet) = + encrypt_substitution(plaintext, alphabet, reverse(alphabet)) +encrypt_atbash(plaintext) = + encrypt_atbash(plaintext, "abcdefghijklmnopqrstuvwxyz") + +""" +```julia +decrypt_atbash(ciphertext, alphabet) +``` + +A special case of the substitution cipher, the Atbash cipher substitutes a given alphabet with its reverse: +```julia +decrypt_atbash(ciphertext, "abcdefghijklmnopqrstuvwxyz") == decrypt_substitution(ciphertext, "zyxwvutsrqponmlkjihgfedcba", "abcdefghijklmnopqrstuvwxyz") +decrypt_atbash(ciphertext, "abcdefghijklmnopqrstuvwxyz") == decrypt_substitution(ciphertext, "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true) +``` + +*Omitting the alphabet, it will assume you are using the English alphabet.* + +--- + +### Examples + +```julia +julia> encrypt_atbash("some text", "abcdefghijklmnopqrstuvwxyz") +"HLNV GVCG" + +julia> decrypt_atbash("HLNV GVCG", "abcdefghijklmnopqrstuvwxyz") +"some text" +``` +""" +decrypt_atbash(ciphertext, alphabet) = + decrypt_substitution(ciphertext, reverse(alphabet), alphabet) +decrypt_atbash(ciphertext) = + decrypt_atbash(ciphertext, "abcdefghijklmnopqrstuvwxyz") diff --git a/src/substitution.jl b/src/substitution.jl deleted file mode 100644 index 24e3f64..0000000 --- a/src/substitution.jl +++ /dev/null @@ -1,135 +0,0 @@ -construct_sub_dict(A, B) = - Dict{eltype(A), eltype(B)}(a => b for (a, b) in zip(lowercase(A), lowercase(B))) # policy decision: all dictionaries are lowercase -Base.reverse(D::Dict{T, S}) where {T, S} = - Dict{S, T}(reverse(p) for p in D) -something_crypt_substitution(text, sub_dict::Dict{T, S}) where {T, S} = - S[get(sub_dict, c, c) for c in text] - -@doc raw""" -Arguably the most simple of the classical ciphers, the substitution cipher works by creating an arbitrary substitution dictionary; e.g., -```julia -'a' => 'x' -'b' => 'g' -'c' => 'l' -... -``` -This dictionary then replaces every corresponding letter in the plaintext input with a different letter (as specified by the dictionary input.) - -The function `encrypt_substitution` will either take this dictionary as its second parameter, _or_ it can construct the dictionary itself: -```julia -encrypt_substitution(plaintext, Dict(...)) -encrypt_substitution(plaintext, "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba") # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' -encrypt_substitution(plaintext, "zyxwvutsrqponmlkjihgfedcba") # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' by assuming the keys in the substitution dictionary -``` - -*All characters undefined in the dictionary are preserved by default; this includes punctionation and spaces.* - -As per convention, the output will always be uppercase. - -For more information, see [`https://en.wikipedia.org/wiki/Substitution_cipher`](https://en.wikipedia.org/wiki/Substitution_cipher). - ---- - -### Examples - -```julia -julia> encrypt_substitution("Hello, this is plaintext", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm") -"ITSSG, ZIOL OL HSQOFZTBZ" - -julia> encrypt_substitution("Hello, this is plaintext", "qwertyuiopasdfghjklzxcvbnm") -"ITSSG, ZIOL OL HSQOFZTBZ" - -julia> encrypt_substitution("xyz", Dict('x' => 'd', 'y' => 'e', 'z' => 't')) -"DET" -``` -""" -encrypt_substitution(plaintext, sub_dict::Dict{T, S}) where {T, S} = - uppercase(join(something_crypt_substitution(lowercase(plaintext), sub_dict))) -encrypt_substitution(plaintext, A, B) = - encrypt_substitution(plaintext, construct_sub_dict(A, B)) -encrypt_substitution(plaintext, B) = - encrypt_substitution(plaintext, "abcdefghijklmnopqrstuvwxyz", B) - -@doc raw""" -Arguably the most simple of the classical ciphers, the substitution cipher works by creating an arbitrary substitution dictionary; e.g., -```julia -'a' => 'x' -'b' => 'g' -'c' => 'l' -... -``` -This dictionary then replaces every corresponding letter in the plaintext input with a different letter (as specified by the dictionary input.) - -The function `decrypt_substitution` will either take this dictionary as its second parameter, _or_ it can construct the dictionary itself: -```julia -decrypt_substitution(ciphertext, Dict(...); reverse_dict = true) -decrypt_substitution(ciphertext, "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true) # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' -decrypt_substitution(ciphertext, "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true) # this will create the dictionary 'a' => 'z', 'b' => 'y', ..., 'z' => 'a' by assuming the keys in the substitution dictionary -``` - -*All characters undefined in the dictionary are preserved by default; this includes punctionation and spaces.* - -*If `reverse_dict` is set to true (as it is by default), the input dictionary is assumed to be the same used to _en_crypt, meaning it is reversed in order to _decrypt_ the ciphertext.* - -As per convention, the output will always be lowercase. - -For more information, see [`https://en.wikipedia.org/wiki/Substitution_cipher`](https://en.wikipedia.org/wiki/Substitution_cipher). - ---- - -### Examples - -```julia -julia> decrypt_substitution("ITSSG, ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm", reverse_dict = true) -"hello, this is plaintext" - -julia> encrypt_atbash("some text", "abcdefghijklmnopqrstuvwxyz") -"HLNV GVCG" - -julia> decrypt_atbash("HLNV GVCG", "abcdefghijklmnopqrstuvwxyz") -"some text" -``` -""" -function decrypt_substitution(ciphertext, sub_dict::Dict{T, S}; reverse_dict::Bool = true) where {T, S} - sub_dict = reverse_dict ? reverse(sub_dict) : sub_dict - return lowercase(join(something_crypt_substitution(lowercase(ciphertext), sub_dict))) -end -decrypt_substitution(ciphertext, A, B; reverse_dict::Bool = true) = - decrypt_substitution(ciphertext, construct_sub_dict(A, B); reverse_dict = reverse_dict) -decrypt_substitution(ciphertext, B; reverse_dict::Bool = true) = - decrypt_substitution(ciphertext, "abcdefghijklmnopqrstuvwxyz", B; reverse_dict = reverse_dict) - -""" -```julia -encrypt_atbash(plaintext, alphabet) -``` - -A special case of the substitution cipher, the Atbash cipher substitutes a given alphabet with its reverse: -```julia -encrypt_atbash(plaintext, "abcdefghijklmnopqrstuvwxyz") == encrypt_substitution(plaintext, "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba") -``` - -*Omitting the alphabet, it will assume you are using the English alphabet.* -""" -encrypt_atbash(plaintext, alphabet) = - encrypt_substitution(plaintext, alphabet, reverse(alphabet)) -encrypt_atbash(plaintext) = - encrypt_atbash(plaintext, "abcdefghijklmnopqrstuvwxyz") - -""" -```julia -decrypt_atbash(ciphertext, alphabet) -``` - -A special case of the substitution cipher, the Atbash cipher substitutes a given alphabet with its reverse: -```julia -decrypt_atbash(ciphertext, "abcdefghijklmnopqrstuvwxyz") == decrypt_substitution(ciphertext, "zyxwvutsrqponmlkjihgfedcba", "abcdefghijklmnopqrstuvwxyz") -decrypt_atbash(ciphertext, "abcdefghijklmnopqrstuvwxyz") == decrypt_substitution(ciphertext, "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true) -``` - -*Omitting the alphabet, it will assume you are using the English alphabet.* -""" -decrypt_atbash(ciphertext, alphabet) = - decrypt_substitution(ciphertext, reverse(alphabet), alphabet) -decrypt_atbash(ciphertext) = - decrypt_atbash(ciphertext, "abcdefghijklmnopqrstuvwxyz") diff --git a/test/substitution.jl b/test/substitution.jl deleted file mode 100644 index 53d8060..0000000 --- a/test/substitution.jl +++ /dev/null @@ -1,33 +0,0 @@ -using ClassicalCiphers -using Test - -@test encrypt_substitution("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz") == "HELLO THIS IS PLAINTEXT" -@test encrypt_substitution("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz") == "HELLO THIS IS PLAINTEXT" -@test encrypt_substitution("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm") == "ITSSG ZIOL OL HSQOFZTBZ" -@test encrypt_substitution("hello this is plaintext", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz") == "PCSSI EPHL HL JSKHYECUE" -@test encrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz") == "HELLO THIS IS PLAINTEXT" -@test encrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz") != encrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm") -@test encrypt_substitution("hello this is plaintext", Dict('n' => 'y','f' => 'n','w' => 'b','d' => 'm','e' => 'c','o' => 'i','h' => 'p','y' => 'f','i' => 'h','r' => 'd','t' => 'e','s' => 'l','j' => 'q','q' => 'a','k' => 'r','a' => 'k','c' => 'v','p' => 'j','m' => 'z','z' => 't','g' => 'o','x' => 'u','u' => 'g','l' => 's','v' => 'w','b' => 'x')) == "PCSSI EPHL HL JSKHYECUE" -@test encrypt_substitution("hello this is plaintext", Dict('n' => 'f','f' => 'y','w' => 'v','d' => 'r','e' => 't','o' => 'g','h' => 'i','j' => 'p','i' => 'o','k' => 'a','r' => 'k','s' => 'l','t' => 'z','q' => 'j','y' => 'n','a' => 'q','c' => 'e','p' => 'h','m' => 'd','z' => 'm','g' => 'u','v' => 'c','l' => 's','u' => 'x','x' => 'b','b' => 'w')) == "ITSSG ZIOL OL HSQOFZTBZ" - -@test decrypt_substitution("hello this is ciphertext", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz") == "hello this is ciphertext" -@test decrypt_substitution("hello this is ciphertext", "abcdefghijklmnopqrstuvwxyz") == "hello this is ciphertext" -@test decrypt_substitution("hello this is ciphertext", "abcdefghijklmnopqrstuvwxyz"; reverse_dict = true) == "hello this is ciphertext" -@test decrypt_substitution("hello this is ciphertext", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz") == "itssg ziol ol eohitkztbz" -@test decrypt_substitution("hello this is ciphertext", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz"; reverse_dict = false) == "pcssi ephl hl vhjpcdecue" -@test decrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm"; reverse_dict = false) == "ozllu mogs gs iljgymzwm" -@test decrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm"; reverse_dict = true) == "hello this is plaintext" -@test decrypt_substitution("PCSSI EPHL HL JSKHYECUE", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz"; reverse_dict = false) == "jvllh cjps ps qlrpfcvgc" -@test decrypt_substitution("PCSSI EPHL HL JSKHYECUE", "qwertyuiopasdfghjklzxcvbnm", "abcdefghijklmnopqrstuvwxyz"; reverse_dict = true) == "hello this is plaintext" -@test decrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm"; reverse_dict = false) != decrypt_substitution("ITSSG ZIOL OL HSQOFZTBZ", "abcdefghijklmnopqrstuvwxyz", "qwertyuiopasdfghjklzxcvbnm"; reverse_dict = true) - - - - -@test encrypt_atbash("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz") == "SVOOL GSRH RH KOZRMGVCG" -@test encrypt_atbash("hello this is plaintext") == "SVOOL GSRH RH KOZRMGVCG" -@test decrypt_atbash("SVOOL GSRH RH KOZRMGVCG", "abcdefghijklmnopqrstuvwxyz") == "hello this is plaintext" -@test decrypt_atbash("SVOOL GSRH RH KOZRMGVCG") == "hello this is plaintext" -@test encrypt_atbash("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz") == encrypt_substitution("hello this is plaintext", "abcdefghijklmnopqrstuvwxyz", "zyxwvutsrqponmlkjihgfedcba") -@test decrypt_atbash("SVOOL GSRH RH XRKSVIGVCG", "abcdefghijklmnopqrstuvwxyz") == decrypt_substitution("SVOOL GSRH RH XRKSVIGVCG", "zyxwvutsrqponmlkjihgfedcba", "abcdefghijklmnopqrstuvwxyz") -@test decrypt_atbash("SVOOL GSRH RH XRKSVIGVCG", "abcdefghijklmnopqrstuvwxyz") == decrypt_substitution("SVOOL GSRH RH XRKSVIGVCG", "zyxwvutsrqponmlkjihgfedcba"; reverse_dict = true)