Simple Cryptosystems (jl)


using Plots
using StatsBase

function GetNum(X,n=1)
    local Rx
    function BuildRegEx(n)
        n<=1 && return Regex("([a-z])")
        Regex("([a-z])\\s."*BuildRegEx(n-1).pattern)
    end
    Rx=BuildRegEx(n)
    countmap([join(m.captures)
              for m in eachmatch(Rx,lowercase(X))])
end

function GenSubst(X)
    local alpha, state
    alpha = collect('a':'z')
    state=Dict{Char,Char}()
    for x in 1:length(alpha)
        state[alpha[x]]=X[x]
    end
    return m->state[m]
end

function GenInvSubst(X)
    local alpha, state
    alpha = collect('a':'z')
    state=Dict{Char,Char}()
    for x in 1:length(alpha)
        state[X[x]]=alpha[x]
    end
    return m->state[m]
end

function ApplySubst(σ)
    m->join( [σ(x) for x in m ] )
end

function EncodeMono(m,K)
    σ=GenSubst(K)
    ApplySubst(σ)(lowercase(filter(isletter,m)))
end

function DecodeMono(m,K)
    θ=GenInvSubst(K)
    ApplySubst(θ)(lowercase(filter(isletter,m)))
end

function CaesarSub(x)
    GenSubst(join(x:'z')*join('a':(x-1)))
end

function CaesarInvSub(x)
    GenInvSubst(join(x:'z')*join('a':(x-1)))
end

function EncodeCaesar(m,K)
    σ=CaesarSub(K)
    ApplySubst(σ)(lowercase(filter(isletter,m)))
end

function DecodeCaesar(m,K)
    θ=CaesarInvSub(K)
    ApplySubst(θ)(lowercase(filter(isletter,m)))
end

function PolySubst(m,K)
    local m0
    local c
    c=""
    m0=lowercase(filter(isletter,m))
    for i in 1:length(m0)
        σ=CaesarSub(K[mod1(i,length(K))])
        c=c*σ(m0[i])
    end
    join(c)
end

function PolyInvSubst(m,K)
    local m0
    local c
    c=""
    m0=lowercase(filter(isletter,m))
    for i in 1:length(m0)
        σ=CaesarInvSub(K[mod1(i,length(K))])
        c=c*σ(m0[i])
    end
    join(c)
end

function κ(m)
    local m0
    local d
    local fr
    fr=GetNum(m)
    d::Float64=sum(values(fr))
    sum([ i*(i-1)/(d*(d-1)) for i::Float64 in values(fr) ])
end

function computeIk(m,tgt=20)
    local r
    r=[]
    for i in 1:tgt
        push!(r, κ(m[1:i:end]))
    end
    r
end

function findLen(m)
    gcd(sortperm(computeIk(m),rev=true)[1:3])
end