小型块完美分组密码及相关算法解析
1. 引言
现有的对称加密算法通常针对由至少64位基本二进制块组成的消息。然而,一些应用需要能处理更小甚至非二进制块的分组密码,可将其视为对n个元素的伪随机排列。
例如,生成供用户输入的唯一不可预测的十进制数字,这类数字必须简短,简单的伪随机数生成器(PRNG)因有不可忽视的碰撞概率而不适用。一种解决方案是使用能处理所需长度十进制数字集合的分组密码,对计数器的连续值进行加密。
但构建安全的分组密码是一项棘手的任务,小块和非二进制字母表在多方面更具挑战性:
-
理论构造依赖大尺寸块
:一些理论上的安全分组密码构造方法,隐式依赖大尺寸块来隐藏某些偏差,而我们的安全模型无法容忍这些偏差。
-
安全分析模型不适用
:常见的安全分析技术将攻击者建模为可访问加密或解密预言机,但小尺寸块的完整码本太小,此模型不再适用。
-
攻击分析复杂
:某些类型的攻击(如差分和线性密码分析)在非二进制字母表上更难表达,例如十进制数字集合可应用多种不同的环结构,且不存在大小为10的域,只有包含非可逆元素的环,使情况更复杂。
由于这些原因,设计此类分组密码的尝试较少。本文将探讨一种基于洗牌(Shuffle)算法的全新排列生成方法。
2. 洗牌算法与随机数生成
对于非常小的输入数据空间,如两位数的十进制数字,输入空间大小为100,有100!种可能的排列。若有合适的随机源,可使用以下洗牌算法均匀选择100个元素的随机排列:
Shuffle:
1. 用元素w填充数组,使数组元素值为w
2. i ← 0
3. 选择一个介于i和99(包含)之间的随机数j
4. 如果i ≠ j,交换数组中索引为i和j的元素
5. i递增
6. 如果i < 99,返回步骤3
7. 数组内容代表排列
该算法通常被称为“Knuth洗牌”。若步骤3中的随机数选择是均匀的,则所有可能的排列有相等的生成概率。对于非常小的块,可使用加密安全的种子PRNG的密钥,通过Knuth洗牌生成完整排列并应用。简单的线性遍历可计算逆排列用于解密。
若PRNG输出位,可使用以下算法输出0到d - 1之间的均匀随机数:
RandomNumber:
1. 选择一个整数r,使得2^r ≥ d
2. 获取r个随机位并将其解释为一个数字x,满足0 ≤ x < 2^r
3. 计算t = ⌊x / d⌋
4. 如果d + td > 2^r,返回步骤2
5. 输出x - td
根据r的选择,循环发生的概率可任意降低。实际实现中可使用r = 256并忽略步骤4的测试,这会带来微小的选择偏差,但可忽略不计。
洗牌算法生成的排列可视为分组密码,其密钥是PRNG的输出(或等价地,PRNG中使用的种子)。真正的随机生成器意味着真正的随机排列,因此对该选择系统的成功攻击等同于对PRNG的成功区分。但此过程的CPU和空间成本为O(n),对于n大于10^4的值不实用。我们的目标是从PRNG的输出中生成一个排列φ,满足:
- 假设使用完美随机源而非PRNG,n个元素的所有可能排列有相等的被选择概率。
- 对于任何给定的x,计算φ(x)的平均计算成本远低于O(n)。
3. 符号说明
我们考虑选择一个对n个元素进行操作的随机排列φ,n是大于1的整数,目标值在10^3到10^20之间,不过该构造也适用于更小或更大的块。
我们需要一个确定性的PRNG,将其建模为一个函数:
[R : N^r \to {0, 1}]
[(n_1, n_2, \ldots n_r) \to R(n_1, n_2, \ldots n_r)]
假设PRNG是无偏的随机预言机,即给定一组输入整数的输出无法从R对所有其他输入值集的输出知识中计算预测。从具有r个输入参数的PRNG R,可通过以下方式轻松构建具有r + 1个输入参数的PRNG R’:
[R’(n_1, \ldots n_r, n_{r + 1}) = R(n_1, \ldots n_{r - 1}, (n_r + n_{r + 1} + 1)(n_r + n_{r + 1} + 2)/2 - n_r - 1)]
实际中,我们需要一个具有三个输入参数的带密钥PRNG,并会给出可行的界限。
我们使用“log”表示以2为底的对数,即log 2^x = x。算法描述中使用二项式项,为简化方程,使用扩展二项式系数:
[
\begin{cases}
\frac{n!}{p!(n - p)!}, & \text{如果 } 0 \leq p \leq n \
0, & \text{否则}
\end{cases}
]
4. 随机排列选择算法
我们有两个主要算法:Permutator和InvPermutator,分别用于计算φ和φ^(-1)。Permutator通过“分割”的二叉树实现φ,每个分割将输入分为两组。Splitter算法实现分割,它使用由Repartitor计算的再分配二叉树,而Repartitor使用PRNG的输出。InvPermutator使用InvSplitter,后者也依赖Repartitor。
4.1 Repartitor算法
Repartitor的输入为:
- 整数n和p,满足0 ≤ p ≤ n且n ≠ 0
- PRNG索引i
定义a = ⌊n / 2⌋,使用O(log n)次PRNG请求R(i, …)(所有请求的第一个索引为i),Repartitor输出一个整数u,其分布如下:
[P(u = k) = \frac{\binom{a}{k}\binom{n - a}{p - k}}{\binom{n}{p}}]
此分布为超几何分布。可以证明,具有非零返回概率的u值必须满足:
- 0 ≤ u ≤ a
- (a + p) - n ≤ u ≤ p
在p = 0或p = n的退化情况下,只有一个返回值(分别为u = 0或u = a),可快速返回。当p > a时,可使用以下方式实现Repartitor:
[Repartitor(n, p, i) = a - Repartitor(n, n - p, i)]
这意味着在实现Repartitor时,可始终假设p ≤ a。
Repartitor模拟的实验是:从一组n个元素中,将其分为大小为a和n - a的两个子集,随机选择p个不同元素,计算这p个元素中有多少个来自第一个子集(大小为a)。高效实现Repartitor并获得足够无偏的输出是一项挑战,后续会给出一个慢速但精确的算法。
4.2 Splitter算法
Splitter算法的输入为:
- 整数n和p,满足0 ≤ p ≤ n且n ≠ 0
- 输入索引x(0 ≤ x < n)
- PRNG索引i
使用对Repartitor(∗, ∗, j)的请求(索引j满足i ≤ j < i + n - 1),Splitter返回一个整数y = Splitter(n, p, x),满足:
- 0 ≤ Splitter(n, p, x) < n
- x1 ≠ x2 ⇒ Splitter(n, p, x1) ≠ Splitter(n, p, x2)
- #{x | Splitter(n, p, x) < p} = p
- Splitter(n, p, x1) < Splitter(n, p, x2) ≤ p ⇒ x1 < x2
- p ≤ Splitter(n, p, x1) < Splitter(n, p, x2) ⇒ x1 < x2
这些方程意味着Splitter从0到n - 1的整数集合中提取p个元素,将这些p个元素赋予输出索引0到p - 1,且保持其顺序;未提取的n - p个元素赋予索引p到n - 1,也保持其顺序。有(\binom{n}{p})种这样的“分割”,要求Splitter均匀选择其中一种。
Splitter使用“分布树”实现,这是一个二叉树,其叶子节点是n个元素,每个叶子节点要么“被提取”(属于p个元素),要么“未被提取”(属于n - p个其他元素)。树中的每个节点记录从该节点向下的元素中有多少个“被提取”,根节点记录值p。树从根节点开始构建,每个节点管理k个元素,将f个“提取”均匀分配到这些k个元素中,将k个元素分成两半,并使用Repartitor按照正确的概率分布将f个提取分配到两半中,然后对两半递归调用该过程。
计算整个树需要O(n)次对Repartitor的调用,但要知道给定输入元素x的状态(是否被提取)并计算其最终索引,只需探索从根节点到对应叶子节点的树路径。如果树是平衡的,这需要O(log n)次对Repartitor的调用,即O((log n)^2)次PRNG调用。
以下是Splitter的实现:
Splitter:
input: n, p, x and i
output: y
1. 如果n = 1,则返回x
2. 计算a ← ⌊n / 2⌋
3. 计算u ← Repartitor(n, p, i)
4. 如果x ≥ a,转到步骤7
5. 计算t ← Splitter(a, u, x, i + 1)
6. 如果t < u,返回t,否则返回p + (t - u)
7. 计算t ← Splitter(n - a, p - u, x - a, i + a)
8. 如果t < p - u,返回t + u,否则返回a + t
由于a的计算使树平衡,最大递归深度为⌈log n⌉。可以证明,Splitter仅对索引j满足i ≤ j ≤ i + n - 2的PRNG进行调用,且对于给定的x值,相同的PRNG索引不会被使用两次。Repartitor实现的超几何分布确保Splitter在n个元素分成长度为p和n - p的集合的所有可能分割中均匀选择。
下面用mermaid流程图展示Splitter算法的流程:
graph TD;
A[开始] --> B{n = 1?};
B -- 是 --> C[返回x];
B -- 否 --> D[计算a = ⌊n / 2⌋];
D --> E[计算u = Repartitor(n, p, i)];
E --> F{x ≥ a?};
F -- 否 --> G[计算t = Splitter(a, u, x, i + 1)];
G --> H{t < u?};
H -- 是 --> I[返回t];
H -- 否 --> J[返回p + (t - u)];
F -- 是 --> K[计算t = Splitter(n - a, p - u, x - a, i + a)];
K --> L{t < p - u?};
L -- 是 --> M[返回t + u];
L -- 否 --> N[返回a + t];
综上所述,我们介绍了用于小型块的分组密码相关算法,包括洗牌算法、随机数生成算法以及随机排列选择的核心算法Repartitor和Splitter。这些算法为处理小尺寸和非二进制块的分组密码提供了一种新的解决方案,具有较低的计算成本和空间复杂度。
小型块完美分组密码及相关算法解析
5. 安全模型
在构建小型块完美分组密码时,安全模型至关重要。现有的对称加密算法安全分析模型通常不适用于小型块和非二进制字母表的情况。
对于小型块,完整码本规模较小,传统的将攻击者建模为访问加密或解密预言机且对查询次数有限制的模型不再适用。同时,在非二进制字母表上,一些常见的攻击分析方法(如差分和线性密码分析)变得更加复杂,因为非二进制字母表可能存在多种不同的环结构,且可能不存在合适的域,只有包含非可逆元素的环。
我们的安全模型要求能够容忍小型块和非二进制字母表带来的特殊情况,避免传统构造方法中依赖大尺寸块隐藏的偏差。通过使用上述介绍的随机排列选择算法,我们可以生成一个在理论上具有均匀分布的随机排列,使得攻击者难以区分该排列与真正的随机排列。
6. 算法复杂度分析
6.1 时间复杂度
- Shuffle算法 :Shuffle算法的时间复杂度为O(n),因为需要对n个元素进行遍历和交换操作。对于较大的n值,这种复杂度会导致计算成本过高,不适合实际应用。
- RandomNumber算法 :RandomNumber算法的时间复杂度主要取决于循环次数。在实际实现中,通过选择合适的r值(如r = 256),可以将循环发生的概率降低到可忽略不计的程度,因此其平均时间复杂度接近常数。
- Repartitor算法 :Repartitor算法使用O(log n)次PRNG请求,因此其时间复杂度为O(log n)。
- Splitter算法 :Splitter算法在平衡树的情况下,需要O(log n)次对Repartitor的调用,每次Repartitor调用的时间复杂度为O(log n),因此Splitter算法的时间复杂度为O((log n)^2)。
- Permutator和InvPermutator算法 :由于Permutator和InvPermutator算法主要依赖于Splitter和InvSplitter算法,而Splitter和InvSplitter算法的时间复杂度为O((log n)^2),因此Permutator和InvPermutator算法的时间复杂度也为O((log n)^2)。
以下是各算法时间复杂度的总结表格:
| 算法名称 | 时间复杂度 |
| ---- | ---- |
| Shuffle | O(n) |
| RandomNumber | 接近常数 |
| Repartitor | O(log n) |
| Splitter | O((log n)^2) |
| Permutator | O((log n)^2) |
| InvPermutator | O((log n)^2) |
6.2 空间复杂度
- Shuffle算法 :Shuffle算法需要一个长度为n的数组来存储排列,因此其空间复杂度为O(n)。
- RandomNumber算法 :RandomNumber算法只需要存储几个整数,因此其空间复杂度为常数。
- Repartitor算法 :Repartitor算法只需要存储几个整数,因此其空间复杂度为O(log n)。
- Splitter算法 :Splitter算法的递归深度为⌈log n⌉,因此其空间复杂度为O(log n)。
- Permutator和InvPermutator算法 :Permutator和InvPermutator算法的空间复杂度主要取决于递归调用栈的深度,因此其空间复杂度也为O(log n)。
以下是各算法空间复杂度的总结表格:
| 算法名称 | 空间复杂度 |
| ---- | ---- |
| Shuffle | O(n) |
| RandomNumber | 常数 |
| Repartitor | O(log n) |
| Splitter | O(log n) |
| Permutator | O(log n) |
| InvPermutator | O(log n) |
7. 应用场景与优势
小型块完美分组密码在一些特定的应用场景中具有重要的优势。
7.1 生成唯一不可预测的十进制数字
在需要生成供用户输入的唯一不可预测的十进制数字的场景中,如验证码、交易码等,小型块分组密码可以通过对计数器的连续值进行加密,生成短且唯一的数字序列。与简单的PRNG相比,使用分组密码可以避免碰撞问题,提高数字的安全性和唯一性。
7.2 资源受限环境
在资源受限的环境中,如物联网设备、嵌入式系统等,小型块分组密码的低计算成本和空间复杂度使其成为一种可行的选择。通过使用上述介绍的算法,可以在有限的资源下实现安全的加密和解密操作。
8. 总结
本文介绍了一种用于小型块和非二进制字母表的分组密码解决方案。通过洗牌算法、随机数生成算法以及随机排列选择的核心算法Repartitor和Splitter,我们可以生成一个对n个元素的随机排列φ,满足在假设使用完美随机源的情况下,所有可能排列有相等的被选择概率,并且对于任何给定的x,计算φ(x)和φ^(-1)(y)的平均计算成本远低于O(n)。
这些算法的时间复杂度和空间复杂度较低,适用于资源受限的环境和需要生成唯一不可预测数字的场景。同时,我们还介绍了适用于小型块和非二进制字母表的安全模型,确保了分组密码的安全性。
未来,可以进一步研究如何优化这些算法,提高其性能和安全性。例如,探索更高效的PRNG实现方法,或者改进算法的递归结构以减少计算开销。此外,还可以研究如何将这些算法应用于更多的实际场景中,拓展其应用范围。
下面用mermaid流程图展示整体算法的调用关系:
graph LR;
A[Shuffle] --> B[RandomNumber];
C[Permutator] --> D[Splitter];
D --> E[Repartitor];
F[InvPermutator] --> G[InvSplitter];
G --> E;
综上所述,本文提出的算法为小型块和非二进制字母表的分组密码提供了一种有效的解决方案,具有广阔的应用前景和研究价值。
超级会员免费看
6061

被折叠的 条评论
为什么被折叠?



