4个版本

0.1.3 2023年11月25日
0.1.2 2023年11月21日
0.1.1 2023年4月18日
0.1.0 2023年4月5日

#351加密学

每月34次下载
用于 deck-farfalle

MIT 协议

39KB
460

xoofff

Farfalle with Xoodoo:并行置换密码学

概述

Farfalle是一个具有可扩展输入的密钥加密函数,它可以返回任意长度的输出——它在输入和输出接口中都提供了灵活的增量属性。例如,假设我们有两个消息XY,我们想计算F(X || Y),那么处理它的成本只是吸收Y,如果F(X)已经处理过。一旦X被吸收,就可以最终化状态以从中挤压任意数量的字节。之后可以重新启动吸收阶段,当Y准备好吸收时,状态可以再次最终化,并且可以再次挤压任意数量的字节。这样,可以为处理任意数量的消息重新启动absorb -> finalize -> squeeze循环,而累加器在重启过程中保持内部状态完整。这个想法在https://ia.cr/2016/1188中定义。Xoofff是Farfalle构建,使用Xoodoo置换进行实例化,该置换在https://ia.cr/2018/767中描述。在这篇(后一篇)论文中,提出了deck函数的名称——这是一个密钥函数,它接受任意长度的输入字符串序列,并返回任意长度的伪随机字符串,可以增量计算,其中缩写deck代表Doubly-Extendable Cryptographic Keyed function。

在这里,我正在开发和维护一个Rust库crate,实现Xoofff deck函数。有关API使用示例,请参阅下面

先决条件

Rust稳定工具链,您可以通过访问https://rustup.rs来获取。

# When developing this library, I was using
rustc --version
rustc 1.74.0 (79e9716c9 2023-11-13)

[!TIP] 我建议您还使用cargo-criterion来运行基准可执行文件。更多关于它的信息,请参阅https://crates.io/crates/cargo-criterion。您可以通过运行以下命令在系统范围内安装它:$ cargo install cargo-criterion

测试

为确保Xoofff deck函数实现正确,以及

  • 一次性消息吸收到/从deck函数中挤压
  • 增量消息吸收到/从deck函数中挤压

达到相同状态,我维护了一些测试用例。您可以通过以下命令运行它们:

[!注意]为确保Xoofff实现的函数正确性,我使用了已知答案测试,这些测试是由Xoofff作者使用参考实现生成的,遵循在https://gist.github.com/itzmeanjan/504113021dec30a0909e5f5b47a5bde5上指定的说明。

cargo test --lib

基准测试

使用以下命令对Xoofff的deck函数进行各种输入大小的基准测试。

[!警告]在基准测试时,请确保您已禁用CPU频率调整,否则您看到的数字可能会相当误导。我发现https://github.com/google/benchmark/blob/b40db869/docs/reducing_variance.md很有帮助。

RUSTFLAGS="-C opt-level=3 -C target-cpu=native" cargo criterion xoofff

如果您对基准测试底层Xoodoo排列感兴趣,请考虑以下命令。

RUSTFLAGS="-C opt-level=3 -C target-cpu=native" cargo criterion xoodoo --features="dev"

[!注意]如果您在https://github.com/itzmeanjan/criterion-cycles-per-byte/blob/63edc6b46/src/lib.rs#L63-L70指定的目标上运行基准测试,请考虑阅读。

[!重要]如果您尚未安装cargo-criterion,您必须使用以下命令构建和执行基准测试二进制文件:$ RUSTFLAGS="-C opt-level=3 -C target-cpu=native" cargo bench ...

在12代英特尔(R)酷睿(TM) i7-1260P上

Xoofff - Deck函数

xoofff/key = 32B | in = 32B | out = 32B | offset = 16B (cached)                                                                            
                        time:   [386.0719 cycles 386.7368 cycles 388.0084 cycles]
                        thrpt:  [4.8501 cpb 4.8342 cpb 4.8259 cpb]
xoofff/key = 32B | in = 32B | out = 32B | offset = 16B (random)                                                                            
                        time:   [463.2273 cycles 468.2415 cycles 472.7826 cycles]
                        thrpt:  [5.9098 cpb 5.8530 cpb 5.7903 cpb]

xoofff/key = 32B | in = 128B | out = 32B | offset = 16B (cached)                                                                            
                        time:   [510.5196 cycles 510.6597 cycles 510.8342 cycles]
                        thrpt:  [2.9025 cpb 2.9015 cpb 2.9007 cpb]
