Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
3
Task/ADFGVX-cipher/00-META.yaml
Normal file
3
Task/ADFGVX-cipher/00-META.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/ADFGVX_cipher
|
||||
note: Encryption
|
||||
24
Task/ADFGVX-cipher/00-TASK.txt
Normal file
24
Task/ADFGVX-cipher/00-TASK.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
;Description
|
||||
The [https://en.wikipedia.org/wiki/ADFGVX_cipher ADFGVX cipher] was a manually applied field cipher used by the German Army during World War I. It was broken in 1918 by the French cryptanalyst [https://en.wikipedia.org/wiki/Georges_Painvin Georges Painvin].
|
||||
|
||||
The workings of the cipher are described in the Wikipedia article, linked to above, and so will not be repeated here.
|
||||
|
||||
;Task
|
||||
|
||||
Write routines, functions etc. in your language to:
|
||||
|
||||
1. Encrypt ''suitable'' plaintext and decrypt the resulting cipher text using the ADFGVX cipher algorithm given a Polybius square (see 2. below) and a ''suitable'' key. For this purpose ''suitable'' means text consisting solely of ASCII upper case letters or digits.
|
||||
|
||||
2. Create a 6 x 6 [https://en.wikipedia.org/wiki/Polybius_square Polybius square] using a random combination of the letters A to Z and the digits 0 to 9 and then display it.
|
||||
|
||||
3. Given the number of letters (between 7 and 12 say) to use, create a key by selecting a ''suitable'' word at random from [http://wiki.puzzlers.org/pub/wordlists/unixdict.txt unixdict.txt] and then display it. The word selected should be such that none of its characters are repeated.
|
||||
|
||||
Use these routines to create a Polybius square and a 9 letter key.
|
||||
|
||||
These should then be used to encrypt the plaintext: '''ATTACKAT1200AM''' and decrypt the resulting cipher text. Display here the results of both operations.
|
||||
|
||||
;Note
|
||||
|
||||
As it's unclear from the Wikipedia article how to handle a final row with fewer elements than the number of characters in the key, either of the methods mentioned in [https://en.wikipedia.org/wiki/Transposition_cipher#Columnar_transposition Columnar transposition] may be used. In the case of the second method, it is also acceptable to fill any gaps after shuffling by moving elements to the left which makes decipherment harder.
|
||||
<br><br>
|
||||
|
||||
67
Task/ADFGVX-cipher/11l/adfgvx-cipher.11l
Normal file
67
Task/ADFGVX-cipher/11l/adfgvx-cipher.11l
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
V adfgvx = ‘ADFGVX’
|
||||
|
||||
F encrypt(plainText, polybius, key)
|
||||
V s = ‘’
|
||||
L(ch) plainText
|
||||
L(r) 6
|
||||
L(c) 6
|
||||
I polybius[r][c] == ch
|
||||
s ‘’= :adfgvx[r]‘’:adfgvx[c]
|
||||
|
||||
DefaultDict[Char, String] cols
|
||||
L(ch) s
|
||||
cols[key[L.index % key.len]] ‘’= ch
|
||||
|
||||
V result = ‘’
|
||||
L(k) sorted(cols.keys())
|
||||
I !result.empty
|
||||
result ‘’= ‘ ’
|
||||
result ‘’= cols[k]
|
||||
R result
|
||||
|
||||
F decrypt(cipherText, polybius, key)
|
||||
V skey = sorted(key)
|
||||
V cols = [‘’] * key.len
|
||||
V idx = 0
|
||||
L(col) cipherText.split(‘ ’)
|
||||
cols[key.findi(skey[idx])] = col
|
||||
idx++
|
||||
|
||||
V s = ‘’
|
||||
L(i) 0 .< key.len
|
||||
L(col) cols
|
||||
I i < col.len
|
||||
s ‘’= col[i]
|
||||
|
||||
V result = ‘’
|
||||
L(i) (0 .< s.len - 1).step(2)
|
||||
V r = :adfgvx.findi(s[i])
|
||||
V c = :adfgvx.findi(s[i + 1])
|
||||
result ‘’= polybius[r][c]
|
||||
R result
|
||||
|
||||
V polybius = [[Char("\0")] * 6] * 6
|
||||
V alphabet = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789’
|
||||
random:shuffle(&alphabet)
|
||||
L(r) 6
|
||||
L(c) 6
|
||||
polybius[r][c] = alphabet[6 * r + c]
|
||||
|
||||
print("6 x 6 Polybius square:\n")
|
||||
print(‘ | A D F G V X’)
|
||||
print(‘---------------’)
|
||||
L(row) polybius
|
||||
print(adfgvx[L.index]‘ | ’row.join(‘ ’))
|
||||
|
||||
V words = File(‘unixdict.txt’).read().split("\n").filter(w -> w.len == 9 & w.len == Set(Array(w)).len)
|
||||
V key = random:choice(words).uppercase()
|
||||
print("\nThe key is "key)
|
||||
|
||||
V PlainText = ‘ATTACKAT1200AM’
|
||||
print("\nPlaintext : "PlainText)
|
||||
|
||||
V cipherText = encrypt(PlainText, polybius, key)
|
||||
print("\nEncrypted : "cipherText)
|
||||
|
||||
V plainText = decrypt(cipherText, polybius, key)
|
||||
print("\nDecrypted : "plainText)
|
||||
17
Task/ADFGVX-cipher/F-Sharp/adfgvx-cipher.fs
Normal file
17
Task/ADFGVX-cipher/F-Sharp/adfgvx-cipher.fs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// ADFGVX cipher. Nigel Galloway: August 23rd., 2021
|
||||
let polybus=let n=[|yield! {'A'..'Z'}; yield! {'0'..'9'}|] in MathNet.Numerics.Combinatorics.GeneratePermutation 36|>Array.map(fun g->n.[g]),[|'A';'D';'F';'G';'V';'X'|]
|
||||
let printPolybus(a,g)=printf " "; g|>Array.iter(printf "%c "); printfn ""; printfn " ----------------"
|
||||
g|>Array.iteri(fun n g->printf " %c|" g; [0..5]|>List.iter(fun g->printf " %c " (Array.item(n*6+g) a)); printfn "")
|
||||
let c2p n g=let g=(fst>>(Array.findIndex((=) g))) n in let (n:char[])=(snd n) in [|n.[g/n.Length];n.[g%n.Length]|]
|
||||
let p2c n (g:char[])=Array.item(let n=snd n in (Array.findIndex((=)g.[0]) n)*n.Length+(Array.findIndex((=)g.[1]) n))(fst n)
|
||||
let fN(g:string)=let e,d=let n=g|>Seq.sort|>List.ofSeq in (g|>Seq.mapi(fun i l->(List.findIndex((=)l)n)-i)|>Array.ofSeq,n|>Seq.mapi(fun i l->(Seq.findIndex((=)l)g)-i)|>Array.ofSeq)
|
||||
(fun i->i+(e.[i%g.Length])),(fun i->i+(d.[i%g.Length]))
|
||||
let ADFGVX n (g:string)=let pE,pD=fN g
|
||||
(fun(s:string)->let a,b=s|>Seq.collect(c2p n)|>Array.ofSeq|>Array.splitAt(2*s.Length-(2*s.Length)%g.Length)
|
||||
Array.append(Array.permute(pE) a)(Array.permute(fst(fN(g.[..b.Length-1]))) b)|>System.String),
|
||||
(fun(s:string)->let a,b=s.ToCharArray()|>Array.splitAt(s.Length-(s.Length)%g.Length)
|
||||
Array.append(Array.permute(pD) a)(Array.permute(snd(fN(g.[..b.Length-1]))) b)|>Array.chunkBySize 2|>Array.map(p2c n)|>System.String)
|
||||
|
||||
printPolybus polybus
|
||||
let encrypt,decrypt=ADFGVX polybus "nigel" //Using "nigel" as the key no hacker will guess that!
|
||||
let n=encrypt "ATTACKAT1200AM" in printfn $"\nATTACKAT1200AM encrypted is %s{n} which decrypted is %s{decrypt n}"
|
||||
183
Task/ADFGVX-cipher/Go/adfgvx-cipher.go
Normal file
183
Task/ADFGVX-cipher/Go/adfgvx-cipher.go
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var adfgvx = "ADFGVX"
|
||||
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
func distinct(bs []byte) []byte {
|
||||
var u []byte
|
||||
for _, b := range bs {
|
||||
if !bytes.Contains(u, []byte{b}) {
|
||||
u = append(u, b)
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
func allAsciiAlphaNum(word []byte) bool {
|
||||
for _, b := range word {
|
||||
if !((b >= 48 && b <= 57) || (b >= 65 && b <= 90) || (b >= 97 && b <= 122)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func orderKey(key string) []int {
|
||||
temp := make([][2]byte, len(key))
|
||||
for i := 0; i < len(key); i++ {
|
||||
temp[i] = [2]byte{key[i], byte(i)}
|
||||
}
|
||||
sort.Slice(temp, func(i, j int) bool { return temp[i][0] < temp[j][0] })
|
||||
res := make([]int, len(key))
|
||||
for i := 0; i < len(key); i++ {
|
||||
res[i] = int(temp[i][1])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func createPolybius() []string {
|
||||
temp := []byte(alphabet)
|
||||
rand.Shuffle(36, func(i, j int) {
|
||||
temp[i], temp[j] = temp[j], temp[i]
|
||||
})
|
||||
alphabet = string(temp)
|
||||
fmt.Println("6 x 6 Polybius square:\n")
|
||||
fmt.Println(" | A D F G V X")
|
||||
fmt.Println("---------------")
|
||||
p := make([]string, 6)
|
||||
for i := 0; i < 6; i++ {
|
||||
fmt.Printf("%c | ", adfgvx[i])
|
||||
p[i] = alphabet[6*i : 6*(i+1)]
|
||||
for _, c := range p[i] {
|
||||
fmt.Printf("%c ", c)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func createKey(n int) string {
|
||||
if n < 7 || n > 12 {
|
||||
log.Fatal("Key should be within 7 and 12 letters long.")
|
||||
}
|
||||
bs, err := ioutil.ReadFile("unixdict.txt")
|
||||
if err != nil {
|
||||
log.Fatal("Error reading file")
|
||||
}
|
||||
words := bytes.Split(bs, []byte{'\n'})
|
||||
var candidates [][]byte
|
||||
for _, word := range words {
|
||||
if len(word) == n && len(distinct(word)) == n && allAsciiAlphaNum(word) {
|
||||
candidates = append(candidates, word)
|
||||
}
|
||||
}
|
||||
k := string(bytes.ToUpper(candidates[rand.Intn(len(candidates))]))
|
||||
fmt.Println("\nThe key is", k)
|
||||
return k
|
||||
}
|
||||
|
||||
func encrypt(polybius []string, key, plainText string) string {
|
||||
temp := ""
|
||||
outer:
|
||||
for _, ch := range []byte(plainText) {
|
||||
for r := 0; r <= 5; r++ {
|
||||
for c := 0; c <= 5; c++ {
|
||||
if polybius[r][c] == ch {
|
||||
temp += fmt.Sprintf("%c%c", adfgvx[r], adfgvx[c])
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
colLen := len(temp) / len(key)
|
||||
// all columns need to be the same length
|
||||
if len(temp)%len(key) > 0 {
|
||||
colLen++
|
||||
}
|
||||
table := make([][]string, colLen)
|
||||
for i := 0; i < colLen; i++ {
|
||||
table[i] = make([]string, len(key))
|
||||
}
|
||||
for i := 0; i < len(temp); i++ {
|
||||
table[i/len(key)][i%len(key)] = string(temp[i])
|
||||
}
|
||||
order := orderKey(key)
|
||||
cols := make([][]string, len(key))
|
||||
for i := 0; i < len(key); i++ {
|
||||
cols[i] = make([]string, colLen)
|
||||
for j := 0; j < colLen; j++ {
|
||||
cols[i][j] = table[j][order[i]]
|
||||
}
|
||||
}
|
||||
res := make([]string, len(cols))
|
||||
for i := 0; i < len(cols); i++ {
|
||||
res[i] = strings.Join(cols[i], "")
|
||||
}
|
||||
return strings.Join(res, " ")
|
||||
}
|
||||
|
||||
func decrypt(polybius []string, key, cipherText string) string {
|
||||
colStrs := strings.Split(cipherText, " ")
|
||||
// ensure all columns are same length
|
||||
maxColLen := 0
|
||||
for _, s := range colStrs {
|
||||
if len(s) > maxColLen {
|
||||
maxColLen = len(s)
|
||||
}
|
||||
}
|
||||
cols := make([][]string, len(colStrs))
|
||||
for i, s := range colStrs {
|
||||
var ls []string
|
||||
for _, c := range s {
|
||||
ls = append(ls, string(c))
|
||||
}
|
||||
if len(s) < maxColLen {
|
||||
cols[i] = make([]string, maxColLen)
|
||||
copy(cols[i], ls)
|
||||
} else {
|
||||
cols[i] = ls
|
||||
}
|
||||
}
|
||||
table := make([][]string, maxColLen)
|
||||
order := orderKey(key)
|
||||
for i := 0; i < maxColLen; i++ {
|
||||
table[i] = make([]string, len(key))
|
||||
for j := 0; j < len(key); j++ {
|
||||
table[i][order[j]] = cols[j][i]
|
||||
}
|
||||
}
|
||||
temp := ""
|
||||
for i := 0; i < len(table); i++ {
|
||||
temp += strings.Join(table[i], "")
|
||||
}
|
||||
plainText := ""
|
||||
for i := 0; i < len(temp); i += 2 {
|
||||
r := strings.IndexByte(adfgvx, temp[i])
|
||||
c := strings.IndexByte(adfgvx, temp[i+1])
|
||||
plainText = plainText + string(polybius[r][c])
|
||||
}
|
||||
return plainText
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
plainText := "ATTACKAT1200AM"
|
||||
polybius := createPolybius()
|
||||
key := createKey(9)
|
||||
fmt.Println("\nPlaintext :", plainText)
|
||||
cipherText := encrypt(polybius, key, plainText)
|
||||
fmt.Println("\nEncrypted :", cipherText)
|
||||
plainText2 := decrypt(polybius, key, cipherText)
|
||||
fmt.Println("\nDecrypted :", plainText2)
|
||||
}
|
||||
4
Task/ADFGVX-cipher/J/adfgvx-cipher-1.j
Normal file
4
Task/ADFGVX-cipher/J/adfgvx-cipher-1.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
polybius=: {{6 6$8 u:({~?~&#)(48+i.10),65+i.26}}
|
||||
lenword=: {{ ;({~ ?@#)(#~ (-:~.)@>)(#~ y=#@>)cutLF fread'unixdict.txt'}}
|
||||
ADFGVX=: {{ deb,' ',.n/:~|:(-#n)]\'ADFGVX'{~,($m)#:(,m)i.y([-.-.),m }}
|
||||
XVGFDA=: {{ (,m){~($m)#.'ADFGVX'i._2]\deb,|:(>cut y)/:/:n }}
|
||||
13
Task/ADFGVX-cipher/J/adfgvx-cipher-2.j
Normal file
13
Task/ADFGVX-cipher/J/adfgvx-cipher-2.j
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
echo W=: lenword 9
|
||||
roughcast
|
||||
echo P=: polybius ''
|
||||
PV5M6Q
|
||||
KR0391
|
||||
4ZS7LA
|
||||
FUT28E
|
||||
GXOBYW
|
||||
ICJDNH
|
||||
echo E=: P ADFGVX W 'ATTACKAT1200AM'
|
||||
FFF FGF FFF GXD XDG FDGG XDX XXA GAD
|
||||
echo D=: P XVGFDA W E
|
||||
ATTACKAT1200AM
|
||||
6
Task/ADFGVX-cipher/J/adfgvx-cipher-3.j
Normal file
6
Task/ADFGVX-cipher/J/adfgvx-cipher-3.j
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
spaces=: {{deb y#inv~,0,.(/:n){*|:_9]\>:i.#y=.y-.' '}}
|
||||
|
||||
echo S=: E-.' '
|
||||
FFFFGFFFFGXDXDGFDGGXDXXXAGAD
|
||||
P spaces W S
|
||||
FFF FGF FFF GXD XDG FDGG XDX XXA GAD
|
||||
71
Task/ADFGVX-cipher/Julia/adfgvx-cipher.julia
Normal file
71
Task/ADFGVX-cipher/Julia/adfgvx-cipher.julia
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"""
|
||||
The ADFGVX cipher.
|
||||
See also eg. https://www.nku.edu/~christensen/092hnr304%20ADFGVX.pdf
|
||||
"""
|
||||
|
||||
using Random
|
||||
|
||||
""" The WWI German ADFGVX cipher. """
|
||||
struct ADFGVX
|
||||
polybius::Vector{Char}
|
||||
pdim::Int
|
||||
key::Vector{Char}
|
||||
keylen::Int
|
||||
alphabet::Vector{Char}
|
||||
encode::Dict{Char, Vector{Char}}
|
||||
decode::Dict{Vector{Char}, Char}
|
||||
end
|
||||
|
||||
""" ADFGVX constructor, takes 2 strings, option for third string if polybius len != 36 """
|
||||
function ADFGVX(s, k, alph = "ADFGVX")
|
||||
poly = collect(uppercase(s))
|
||||
pdim = isqrt(length(poly))
|
||||
al = collect(uppercase(alph))
|
||||
enco::Dict = Dict([(poly[(i - 1) * pdim + j] => [al[i], al[j]])
|
||||
for i in 1:pdim, j in 1:pdim])
|
||||
deco = Dict(last(p) => first(p) for p in enco)
|
||||
@assert pdim^2 == length(poly) && pdim == length(al)
|
||||
return ADFGVX(poly, pdim, collect(uppercase(k)), length(k), al, enco, deco)
|
||||
end
|
||||
|
||||
""" Encrypt with the ADFGVX cipher. """
|
||||
function encrypt(s::String, k::ADFGVX)
|
||||
chars = reduce(vcat, [k.encode[c] for c in
|
||||
filter(c -> c in k.polybius, collect(uppercase(s)))])
|
||||
colvecs = [lett => chars[i:k.keylen:length(chars)] for (i, lett) in enumerate(k.key)]
|
||||
sort!(colvecs, lt = (x, y) -> first(x) < first(y))
|
||||
return String(mapreduce(p -> last(p), vcat, colvecs))
|
||||
end
|
||||
|
||||
""" Decrypt with the ADFGVX cipher. Does not depend on spacing of encoded text """
|
||||
function decrypt(s::String, k::ADFGVX)
|
||||
chars = filter(c -> c in k.alphabet, collect(uppercase(s)))
|
||||
sortedkey = sort(collect(k.key))
|
||||
order = [findfirst(c -> c == ch, k.key) for ch in sortedkey]
|
||||
originalorder = [findfirst(c -> c == ch, sortedkey) for ch in k.key]
|
||||
a, b = divrem(length(chars), k.keylen)
|
||||
strides = [a + (b >= i ? 1 : 0) for i in order] # shuffled column lengths
|
||||
starts = accumulate(+, strides[begin:end-1], init=1) # shuffled starts of columns
|
||||
pushfirst!(starts, 1) # starting index
|
||||
ends = [starts[i] + strides[i] - 1 for i in 1:k.keylen] # shuffled ends of columns
|
||||
cols = [chars[starts[i]:ends[i]] for i in originalorder] # get reordered columns
|
||||
pairs, nrows = Char[], (length(chars) - 1) ÷ k.keylen + 1 # recover the rows
|
||||
for i in 1:nrows, j in 1:k.keylen
|
||||
(i - 1) * k.keylen + j > length(chars) && break
|
||||
push!(pairs, cols[j][i])
|
||||
end
|
||||
return String([k.decode[[pairs[i], pairs[i + 1]]] for i in 1:2:length(pairs)-1])
|
||||
end
|
||||
|
||||
const POLYBIUS = String(shuffle(collect("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")))
|
||||
const KEY = read("unixdict.txt", String) |>
|
||||
v -> split(v, r"\s+") |>
|
||||
v -> filter(w -> (n = length(w); n == 9 && n == length(unique(collect(w)))), v) |>
|
||||
shuffle |> first |> uppercase
|
||||
const SECRETS, message = ADFGVX(POLYBIUS, KEY), "ATTACKAT1200AM"
|
||||
println("Polybius: $POLYBIUS, Key: $KEY")
|
||||
println("Message: $message")
|
||||
encoded = encrypt(message, SECRETS)
|
||||
decoded = decrypt(encoded, SECRETS)
|
||||
println("Encoded: $encoded")
|
||||
println("Decoded: $decoded")
|
||||
101
Task/ADFGVX-cipher/Nim/adfgvx-cipher.nim
Normal file
101
Task/ADFGVX-cipher/Nim/adfgvx-cipher.nim
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import algorithm, random, sequtils, strutils, sugar, tables
|
||||
|
||||
const Adfgvx = "ADFGVX"
|
||||
|
||||
type PolybiusSquare = array[6, array[6, char]]
|
||||
|
||||
|
||||
iterator items(p: PolybiusSquare): (int, int, char) =
|
||||
## Yield Polybius square characters preceded by row and column numbers.
|
||||
for r in 0..5:
|
||||
for c in 0..5:
|
||||
yield (r, c, p[r][c])
|
||||
|
||||
|
||||
proc initPolybiusSquare(): PolybiusSquare =
|
||||
## Initialize a 6x6 Polybius square.
|
||||
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
alphabet.shuffle()
|
||||
for r in 0..5:
|
||||
for c in 0..5:
|
||||
result[r][c] = alphabet[6 * r + c]
|
||||
|
||||
|
||||
proc createKey(n: Positive): string =
|
||||
## Create a key using a word from "unixdict.txt".
|
||||
doAssert n in 7..12, "Key should be within 7 and 12 letters long."
|
||||
let candidates = collect(newSeq):
|
||||
for word in "unixdict.txt".lines:
|
||||
if word.len == n and
|
||||
word.deduplicate().len == n and
|
||||
word.allCharsInSet(Letters + Digits): word
|
||||
result = candidates[rand(candidates.high)].toUpperAscii
|
||||
|
||||
|
||||
func encrypt(plainText: string; polybius: PolybiusSquare; key: string): string =
|
||||
## Encrypt "plaintext" using the given Polybius square and the given key.
|
||||
|
||||
# Replace characters by row+column letters.
|
||||
var str: string
|
||||
for ch in plainText:
|
||||
for (r, c, val) in polybius:
|
||||
if val == ch:
|
||||
str.add Adfgvx[r] & Adfgvx[c]
|
||||
|
||||
# Build ordered table of columns and sort it by key value.
|
||||
var cols: OrderedTable[char, string]
|
||||
for i, ch in str:
|
||||
let tkey = key[i mod key.len]
|
||||
cols.mgetOrPut(tkey, "").add ch
|
||||
cols.sort(cmp)
|
||||
|
||||
# Build cipher text from sorted column table values.
|
||||
for s in cols.values:
|
||||
result.addSep(" ")
|
||||
result.add s
|
||||
|
||||
|
||||
func decrypt(cipherText: string; polybius: PolybiusSquare; key: string): string =
|
||||
## Decrypt "cipherText" using the given Polybius square and the given key.
|
||||
|
||||
# Build list of columns.
|
||||
let skey = sorted(key)
|
||||
var cols = newSeq[string](key.len)
|
||||
var idx = 0
|
||||
for col in cipherText.split(' '):
|
||||
cols[key.find(skey[idx])] = col
|
||||
inc idx
|
||||
|
||||
# Build string of row+column values.
|
||||
var str: string
|
||||
for i in 0..key.high:
|
||||
for col in cols:
|
||||
if i < col.len: str.add col[i]
|
||||
|
||||
# Build plain text from row+column values.
|
||||
for i in countup(0, str.len - 2, 2):
|
||||
let r = Adfgvx.find(str[i])
|
||||
let c = Adfgvx.find(str[i+1])
|
||||
result.add polybius[r][c]
|
||||
|
||||
|
||||
randomize()
|
||||
|
||||
var polybius = initPolybiusSquare()
|
||||
echo "6 x 6 Polybius square:\n"
|
||||
echo " | A D F G V X"
|
||||
echo "---------------"
|
||||
for i, row in polybius:
|
||||
echo Adfgvx[i], " | ", row.join(" ")
|
||||
|
||||
let key = createKey(9)
|
||||
echo "\nThe key is ", key
|
||||
|
||||
const PlainText = "ATTACKAT1200AM"
|
||||
echo "\nPlaintext : ", PlainText
|
||||
|
||||
let cipherText = PlainText.encrypt(polybius, key)
|
||||
echo "\nEncrypted : ", cipherText
|
||||
|
||||
let plainText = cipherText.decrypt(polybius, key)
|
||||
echo "\nDecrypted : ", plainText
|
||||
51
Task/ADFGVX-cipher/Perl/adfgvx-cipher.pl
Normal file
51
Task/ADFGVX-cipher/Perl/adfgvx-cipher.pl
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict; # https://rosettacode.org/wiki/ADFGVX_cipher
|
||||
use warnings;
|
||||
use List::Util qw( shuffle );
|
||||
|
||||
my $plaintext = 'ATTACKAT1200AM';
|
||||
my $keysize = 9;
|
||||
|
||||
my $polybius = <<END;
|
||||
| A D F G V X
|
||||
--+------------
|
||||
A | x x x x x x
|
||||
D | x x x x x x
|
||||
F | x x x x x x
|
||||
G | x x x x x x
|
||||
V | x x x x x x
|
||||
X | x x x x x x
|
||||
END
|
||||
$polybius =~ s/x/$_/ for my @letters = shuffle "A" .. 'Z' , 0 .. 9;
|
||||
print "Polybius square =\n\n$polybius\n";
|
||||
my %char2pair;
|
||||
@char2pair{ @letters } = glob '{A,D,F,G,V,X}' x 2; # map chars to pairs
|
||||
my %pair2char = reverse %char2pair; # map pairs to chars
|
||||
my ($keyword) = shuffle grep !/(.).*\1/,
|
||||
do { local (@ARGV, $/) = 'unixdict.txt'; <> =~ /^.{$keysize}$/gm };
|
||||
my ($n, @deorder) = 0;
|
||||
my @reorder = map /.(.+)/, sort map $_ . $n++, split //, $keyword;
|
||||
@deorder[@reorder] = 0 .. $#reorder;
|
||||
print " keyword = $keyword\n\nplaintext = $plaintext\n\n";
|
||||
|
||||
my $encoded = encode( $plaintext, \%char2pair, \@reorder );
|
||||
print " encoded = $encoded\n\n";
|
||||
|
||||
my $decoded = decode( $encoded, \%pair2char, \@deorder );
|
||||
print " decoded = $decoded\n";
|
||||
|
||||
sub encode
|
||||
{
|
||||
my ($plain, $c2p, $order) = @_;
|
||||
my $len = @$order;
|
||||
join ' ', (transpose( $plain =~ s/./$c2p->{$&}/gr =~ /.{1,$len}/g ))[@$order];
|
||||
}
|
||||
|
||||
sub decode
|
||||
{
|
||||
my ($encoded, $p2c, $order) = @_;
|
||||
(join '', transpose((split ' ', $encoded)[@$order])) =~ s/../$p2c->{$&}/gr;
|
||||
}
|
||||
|
||||
sub transpose { map join('', map {s/.// ? $& : ''} @_), 1 .. length $_[0] }
|
||||
74
Task/ADFGVX-cipher/Phix/adfgvx-cipher.phix
Normal file
74
Task/ADFGVX-cipher/Phix/adfgvx-cipher.phix
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">ADFGVX</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ADFGVX"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">ALEPH</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">)&</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'9'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">create_polybius</span><span style="color: #0000FF;">()</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">aleph</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ALEPH</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000080;font-style:italic;">-- string aleph = "U1CNHFEM4RSGPI8965X2ZB7KA3YVOD0WQTJL" -- Nim
|
||||
-- string aleph = "T71VB5HYG2JKIQM8REOPDUNCZ063FXAW9S4L" -- Wren
|
||||
-- string aleph = "NA1C3H8TB2OME5WRPD4F6G7I9J0KLQSUVXYZ" -- wp</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aleph</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">),</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"6 x 6 Polybius square:\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" | A D F G V X\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"---------------\n"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s | %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">ADFGVX</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">aleph</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">lnua</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">n</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">unique</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">))==</span><span style="color: #000000;">n</span>
|
||||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"in"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ALEPH</span><span style="color: #0000FF;">))==</span><span style="color: #000000;">n</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">create_key</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">7</span> <span style="color: #008080;">and</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">12</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">candidates</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">upper</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">unix_dict</span><span style="color: #0000FF;">()),</span><span style="color: #000000;">lnua</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">candidates</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">candidates</span><span style="color: #0000FF;">))]</span>
|
||||
<span style="color: #000080;font-style:italic;">-- string res = "PHAGOCYTE" -- Nim
|
||||
-- string res = "SUNFLOWER" -- Wren
|
||||
-- string res = "PRIVACY" -- wp</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nThe key is %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">encrypt</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">polybius</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">plaintext</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tags</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">polybius</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (simply ignore any non-alphanum)</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ADFGVX</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">6</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]&</span>
|
||||
<span style="color: #000000;">ADFGVX</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">((</span><span style="color: #000000;">k</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">6</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">),</span><span style="color: #000000;">tags</span><span style="color: #0000FF;">,</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">)),</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">decrypt</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">polybius</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">key</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">encrypted</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tags</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">encrypted</span><span style="color: #0000FF;">,</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">),{},</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">apply</span><span style="color: #0000FF;">(</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">extract</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">tags</span><span style="color: #0000FF;">},</span><span style="color: #004600;">true</span><span style="color: #0000FF;">}),</span><span style="color: #008000;">""</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">plaintext</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">ADFGVX</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">ADFGVX</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">plaintext</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">polybius</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">*</span><span style="color: #000000;">6</span><span style="color: #0000FF;">+</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">plaintext</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">polybius</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_polybius</span><span style="color: #0000FF;">(),</span>
|
||||
<span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_key</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">plaintext</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ATTACKAT1200AM"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">encrypted</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">encrypt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">polybius</span><span style="color: #0000FF;">,</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">decrypted</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">decrypt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">polybius</span><span style="color: #0000FF;">,</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">encrypted</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nPlainText : %s\n\nEncrypted : %s\n\nDecrypted : %s\n"</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">plaintext</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">encrypted</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">decrypted</span><span style="color: #0000FF;">})</span>
|
||||
<!--
|
||||
66
Task/ADFGVX-cipher/Python/adfgvx-cipher.py
Normal file
66
Task/ADFGVX-cipher/Python/adfgvx-cipher.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
"""
|
||||
The ADFGVX cipher implemented as a Python class
|
||||
See also eg. https://www.nku.edu/~christensen/092hnr304%20ADFGVX.pdf
|
||||
"""
|
||||
|
||||
from random import shuffle, choice
|
||||
from itertools import product, accumulate
|
||||
from numpy import floor, sqrt
|
||||
|
||||
class ADFGVX:
|
||||
""" The WWI German ADFGVX cipher. """
|
||||
def __init__(self, spoly, k, alph='ADFGVX'):
|
||||
self.polybius = list(spoly.upper())
|
||||
self.pdim = int(floor(sqrt(len(self.polybius))))
|
||||
self.key = list(k.upper())
|
||||
self.keylen = len(self.key)
|
||||
self.alphabet = list(alph)
|
||||
pairs = [p[0] + p[1] for p in product(self.alphabet, self.alphabet)]
|
||||
self.encode = dict(zip(self.polybius, pairs))
|
||||
self.decode = dict((v, k) for (k, v) in self.encode.items())
|
||||
|
||||
def encrypt(self, msg):
|
||||
""" Encrypt with the ADFGVX cipher. """
|
||||
chars = list(''.join([self.encode[c] for c in msg.upper() if c in self.polybius]))
|
||||
colvecs = [(lett, chars[i:len(chars):self.keylen]) \
|
||||
for (i, lett) in enumerate(self.key)]
|
||||
colvecs.sort(key=lambda x: x[0])
|
||||
return ''.join([''.join(a[1]) for a in colvecs])
|
||||
|
||||
def decrypt(self, cod):
|
||||
""" Decrypt with the ADFGVX cipher. Does not depend on spacing of encoded text """
|
||||
chars = [c for c in cod if c in self.alphabet]
|
||||
sortedkey = sorted(self.key)
|
||||
order = [self.key.index(ch) for ch in sortedkey]
|
||||
originalorder = [sortedkey.index(ch) for ch in self.key]
|
||||
base, extra = divmod(len(chars), self.keylen)
|
||||
strides = [base + (1 if extra > i else 0) for i in order] # shuffled column lengths
|
||||
starts = list(accumulate(strides[:-1], lambda x, y: x + y)) # shuffled starts of columns
|
||||
starts = [0] + starts # starting index
|
||||
ends = [starts[i] + strides[i] for i in range(self.keylen)] # shuffled ends of columns
|
||||
cols = [chars[starts[i]:ends[i]] for i in originalorder] # get reordered columns
|
||||
pairs = [] # recover the rows
|
||||
for i in range((len(chars) - 1) // self.keylen + 1):
|
||||
for j in range(self.keylen):
|
||||
if i * self.keylen + j < len(chars):
|
||||
pairs.append(cols[j][i])
|
||||
|
||||
return ''.join([self.decode[pairs[i] + pairs[i + 1]] for i in range(0, len(pairs), 2)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
PCHARS = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
|
||||
shuffle(PCHARS)
|
||||
POLYBIUS = ''.join(PCHARS)
|
||||
with open('unixdict.txt') as fh:
|
||||
WORDS = [w for w in (fh.read()).split() \
|
||||
if len(w) == 9 and len(w) == len(set(list(w)))]
|
||||
KEY = choice(WORDS)
|
||||
|
||||
SECRET, MESSAGE = ADFGVX(POLYBIUS, KEY), 'ATTACKAT1200AM'
|
||||
print(f'Polybius: {POLYBIUS}, key: {KEY}')
|
||||
print('Message: ', MESSAGE)
|
||||
ENCODED = SECRET.encrypt(MESSAGE)
|
||||
DECODED = SECRET.decrypt(ENCODED)
|
||||
print('Encoded: ', ENCODED)
|
||||
print('Decoded: ', DECODED)
|
||||
118
Task/ADFGVX-cipher/REXX/adfgvx-cipher.rexx
Normal file
118
Task/ADFGVX-cipher/REXX/adfgvx-cipher.rexx
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/* REXX */
|
||||
cls
|
||||
eol=x2c(0D0A) ; msg="ATTACKAT1200AM"
|
||||
keyword= upper('lifeguard') ; cyph= 'ADFGVX'
|
||||
|
||||
s_sort= keyword ; new_key= ''
|
||||
do while length(s_sort) > 0
|
||||
nmax= 0
|
||||
do i=1 to length(s_sort)
|
||||
ch= substr(s_sort,i,1)
|
||||
num= c2d(ch)
|
||||
if num > nmax then do
|
||||
nmax= num
|
||||
max_i = i
|
||||
end
|
||||
end
|
||||
s_sort= delstr(s_sort,max_i,1)
|
||||
new_key= d2c(nmax)||new_key
|
||||
end /* Alphabetical sorting */
|
||||
|
||||
j=0 ; num_str= '' ; rnd_s= ''
|
||||
do while j < 36
|
||||
num= random(0,35)
|
||||
if wordpos(num,num_str) = 0 then do
|
||||
j= j + 1
|
||||
num_str= num_str||num||' '
|
||||
if num >= 10 then do
|
||||
num= num - 10 + x2d(41)
|
||||
num= d2c(num)
|
||||
end
|
||||
rnd_s= rnd_s||num
|
||||
end
|
||||
end /* say 'Generated string: '||rnd_s||eol */
|
||||
|
||||
say 'Polybius square:'||eol
|
||||
call tab cyph, rnd_s ,1
|
||||
say "Only characters from the '"|| msg||"'"||eol
|
||||
t= translate(rnd_s,' ',msg)
|
||||
_t= translate(rnd_s,' ',t)
|
||||
call tab cyph, _t ,1
|
||||
|
||||
len_c= length(cyph) ; cyph_T=''
|
||||
do i=1 to len_c
|
||||
ch_i= substr(cyph,i,1)
|
||||
do j=1 to len_c
|
||||
ch_j= substr(cyph,j,1)
|
||||
cyph_T= cyph_T||ch_i||ch_j||' '
|
||||
end
|
||||
end
|
||||
|
||||
enc_msg= ''
|
||||
do i=1 to length(msg)
|
||||
ch= substr(msg,i,1)
|
||||
j= pos(ch,rnd_s,1)
|
||||
enc_msg= enc_msg||word(cyph_T,j)
|
||||
end
|
||||
|
||||
say "Conversion by table: "||eol||eol||msg||" ==> "||enc_msg||eol
|
||||
call tab keyword, enc_msg
|
||||
|
||||
len= length(keyword)
|
||||
n_row= 0 ; column.= ''
|
||||
do while enc_msg <> ''
|
||||
parse var enc_msg 1 s1 +(len) enc_msg
|
||||
n_row= n_row+1
|
||||
do m= 1 to len
|
||||
ch_m= substr(s1,m,1)
|
||||
column.m= column.m||ch_m
|
||||
end
|
||||
end
|
||||
|
||||
s_lst= ''
|
||||
do m= 1 to len
|
||||
ch= substr(new_key,m,1)
|
||||
i= pos(ch,keyword,1)
|
||||
w_i= column.i
|
||||
s_lst= s_lst||w_i||' '
|
||||
end
|
||||
|
||||
row.= '' ; t_row= ''
|
||||
do i=1 to len
|
||||
w_i= word(s_lst,i)
|
||||
do j=1 to n_row
|
||||
row.j= row.j||substr(w_i,j,1)
|
||||
end
|
||||
end
|
||||
do j=1 to n_row; t_row= t_row||row.j; end
|
||||
|
||||
say "Sorted by columns:"||eol
|
||||
call tab new_key, t_row
|
||||
|
||||
say '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
|
||||
say 'Encrypted message: '||s_lst
|
||||
say '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
|
||||
|
||||
exit
|
||||
tab:
|
||||
parse arg h, s, p /* header, string, param */
|
||||
|
||||
lh= length(h) ;
|
||||
s= h||copies('-',lh)||s ; ls= length(s)
|
||||
h=' -'||h
|
||||
|
||||
t= '' ; j= 1
|
||||
do i= 1 to ls by lh
|
||||
row= substr(s,i,lh)
|
||||
r_ch= ''
|
||||
do l=1 to lh
|
||||
ch= substr(row,l,1)
|
||||
r_ch= r_ch||ch||' '
|
||||
end
|
||||
row= r_ch
|
||||
if p <> '' then row= row||'|'||substr(h,j,1)
|
||||
t= t||row||eol
|
||||
j= j + 1
|
||||
end
|
||||
say t
|
||||
return
|
||||
33
Task/ADFGVX-cipher/Raku/adfgvx-cipher.raku
Normal file
33
Task/ADFGVX-cipher/Raku/adfgvx-cipher.raku
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
srand 123456; # For repeatability
|
||||
|
||||
my @header = < A D F G V X >;
|
||||
my $polybius = (flat 'A'..'Z', 0..9).pick(*).join;
|
||||
|
||||
my $key-length = 9;
|
||||
my $key = uc 'unixdict.txt'.IO.words.grep( { (.chars == $key-length) && (+.comb.Set == +.comb) } ).roll;
|
||||
|
||||
my %cypher = (@header X~ @header) Z=> $polybius.comb;
|
||||
|
||||
my $message = 'Attack at 1200AM';
|
||||
|
||||
use Terminal::Boxer;
|
||||
say "Key: $key\n";
|
||||
say "Polybius square:\n", ss-box :7col, :3cw, :indent("\t"), '', |@header, |(@header Z $polybius.comb.batch: 6);
|
||||
say "Message to encode: $message";
|
||||
say "\nEncoded: " ~ my $encoded = encode $message;
|
||||
say "\nDecoded: " ~ decode $encoded;
|
||||
|
||||
sub encode ($text is copy) {
|
||||
$text = $text.uc.comb(/<[A..Z 0..9]>/).join;
|
||||
my @order = $key.comb.pairs.sort( *.value )».key;
|
||||
my @encode = %cypher.invert.hash{ $text.comb }.join.comb.batch($key-length).map: { [$_] };
|
||||
((^$key-length).map: { @encode».[@order]».grep( *.defined )».[$_].grep( *.defined ).join }).Str;
|
||||
}
|
||||
|
||||
sub decode ($text is copy) {
|
||||
my @text = $text.split(' ')».comb;
|
||||
my $chars = @text[0].chars;
|
||||
$_ = flat |$_, ' ' if .chars < $chars for @text;
|
||||
my @order = $key.comb.pairs.sort( *.value )».key.pairs.sort( *.value )».key;
|
||||
%cypher{ ( grep { /\w/ }, flat [Z] @order.map( { |@text.batch($key-length)».[$_] } ) ).batch(2)».join }.join;
|
||||
}
|
||||
104
Task/ADFGVX-cipher/Wren/adfgvx-cipher.wren
Normal file
104
Task/ADFGVX-cipher/Wren/adfgvx-cipher.wren
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import "random" for Random
|
||||
import "/ioutil" for FileUtil
|
||||
import "/seq" for Lst
|
||||
import "/str" for Char, Str
|
||||
|
||||
var rand = Random.new()
|
||||
var adfgvx = "ADFGVX"
|
||||
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toList
|
||||
|
||||
var createPolybius = Fn.new {
|
||||
rand.shuffle(alphabet)
|
||||
var p = Lst.chunks(alphabet, 6)
|
||||
System.print("6 x 6 Polybius square:\n")
|
||||
System.print(" | A D F G V X")
|
||||
System.print("---------------")
|
||||
for (i in 0...p.count) {
|
||||
System.write("%(adfgvx[i]) | ")
|
||||
System.print(p[i].join(" "))
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
var createKey = Fn.new { |n|
|
||||
if (n < 7 || n > 12) Fiber.abort("Key should be within 7 and 12 letters long.")
|
||||
var candidates = FileUtil.readLines("unixdict.txt").where { |word|
|
||||
return word.count == n && Lst.distinct(word.toList).count == n &&
|
||||
word.all { |ch| Char.isAsciiAlphaNum(ch) }
|
||||
}.toList
|
||||
var k = Str.upper(candidates[rand.int(candidates.count)])
|
||||
System.print("\nThe key is %(k)")
|
||||
return k
|
||||
}
|
||||
|
||||
// helper function to sort the key into alphabetical order
|
||||
// and return a list of the original indices of its letters.
|
||||
var orderKey = Fn.new { |key|
|
||||
var temp = (0...key.count).map { |i| [key[i], i] }.toList
|
||||
temp.sort { |x, y| x[0].bytes[0] < y[0].bytes[0] }
|
||||
return temp.map { |e| e[1] }.toList
|
||||
}
|
||||
|
||||
var encrypt = Fn.new { |polybius, key, plainText|
|
||||
var temp = ""
|
||||
for (ch in plainText) {
|
||||
var outer = false
|
||||
for (r in 0..5) {
|
||||
for (c in 0..5) {
|
||||
if (polybius[r][c] == ch) {
|
||||
temp = temp + adfgvx[r] + adfgvx[c]
|
||||
outer = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (outer) break
|
||||
}
|
||||
}
|
||||
var colLen = (temp.count / key.count).floor
|
||||
// all columns need to be the same length
|
||||
if (temp.count % key.count > 0) colLen = colLen + 1
|
||||
var table = Lst.chunks(temp.toList, key.count)
|
||||
var lastLen = table[-1].count
|
||||
if (lastLen < key.count) table[-1] = table[-1] + ([""] * (key.count - lastLen))
|
||||
var order = orderKey.call(key)
|
||||
var cols = List.filled(key.count, null)
|
||||
for (i in 0...cols.count) {
|
||||
cols[i] = List.filled(colLen, null)
|
||||
for (j in 0...table.count) cols[i][j] = table[j][order[i]]
|
||||
}
|
||||
return cols.map { |col| col.join() }.join(" ")
|
||||
}
|
||||
|
||||
var decrypt = Fn.new { |polybius, key, cipherText|
|
||||
var colStrs = cipherText.split(" ")
|
||||
// ensure all columns are same length
|
||||
var maxColLen = colStrs.reduce(0) { |max, col| max = (col.count > max) ? col.count : max }
|
||||
var cols = colStrs.map { |s|
|
||||
return (s.count < maxColLen) ? s.toList + ([""] * (maxColLen - s.count)) : s.toList
|
||||
}.toList
|
||||
var table = List.filled(maxColLen, null)
|
||||
var order = orderKey.call(key)
|
||||
for (i in 0...maxColLen) {
|
||||
table[i] = List.filled(key.count, "")
|
||||
for (j in 0...key.count) table[i][order[j]] = cols[j][i]
|
||||
}
|
||||
var temp = table.map { |row| row.join("") }.join("")
|
||||
var plainText = ""
|
||||
var i = 0
|
||||
while (i < temp.count) {
|
||||
var r = adfgvx.indexOf(temp[i])
|
||||
var c = adfgvx.indexOf(temp[i+1])
|
||||
plainText = plainText + polybius[r][c]
|
||||
i = i + 2
|
||||
}
|
||||
return plainText
|
||||
}
|
||||
|
||||
var plainText = "ATTACKAT1200AM"
|
||||
var polybius = createPolybius.call()
|
||||
var key = createKey.call(9)
|
||||
System.print("\nPlaintext : %(plainText)")
|
||||
var cipherText = encrypt.call(polybius, key, plainText)
|
||||
System.print("\nEncrypted : %(cipherText)")
|
||||
var plainText2 = decrypt.call(polybius, key, cipherText)
|
||||
System.print("\nDecrypted : %(plainText2)")
|
||||
Loading…
Add table
Add a link
Reference in a new issue