ADFGVX密码
本示例考察了ADFGVX密码的实现,ADFGVX密码是德国军队使用的第一次世界大战中最复杂的军事密码之一。
导言
[ADFGVX](https://ru.wikipedia.org/wiki/Шифр_ADFGVX )是德国在第一次世界大战期间使用的替代多边形密码。 它结合了替换密码(使用Polybius表)和换位密码。 加密算法是为高水平的安全性而设计的,使用有限的一组字母进行编码(A,D,F,G,V,X),这有利于无线电传输。 这种密码以长期被认为无法破解而闻名,并且只有法国密码学家Georges Penven才成功破解。
In [ ]:
# Устанавливаем необходимый пакет, если он еще не установлен
import Pkg; Pkg.add("Random")
# Подключаем пакет для генерации случайных чисел и перетасовки
using Random
主要部分
ADFGVX密码的数据结构
首先,我们将定义用于存储所有必要的密码组件的数据结构。:
In [ ]:
"""
struct ADFGVX
Определяет структуру для хранения параметров шифра ADFGVX:
- `polybius`: таблица символов (шифруемый алфавит)
- `pdim`: размер таблицы Полибия (например, 6 для 6x6)
- `key`: ключ транспозиции
- `keylen`: длина ключа
- `alphabet`: алфавит, используемый для кодирования (обычно "ADFGVX")
- `encode`: словарь шифрования (символ -> пара букв)
- `decode`: словарь дешифрования (пара букв -> символ)
"""
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
Out[0]:
ADFGVX结构构造函数
接下来,我们创建一个生成映射表的构造函数,并填写加密和解密字典。:
In [ ]:
"""
ADFGVX(s, k, alph = "ADFGVX")
Конструктор создает объект шифра ADFGVX по данным:
- `s`: строка символов, образующая таблицу Полибия
- `k`: ключ транспозиции
- `alph`: алфавит шифра, по умолчанию "ADFGVX"
"""
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
Out[0]:
加密功能
加密函数将输入的文本转换为密码字母表中的字符序列,然后应用基于密钥的转换。
In [ ]:
"""
encrypt(s::String, k::ADFGVX)
Шифрует строку `s` с помощью объекта `k` типа `ADFGVX`.
"""
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
Out[0]:
解密函数
In [ ]:
"""
decrypt(s::String, k::ADFGVX)
Дешифрует строку `s`, зашифрованную с помощью шифра ADFGVX.
"""
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]
starts = accumulate(+, strides[begin:end-1], init=1)
pushfirst!(starts, 1)
ends = [starts[i] + strides[i] - 1 for i in 1:k.keylen]
# Восстанавливаем столбцы в оригинальном порядке
cols = [chars[starts[i]:ends[i]] for i in originalorder]
# Восстанавливаем строки из столбцов
pairs, nrows = Char[], (length(chars) - 1) ÷ k.keylen + 1
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
Out[0]:
工作示范
生成随机Polybius表和随机密钥
In [ ]:
const POLYBIUS = String(shuffle(collect("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")))
Out[0]:
下载英语词典并选择长度为9的随机匹配密钥
In [ ]:
# Загружаем английский словарь и выбираем случайный подходящий ключ длины 9
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
Out[0]:
创建密码对象
In [ ]:
const SECRETS = ADFGVX(POLYBIUS, KEY)
message = "ATTACKAT1200AM"
Out[0]:
In [ ]:
# Вывод данных на экран
println("Polybius: $POLYBIUS, Key: $KEY\n")
println("Message: $message\n")
# Шифрование сообщения
encoded = encrypt(message, SECRETS)
println("Encoded: $encoded\n")
# Дешифрование сообщения
decoded = decrypt(encoded, SECRETS)
println("Decoded: $decoded\n")
结论
我们已经在Julia中审查并实施了ADFGVX密码,Julia是第一次世界大战中最安全的现场密码之一。 我们已经学会了:
*构建加密表(Polybius表);
*创建替换规则(按字符对加密);
*使用基于键的换位;
*在解密阶段恢复原始消息。
该项目展示了研究现代数据保护系统基础的经典加密方法的重要性。 Julia实现使实验算法和理解它们如何"在引擎盖下"工作变得容易。
该示例是使用[Rosetta代码]的材料开发的(https://rosettacode.org/wiki/ADFGVX_cipher )