xoofff/key = 32B | in = 128B | out = 32B | offset = 16B (random)                                                                            
                        time:   [597.6074 cycles 598.6353 cycles 599.5923 cycles]
                        thrpt:  [3.4068 cpb 3.4013 cpb 3.3955 cpb]

xoofff/key = 32B | in = 512B | out = 32B | offset = 16B (cached)                                                                            
                        time:   [993.0588 cycles 994.1031 cycles 995.7628 cycles]
                        thrpt:  [1.7781 cpb 1.7752 cpb 1.7733 cpb]
xoofff/key = 32B | in = 512B | out = 32B | offset = 16B (random)                                                                             
                        time:   [1136.8571 cycles 1139.8106 cycles 1143.5883 cycles]
                        thrpt:  [2.0421 cpb 2.0354 cpb 2.0301 cpb]

xoofff/key = 32B | in = 2048B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [2924.0033 cycles 2931.8707 cycles 2941.8708 cycles]
                        thrpt:  [1.4036 cpb 1.3988 cpb 1.3950 cpb]
xoofff/key = 32B | in = 2048B | out = 32B | offset = 16B (random)                                                                             
                        time:   [3010.5796 cycles 3014.4697 cycles 3018.8273 cycles]
                        thrpt:  [1.4403 cpb 1.4382 cpb 1.4363 cpb]

xoofff/key = 32B | in = 8192B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [10624.0893 cycles 10626.9955 cycles 10630.3327 cycles]
                        thrpt:  [1.2901 cpb 1.2897 cpb 1.2893 cpb]
xoofff/key = 32B | in = 8192B | out = 32B | offset = 16B (random)                                                                             
                        time:   [10801.9904 cycles 10817.4401 cycles 10835.1726 cycles]
                        thrpt:  [1.3149 cpb 1.3128 cpb 1.3109 cpb]

Xoodoo[{6, 12}] 排列

xoodoo/6 (cached)       time:   [71.5661 cycles 71.7006 cycles 71.9454 cycles]                
                        thrpt:  [1.4989 cpb 1.4938 cpb 1.4910 cpb]
xoodoo/6 (random)       time:   [82.5140 cycles 82.5797 cycles 82.6480 cycles]                
                        thrpt:  [1.7218 cpb 1.7204 cpb 1.7190 cpb]

xoodoo/12 (cached)      time:   [138.7907 cycles 138.8587 cycles 138.9365 cycles]             
                        thrpt:  [2.8945 cpb 2.8929 cpb 2.8915 cpb]
xoodoo/12 (random)      time:   [150.6641 cycles 152.5450 cycles 154.7112 cycles]             
                        thrpt:  [3.2231 cpb 3.1780 cpb 3.1388 cpb]

在ARM Cortex-A72(即树莓派4B)上

Xoofff - Deck函数

xoofff/key = 32B | in = 32B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [1475.7031 cycles 1475.7816 cycles 1475.8610 cycles]
                        thrpt:  [18.4483 cpb 18.4473 cpb 18.4463 cpb]
xoofff/key = 32B | in = 32B | out = 32B | offset = 16B (random)                                                                             
                        time:   [1614.8130 cycles 1617.2083 cycles 1619.2197 cycles]
                        thrpt:  [20.2402 cpb 20.2151 cpb 20.1852 cpb]

xoofff/key = 32B | in = 128B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [2155.4275 cycles 2155.6064 cycles 2155.8013 cycles]
                        thrpt:  [12.2489 cpb 12.2478 cpb 12.2467 cpb]
xoofff/key = 32B | in = 128B | out = 32B | offset = 16B (random)                                                                             
                        time:   [2358.8773 cycles 2366.7201 cycles 2373.2365 cycles]
                        thrpt:  [13.4843 cpb 13.4473 cpb 13.4027 cpb]

xoofff/key = 32B | in = 512B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [4846.7515 cycles 4847.1301 cycles 4847.5460 cycles]
                        thrpt:  [8.6563 cpb 8.6556 cpb 8.6549 cpb]
xoofff/key = 32B | in = 512B | out = 32B | offset = 16B (random)                                                                             
                        time:   [5129.3271 cycles 5141.8396 cycles 5152.6335 cycles]
                        thrpt:  [9.2011 cpb 9.1819 cpb 9.1595 cpb]

xoofff/key = 32B | in = 2048B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [15637.2770 cycles 15638.4849 cycles 15639.8726 cycles]
                        thrpt:  [7.4618 cpb 7.4611 cpb 7.4605 cpb]
