mirror of
https://github.com/Smaug123/ClassicalCiphers.jl
synced 2025-10-05 17:38:48 +00:00
Merge pull request #4 from Smaug123/pull-request/f9777201
Add Portas cipher encryption/decryption
This commit is contained in:
25
README.md
25
README.md
@@ -12,6 +12,7 @@ The Solitaire cipher is included for completeness, though it is perhaps not stri
|
||||
* [Caesar]
|
||||
* [Monoalphabetic substitution]
|
||||
* [Vigenère]
|
||||
* [Portas]
|
||||
* [Solitaire]
|
||||
|
||||
## Gotchas
|
||||
@@ -131,6 +132,28 @@ It returns (key, decrypted text).
|
||||
If the keylength is known, specifying it as `crack_vigenere(str, keylength=6)`
|
||||
may aid decryption.
|
||||
|
||||
### Portas cipher
|
||||
|
||||
Encrypt the text "Hello, World!" with a Portas cipher of key "ab":
|
||||
|
||||
```julia
|
||||
encrypt_portas("Hello, World!", "ab")
|
||||
# outputs "URYYB, JBEYQ!"
|
||||
```
|
||||
|
||||
Note that the input has been made uppercase, but symbols have been preserved.
|
||||
The key is expected to be letters only; it is converted to uppercase and symbols
|
||||
are stripped out before use.
|
||||
|
||||
Decrypt the same text:
|
||||
|
||||
```julia
|
||||
decrypt_portas("URYYB, JBEYQ!", "ab")
|
||||
# outputs "hello, world!"
|
||||
```
|
||||
|
||||
Notice that the input has been made lowercase.
|
||||
|
||||
### Solitaire cipher
|
||||
|
||||
Encrypt the text "Hello, World!" with the Solitaire cipher, key "crypto":
|
||||
@@ -147,8 +170,8 @@ decrypt_solitaire("EXKYI ZSGEH UNTIQ", collect(1:54))
|
||||
# outputs "aaaaaaaaaaaaaaa", as per https://www.schneier.com/code/sol-test.txt
|
||||
```
|
||||
|
||||
|
||||
[Caesar]: https://en.wikipedia.org/wiki/Caesar_cipher
|
||||
[Vigenère]: https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
|
||||
[Monoalphabetic substitution]: https://en.wikipedia.org/wiki/Substitution_cipher
|
||||
[Solitaire]: https://en.wikipedia.org/wiki/Solitaire_(cipher)
|
||||
[Portas]: http://practicalcryptography.com/ciphers/porta-cipher/
|
||||
|
@@ -7,10 +7,12 @@ include("monoalphabetic.jl")
|
||||
include("caesar.jl")
|
||||
include("vigenere.jl")
|
||||
include("solitaire.jl")
|
||||
include("portas.jl")
|
||||
|
||||
export encrypt_monoalphabetic, decrypt_monoalphabetic, crack_monoalphabetic,
|
||||
encrypt_caesar, decrypt_caesar, crack_caesar,
|
||||
encrypt_vigenere, decrypt_vigenere, crack_vigenere,
|
||||
encrypt_portas, decrypt_portas,
|
||||
encrypt_solitaire, decrypt_solitaire,
|
||||
string_fitness, index_of_coincidence
|
||||
|
||||
|
47
src/portas.jl
Normal file
47
src/portas.jl
Normal file
@@ -0,0 +1,47 @@
|
||||
"""
|
||||
Encrypts the given plaintext with the Portas cipher.
|
||||
|
||||
The key must be given as a string, whose characters are letters.
|
||||
|
||||
Converts the text to uppercase.
|
||||
"""
|
||||
function encrypt_portas(plaintext, key_in::AbstractString)
|
||||
key = uppercase(letters_only(key_in))
|
||||
plaintext = uppercase(plaintext)
|
||||
keyarr = [div(Int(ch) - 65, 2) for ch in key]
|
||||
|
||||
keycounter = 1
|
||||
ans = IOBuffer()
|
||||
|
||||
for i in 1:length(plaintext)
|
||||
if ('A' <= plaintext[i] <= 'Z')
|
||||
plainch = Int(plaintext[i]) # 68
|
||||
keych = keyarr[keycounter] # 4
|
||||
if 'Z' >= plaintext[i] >= 'M'
|
||||
print(ans, Char(((plainch - 65 - keych + 13) % 13) + 65))
|
||||
else
|
||||
print(ans, Char(((plainch - 65 + keych) % 13) + 65+13))
|
||||
end
|
||||
|
||||
keycounter += 1
|
||||
if keycounter == length(key) + 1
|
||||
keycounter = 1
|
||||
end
|
||||
else
|
||||
print(ans, plaintext[i])
|
||||
end
|
||||
end
|
||||
|
||||
takebuf_string(ans)
|
||||
end
|
||||
|
||||
"""
|
||||
Decrypts the given ciphertext with the Portas cipher.
|
||||
|
||||
The key must be given as a string, whose characters are letters.
|
||||
|
||||
Converts the text to lowercase.
|
||||
"""
|
||||
function decrypt_portas(ciphertext, key::AbstractString)
|
||||
lowercase(encrypt_portas(ciphertext, key))
|
||||
end
|
12
test/portas.jl
Normal file
12
test/portas.jl
Normal file
@@ -0,0 +1,12 @@
|
||||
using ClassicalCiphers
|
||||
using Base.Test
|
||||
|
||||
@test encrypt_portas("DEFENDTHEEASTWALLOFTHECASTLE", "FORTIFICATION") == uppercase("synnjscvrnrlahutukucvryrlany")
|
||||
@test decrypt_portas("synnjscvrnrlahutukucvryrlany", "FORTIFICATION") == lowercase("DEFENDTHEEASTWALLOFTHECASTLE")
|
||||
|
||||
@test decrypt_portas("synnjs cvr nrla hutu ku cvr yrlany!", "FORTIFICATION") == lowercase("DEFEND THE EAST WALL OF THE CASTLE!")
|
||||
|
||||
# doc tests
|
||||
|
||||
@test decrypt_portas("URYYB, JBEYQ!", "ab") == "hello, world!"
|
||||
@test encrypt_portas("Hello, World!", "ab") == "URYYB, JBEYQ!"
|
@@ -1,6 +1,6 @@
|
||||
using ClassicalCiphers
|
||||
|
||||
tests = ["vigenere", "monoalphabetic", "solitaire", "caesar"]
|
||||
tests = ["vigenere", "monoalphabetic", "solitaire", "caesar", "portas"]
|
||||
|
||||
println("Running tests:")
|
||||
|
||||
|
Reference in New Issue
Block a user