置换-重排网络(SP-网络)加密模式¶
我们以一个理论实例来研究现代加密系统的组织原理。
任务描述¶
大多数现代信息系统都使用 AES(或类似)密码来加密信息。这些密码基于置换-替换网络算法(SP-network)。
如果你只想对信息进行加密或解密,Julia 有
AES.jl
这样的库来对字节序列进行加密和解密。
这里介绍的算法不一定是强密码。通过适当选择 S 和 P 块参数,以及使用更好的函数生成轮密钥并将其添加到密文中,可以使 "强 "密码变得更强。我们只创建了一个训练示例,在某些方面便于分析和改进。
模型概览¶
基于 SP 网的密码接收一个数据块和一个密钥作为输入,并执行几轮由数据块中比特的交替替换和置换阶段组成的程序。
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]) )
接下来,我们将揭开模型的每个区块,看看每一轮是如何工作的。
三轮加密模型¶
如果扩展每个子系统,就能非常直观地了解每轮算法的工作原理(模型sp_net_cipher_model_3R_expand
)。
它可以让你看到每个阶段的设置,并检查如果替换或重新排列块的设置不协调将会发生什么。
让我们运行这个模型,验证一下用相同的字节传输信息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)... ), " " ) )
In [ ]:
println( "Отправленная строка: ", String( source_bytes ))
println( "Полученная строка: ", String( received_bytes ))
请注意,密文从第 17 个区块开始重复。
一轮密码模式¶
如果我们将网络简化为一轮,模型如下:
我们看到了所有熟悉的 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)... ), " " ) )
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 位(按顺序),我们只使用其中的前三轮密钥。
使用模型的注意事项¶
在解释或计划更改模型时,以下特点值得考虑:
- 信息和密钥循环传递给模型,永不终止、
- 一个区块的完整循环在一个建模周期内执行,没有任何延迟
- 因此,在最高级别,我们不处理比特矢量,而是处理数字
UInt16
,UInt32
等、 - 输入信息和轮次密钥以 16 比特的块输入模型,每轮的所有四个 S 块都以 4 比特的块作为输入,P 块的向量为 16 个二进制位**、
- S 块和 P 块中的置换参数不是从编码本中提取的,而是由操作
shuffle
与指定的seed
生成的、 - 信息以非重叠块的形式传输给算法,关键块由一个偏移一个字节的窗口生成。
结论¶
我们已经创建了一个模型,使我们能够研究使用 SP 网络加密信息的所有步骤,并对该算法的架构进行任何更改,而无需深入研究技术编程问题。