Engee 文档
Notebook

置换-重排网络(SP-网络)加密模式

我们以一个理论实例来研究现代加密系统的组织原理。

任务描述

大多数现代信息系统都使用 AES(或类似)密码来加密信息。这些密码基于置换-替换网络算法(SP-network)。

如果你只想对信息进行加密或解密,Julia 有AES.jl 这样的库来对字节序列进行加密和解密。

这里介绍的算法不一定是强密码。通过适当选择 S 和 P 块参数,以及使用更好的函数生成轮密钥并将其添加到密文中,可以使 "强 "密码变得更强。我们只创建了一个训练示例,在某些方面便于分析和改进。

模型概览

基于 SP 网的密码接收一个数据块和一个密钥作为输入,并执行几轮由数据块中比特的交替替换和置换阶段组成的程序。

image.png

In [ ]:
# Загрузим модель, если она еще не открыта на холсте
if "sp_net_cipher_model"  getfield.(engee.get_all_models(), :name)
    engee.load( "$(@__DIR__)/sp_net_cipher_model.engee");
end

model_data = engee.run( "sp_net_cipher_model" );

println( "Количество ошибок передачи: ", convert(Int, model_data["Кол-во ошибок"].value[end]) )
Количество ошибок передачи: 0

接下来,我们将揭开模型的每个区块,看看每一轮是如何工作的。

三轮加密模型

如果扩展每个子系统,就能非常直观地了解每轮算法的工作原理(模型sp_net_cipher_model_3R_expand )。

它可以让你看到每个阶段的设置,并检查如果替换或重新排列块的设置不协调将会发生什么。

image.png

让我们运行这个模型,验证一下用相同的字节传输信息AAAAAAAA 会产生不同的密文字节:

In [ ]:
# Загрузим модель, если она еще не открыта на холсте
if "sp_net_cipher_model_3R_expand"  getfield.(engee.get_all_models(), :name)
    engee.load( "$(@__DIR__)/sp_net_cipher_model_3R_expand.engee");
end

model_data = engee.run( "sp_net_cipher_model_3R_expand" );

source_message = collect(model_data["Блок сообщения"]).value
cipher_text = UInt16.(collect(model_data["Зашифрованный блок"]).value)
received_message = UInt16.(collect(model_data["Расшифрованный блок"]).value)

source_bytes = vcat( reverse.([reinterpret( UInt8, [UInt16(c)]) for c in source_message])... )
cipher_bytes = vcat( reverse.([reinterpret( UInt8, [UInt16(c)]) for c in cipher_text])... )
received_bytes = vcat( reverse.([reinterpret( UInt8, [UInt16(c)]) for c in received_message])... )

println( "Отправленное сообщение: ", join( vcat( string.(source_bytes, base=16)... ), " " ) )
println( "Зашифрованное сообщение: ", join( vcat( string.(cipher_bytes, base=16)... ), " " ))
println( "Полученное сообщение: ", join( vcat( string.(received_bytes, base=16)... ), " " ) )
Отправленное сообщение: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
Зашифрованное сообщение: 3f 73 25 f1 71 65 64 39 d0 4d 3f 96 b2 eb e1 24 3f 73 25 f1 71 65 64 39 d0 4d 3f 96 b2 eb e1 24 3f 73 25 f1 71 65 64 39 d0 4d
Полученное сообщение: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
In [ ]:
println( "Отправленная строка: ", String( source_bytes ))
println( "Полученная строка: ", String( received_bytes ))

请注意,密文从第 17 个区块开始重复。

一轮密码模式

如果我们将网络简化为一轮,模型如下:

image.png

我们看到了所有熟悉的 SP 网络元素:

  • 将密钥比特与明文比特 (XOR) 混合的功能、
  • 将比特 (Bool) 向量作为输入的替换块、
  • 比特置换块,将前一个操作的四个组合结果向量作为输入。

如果 S 块和 P 块的所有参数设置正确,我们就能在输出端得到与输入端相同的信息。

In [ ]:
# Загрузим модель, если она еще не открыта на холсте
if "sp_net_cipher_model_1R"  getfield.(engee.get_all_models(), :name)
    engee.load( "$(@__DIR__)/sp_net_cipher_model_1R.engee");
end

model_data = engee.run( "sp_net_cipher_model_1R" );

让我们来研究一下发送和接收的信息:

In [ ]:
source_message = collect(model_data["Блок сообщения"]).value
cipher_text = UInt16.(collect(model_data["Зашифрованный блок"]).value)
received_message = UInt16.(collect(model_data["Расшифрованный блок"]).value)

source_bytes = vcat( reverse.([reinterpret( UInt8, [UInt16(c)]) for c in source_message])... )
cipher_bytes = vcat( reverse.([reinterpret( UInt8, [UInt16(c)]) for c in cipher_text])... )
received_bytes = vcat( reverse.([reinterpret( UInt8, [UInt16(c)]) for c in received_message])... )

println( "Отправленное сообщение: ", join( vcat( string.(source_bytes, base=16)... ), " " ) )
println( "Зашифрованное сообщение: ", join( vcat( string.(cipher_bytes, base=16)... ), " " ))
println( "Полученное сообщение: ", join( vcat( string.(received_bytes, base=16)... ), " " ) )
Отправленное сообщение: d0 a1 d0 be d0 be d0 b1 d1 89 d0 b5 d0 bd d0 b8 d0 b5
Зашифрованное сообщение: 7c 9c e3 60 7e 1c f7 5a 6e 9c 6b f0 f8 cc ef b6 2c 5f
Полученное сообщение: d0 a1 d0 be d0 be d0 b1 d1 89 d0 b5 d0 bd d0 b8 d0 b5
In [ ]:
println( "Отправленная строка: ", String( source_bytes ))
println( "Полученная строка: ", String( received_bytes ))
Отправленная строка: Сообщение
Полученная строка: Сообщение

创建回合密钥

创建循环密钥的算法组织如下

  • 构成密钥的字节序列被分割成每个 64 比特的块
  • 块是重叠的(密钥d0 9a d0 bb d1 8e d1 87 生成块d0 9a d0 bb,9a d0 bb d1,d0 bb d1 8e 等)。
  • 循环使用密钥

一个 64 位的密钥块被分为 4 轮密钥,每轮 16 位(按顺序),我们只使用其中的前三轮密钥。

image.png

使用模型的注意事项

在解释或计划更改模型时,以下特点值得考虑:

  • 信息和密钥循环传递给模型,永不终止、
  • 一个区块的完整循环在一个建模周期内执行,没有任何延迟
  • 因此,在最高级别,我们不处理比特矢量,而是处理数字UInt16,UInt32 等、
  • 输入信息和轮次密钥以 16 比特的块输入模型,每轮的所有四个 S 块都以 4 比特的块作为输入,P 块的向量为 16 个二进制位**、
  • S 块和 P 块中的置换参数不是从编码本中提取的,而是由操作shuffle 与指定的seed 生成的、
  • 信息以非重叠块的形式传输给算法,关键块由一个偏移一个字节的窗口生成。

结论

我们已经创建了一个模型,使我们能够研究使用 SP 网络加密信息的所有步骤,并对该算法的架构进行任何更改,而无需深入研究技术编程问题。