Engee 文档
Notebook

使用替换-置换网络(SP-network)的加密模型

我们使用理论示例研究组织现代加密系统的原则。

任务说明

大多数现代信息系统使用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位的块作为输入,以及向量为16二进制位的P块
,
*s块和P块内部的置换参数不是取自码本,而是由运算产生的 shuffle 与指定 seed.
*消息以非重叠块传输到算法,关键块由偏移量为一个字节的窗口生成。

结论

我们创建了一个模型,允许我们使用SP网络研究消息加密的所有阶段,并对此算法的体系结构进行任何更改,而无需深入研究技术编程问题。