import Base.getindex,Base.inv,Base.*,Base.^
struct Perm
permutation::Array{Integer}
end
const ι=Perm([(i)%26+1 for i in 0:25])
const ρ=Perm([(i+1)%26+1 for i in 0:25])
function (π::Perm)(i::Integer)
π.permutation[i]
end
function (π::Perm)(c::Char)
Char(π(Int(c)-Int('a')+1)+Int('a')-1)
end
function inv(π::Perm)
res=zeros(Integer,length(π.permutation))
for i in 1:length(π.permutation)
res[π(i)]=i
end
Perm(res)
end
function *(π::Perm,ψ::Perm)
Perm([π(ψ(i)) for i in 1:length(π.permutation)])
end
function ^(π::Perm,i::Integer)
i==0 && return ι
i==1 && return π
i>1 && return π*(π^(i-1))
i<0 && return (π^(-1))^i
end
function initSwap(s::String)
res=collect(1:26)
for i in 0:(length(s)÷2-1)
res[Int(s[2*i+1])-Int('a')+1]=Int(s[2*i+2]-Int('a')+1)
res[Int(s[2*i+2])-Int('a')+1]=Int(s[2*i+1]-Int('a')+1)
end
Perm(res)
end
abstract type Swaps end
struct Plugboard <: Swaps
wiring:: Perm
Plugboard(s::String) = new(initSwap(s))
end
struct Reflector <: Swaps
wiring:: Perm
Reflector(s::String) = new(initSwap(s))
end
mutable struct Rotor
wiring:: Perm
pin:: Integer
position:: Integer
end
mutable struct Enigma
rotors:: Array{Rotor}
reflector:: Reflector
plugboard:: Plugboard
end
function Rotor(s::String,pin::Integer=1)
r=[ Int(i)-Int('a')+1 for i in s ]
Rotor(Perm(r),pin,1)
end
function getperm(r::Swaps)
r.wiring
end
function getperm(r::Rotor)
σ=ρ^(r.position-1)
σ*(r.wiring)*σ^-1
end
function rotate!(r::Rotor)
r.position %=26
r.position +=1
r.position==r.pin
end
function set!(r::Rotor,c::Char)
r.position=(Int(c)-Int('a'))%26+1
end
function getperm(E::Enigma)
π=getperm(E.plugboard)
μ=reduce(*,[ getperm(x) for x in reverse(E.rotors) ])
σ=getperm(E.reflector)
π*μ^(-1)*σ*μ*π
end
function step!(E::Enigma)
step=true
for rt in E.rotors
step && (step=rotate!(rt))
end
end
function (E::Enigma)(s::String)
map(s) do c
e=getperm(E)(c)
step!(E)
e
end
end
function setkey!(E::Enigma,s::String)
for x in zip(E.rotors,s)
set!(x[1],x[2])
end
end
RA="qwaszxcderfvbgtyhnmjuiklop"
RB="vpwoeirutyalskdjfhgzmxncbq"
RC="plmkoijnbhuygvcftrdxzsewaq"
Rf="zxcvasdfqwertyghbnmjuiklop"
Pb="alpestvj"
ARotorA=Rotor(RA)
ARotorB=Rotor(RB)
ARotorC=Rotor(RC)
ARef=Reflector(Rf)
APlg=Plugboard(Pb)
AliceEnigma=Enigma([ARotorA,ARotorB,ARotorC],ARef,APlg)
BRotorA=Rotor(RA)
BRotorB=Rotor(RB)
BRotorC=Rotor(RC)
BRef=Reflector(Rf)
BPlg=Plugboard(Pb)
BobEnigma=Enigma([BRotorA,BRotorB,BRotorC],BRef,BPlg)
setkey!(AliceEnigma,"cil")
setkey!(BobEnigma,"cil")
AliceMsg=AliceEnigma("thisisatestmessage")
BobMsg=BobEnigma(AliceMsg)