xoofff/key = 32B | in = 2048B | out = 32B | offset = 16B (random)                                                                             
                        time:   [16086.6226 cycles 16098.8318 cycles 16109.5064 cycles]
                        thrpt:  [7.6858 cpb 7.6807 cpb 7.6749 cpb]

xoofff/key = 32B | in = 8192B | out = 32B | offset = 16B (cached)                                                                             
                        time:   [58704.8839 cycles 58707.4874 cycles 58710.3427 cycles]
                        thrpt:  [7.1250 cpb 7.1247 cpb 7.1244 cpb]
xoofff/key = 32B | in = 8192B | out = 32B | offset = 16B (random)                                                                             
                        time:   [59828.4330 cycles 59853.6571 cycles 59876.0584 cycles]
                        thrpt:  [7.2665 cpb 7.2638 cpb 7.2607 cpb]

Xoodoo[{6, 12}] 排列

xoodoo/6 (cached)       time:   [293.7426 cycles 293.8227 cycles 293.9663 cycles]            
                        thrpt:  [6.1243 cpb 6.1213 cpb 6.1196 cpb]
xoodoo/6 (random)       time:   [312.2511 cycles 312.3959 cycles 312.5695 cycles]            
                        thrpt:  [6.5119 cpb 6.5082 cpb 6.5052 cpb]

xoodoo/12 (cached)      time:   [618.6418 cycles 619.0397 cycles 619.4066 cycles]             
                        thrpt:  [12.9043 cpb 12.8967 cpb 12.8884 cpb]
xoodoo/12 (random)      time:   [638.8219 cycles 638.9825 cycles 639.1287 cycles]             
                        thrpt:  [13.3152 cpb 13.3121 cpb 13.3088 cpb]

用法

使用Xoofff - deck函数API入门非常简单。

  1. 在项目Cargo.toml文件中将xoofff添加为依赖项。
[dependencies]
# either
xoofff = { git = "https://github.com/itzmeanjan/xoofff" }
# or
xoofff = "=0.1.3"
  1. 创建Xoofff deck函数对象。
use xoofff::Xoofff;

fn main() {
    let key = [0xff; 32]; // demo key

    // message sequence to be absorbed
    let msg0 = [0, 1, 2, 3];
    let msg1 = [4, 5, 6, 7];

    let mut dig = [0u8; 32]; // (to be) squeezed output bytes

    let mut deck = Xoofff::new(&key);
    // ...
}
  1. 通过发出absorb例程N(>0)多次,将任意(>=0)字节消息吸收到deck函数状态中。
// either
deck.absorb(&msg0[..]);

// or
deck.absorb(&msg0[..1]);
deck.absorb(&msg0[1..]);

// this does no harm, but in most cases we can avoid doing it.
deck.absorb(&[]);
  1. 当第一个消息的所有消息字节都吸收后,我们可以最终确定状态。
// (first arg) domain seperator can be at max 7 -bits wide
// (second arg) must be <= 7
// (third arg) byte offset, must be <= 48
deck.finalize(0, 0, 8);

// once finalized, calling `finalize` again should do nothing.
  1. 现在我们可以通过调用任意次数的squeeze例程,从deck函数状态中挤出任意数量的字节。
// either
deck.squeeze(&mut dig[..]);

// or
deck.squeeze(&mut dig[..16]);
deck.squeeze(&mut dig[16..]);

// you can safely do it, though it's of not much help.
deck.squeeze(&mut []);
  1. deck函数支持扩展输入消息,而无需支付处理消息序列中历史消息的成本。累加器在状态最终确定并准备好被挤压时保持吸收的消息状态完整。当deck函数状态重新启动时,它再次准备好通过absorb -> finalize -> squeeze周期。
deck.restart();
  1. 现在可以通过调用任意次数的absorb例程,从消息序列中的第二个消息中吸收任意数量的字节。
deck.absorb(&msg1);
  1. 一旦第二个消息的所有字节都吸收完毕,您可以最终确定deck函数状态。
deck.finalize(0, 0, 8);
  1. 最后从deck函数状态中挤出任意数量的字节。
deck.squeeze(&mut dig);
  1. 如您所理解,这样您可以通过absorb -> finalize -> squeeze周期再次启动,当有新消息准备好处理时。deck函数提供了非常灵活和可扩展的输入/输出处理接口。

我维护了一个示例,在deck_function.rs中,您可能想查看。您也可以通过以下命令运行它。

cargo run --example deck_function

依赖项