1. 引言
主要参考Grassi等人2019年论文《On a Generalization of Substitution-Permutation Networks: The HADES Design Strategy (Updated Version)》。
相关代码实现有:
block ciphers和cryptographic permutations通常设计为:
- iterate an efficiently implementable round function many times 使得结果看起来像随机的。
通常,对同一round function迭代调用足够多次数,可确保round function中的一些对称和结构属性肯定会消失。
基于HADES构建的cipher,其每轮中有以下三步组成:
- 1)Add Round Key:表示为 ARK ( ⋅ ) \text{ARK}(\cdot) ARK(⋅)
- 2)SubWords:表示为 S-Box ( ⋅ ) \text{S-Box}(\cdot) S-Box(⋅)【每一轮使用的S-Box数量是不一样的。】
- 3)MixLayer:表示为 M ( ⋅ ) \text{M}(\cdot) M(⋅)
然后,最后一轮中,MixLayer操作可忽略:
HADES中的关键特性是每一轮的S-Box数量是不一样的:
- 一定数量的轮中,标记为 R F R_F RF,具有full S-Box layer,即 t t t个S-Box functions;
- 一定数量的轮中,标记为 R P R_P RP,具有partial S-Box layer,即 1 ≤ s < t 1\leq s<t 1≤s<t个S-Box和 ( t − s ) (t-s) (t−s)个identity functions。
接下来仅考虑 s = 1 s=1 s=1的情况。
令 R F = 2 ⋅ R f R_F=2\cdot R_f RF=2⋅Rf,则总的轮数为 R = 2 ⋅ R f + R P R=2\cdot R_f+R_P R=2⋅Rf+RP。
2. HADESMiMC
HADESMiMC中每一轮的 R k ( ⋅ ) : ( F p ) t → ( F p ) t R_k(\cdot):(\mathbb{F}_p)^t\rightarrow (\mathbb{F}_p)^t Rk(⋅):(Fp)t→(Fp)t定义为:
R k ( ⋅ ) = k + M × S ( ⋅ ) R_k(\cdot)=k+M\times \mathcal{S}(\cdot) Rk(⋅)=k+M×S(⋅)
其中 k ∈ ( F p ) t k\in (\mathbb{F}_p)^t k∈(Fp)t 为secret subkey, M ∈ ( F p ) t × t M\in (\mathbb{F}_p)^{t\times t} M∈(Fp)t×t为定义了linear layer的invertible matrix, S ( ⋅ ) : ( F p ) t → ( F p ) t \mathcal{S}(\cdot):(\mathbb{F}_p)^t\rightarrow (\mathbb{F}_p)^t S(⋅):(Fp)t→(Fp)t为S-Box layer。
对于full S-Box layers,定义 S = [ S ( ⋅ ) , ⋯ , S ( ⋅ ) ] \mathcal{S}=[S(\cdot),\cdots, S(\cdot)] S=[S(⋅),⋯,S(⋅)],对于partial S-Box layer,定义 S = [ S ( ⋅ ) , I ( ⋅ ) , ⋯ , I ( ⋅ ) ] \mathcal{S}=[S(\cdot), I(\cdot),\cdots,I(\cdot)] S=[S(⋅),I(⋅),⋯,I(⋅)]。其中 S ( ⋅ ) : F p → F p S(\cdot):\mathbb{F}_p\rightarrow \mathbb{F}_p S(⋅):Fp→Fp为non-linear S-Box, I ( ⋅ ) I(\cdot) I(⋅)为identity function。
对于素数域 p p p,non-linear S-Box定义为power map:
S-Box ( x ) = x α \text{S-Box}(x)=x^{\alpha} S-Box(x)=xα
其中 α ≥ 3 \alpha\geq 3 α≥3 为最小整数——满足 g c d ( p − 1 , α ) = 1 gcd(p-1,\alpha)=1 gcd(p−1,α)=1(如当 g c d ( p − 1 , 3 ) = 1 gcd(p-1,3)=1 gcd(p−1,3)=1时 α = 3 \alpha=3 α=3,当 g c d ( p − 1 , 3 ) ≠ 1 且 g c d ( p − 1 , 5 ) = 1 gcd(p-1,3)\neq 1且gcd(p-1,5)=1 gcd(p−1,3)=1且gcd(p−1,5)=1时 α = 5 \alpha=5 α=5)。
3. HADESMiMC代码解析
Dusk团队实现的 https://github.com/dusk-network/Hades252(Rust)中,定义了:
- 采用BLS12-381曲线, p = 0 x 73 e d a 753299 d 7 d 483339 d 80809 a 1 d 80553 b d a 402 f f f e 5 b f e f f f f f f f f 00000001 p=0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 p=0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001;
- R P = 59 , R F = 8 R_P=59,R_F=8 RP=59,RF=8,每一轮最多的input width为 5 5 5——即 t = 5 t=5 t=5;
/// Total ammount of full rounds that will be applied.
/// This is expressed as `RF` in the paper.
pub const TOTAL_FULL_ROUNDS: usize = 8;
/// Total ammount of partial rounds that will be applied.
/// This is expressed as `Rp` in the paper.
pub const PARTIAL_ROUNDS: usize = 59;
/// Maximum input width for the rounds
pub const WIDTH: usize = 5;
- Add Round Key A R K ( ⋅ ) ARK(\cdot) ARK(⋅)定义为在
./assets/ark.bin
中,总个数为960:
pub const ROUND_CONSTANTS: [BlsScalar; CONSTANTS] = {
let bytes = include_bytes!("../assets/ark.bin");
let mut cnst = [BlsScalar::zero(); CONSTANTS];
......
}
fn add_round_key<'b, I>(&mut self, constants: &mut I, words: &mut [BlsScalar])
where
I: Iterator<Item = &'b BlsScalar>,
{
words.iter_mut().for_each(|w| {
*w += Self::next_c(constants);
});
}
- S-Box ( x ) = x 5 \text{S-Box}(x)=x^{5} S-Box(x)=x5 实现为:
fn quintic_s_box(&mut self, value: &mut BlsScalar) {
*value = value.square().square() * *value;
}
- MixLayer M ( ⋅ ) \text{M}(\cdot) M(⋅)定义在
./assets/mds.bin
中,为 5 × 5 5\times 5 5×5矩阵:
pub const MDS_MATRIX: [[BlsScalar; WIDTH]; WIDTH] = {
let bytes = include_bytes!("../assets/mds.bin");
let mut mds = [[BlsScalar::zero(); WIDTH]; WIDTH];
....
}
fn mul_matrix<'b, I>(&mut self, _constants: &mut I, values: &mut [BlsScalar])
where
I: Iterator<Item = &'b BlsScalar>,
{
let mut result = [BlsScalar::zero(); WIDTH];
for j in 0..WIDTH {
for k in 0..WIDTH {
result[k] += MDS_MATRIX[k][j] * values[j];
}
}
values.copy_from_slice(&result);
}
- full round VS partial round:【当 s = 1 s=1 s=1时,full round对所有输入进行了S-Box运算,而partial round仅对最后一个输入进行了S-Box运算。】
fn apply_partial_round<'b, I>(&mut self, constants: &mut I, words: &mut [T])
where
I: Iterator<Item = &'b BlsScalar>,
{
let last = words.len() - 1;
// Add round keys to each word
self.add_round_key(constants, words);
// Then apply quintic s-box
self.quintic_s_box(&mut words[last]);
// Multiply this result by the MDS matrix
self.mul_matrix(constants, words);
}
fn apply_full_round<'a, I>(&mut self, constants: &mut I, words: &mut [T])
where
I: Iterator<Item = &'a BlsScalar>,
{
// Add round keys to each word
self.add_round_key(constants, words);
// Then apply quintic s-box
words.iter_mut().for_each(|w| self.quintic_s_box(w));
// Multiply this result by the MDS matrix
self.mul_matrix(constants, words);
}
- 完整的HADES流程表示为:
fn perm(&mut self, data: &mut [T]) {
let mut constants = ROUND_CONSTANTS.iter();
// Apply R_f full rounds
for _ in 0..TOTAL_FULL_ROUNDS / 2 {
self.apply_full_round(&mut constants, data);
}
// Apply R_P partial rounds
for _ in 0..PARTIAL_ROUNDS {
self.apply_partial_round(&mut constants, data);
}
// Apply R_f full rounds
for _ in 0..TOTAL_FULL_ROUNDS / 2 {
self.apply_full_round(&mut constants, data);
}
}
4. HADESMiMC+ZK-SNARK 代码解析
具体代码见:
HADESMiMC+ZK-SNARK的关键是将HADESMiMC中的计算操作进行相应的转换:【详细见测试用例:hades_preimage()
】
- 1)Add Round Key:以circuit中的加法门表示:
fn add_round_key<'b, I>(&mut self, constants: &mut I, words: &mut [Variable])
where
I: Iterator<Item = &'b BlsScalar>,
{
// Add only for the first round.
//
// The remainder ARC are performed with the constant appended
// to the linear layer
if self.count == 0 {
words.iter_mut().for_each(|w| {
*w = self.cs.add(
(BlsScalar::one(), *w),
(BlsScalar::zero(), self.zero),
Self::next_c(constants),
None,
);
});
}
}
- 2)S-Box运算:以circuit中的乘法门表示:
fn quintic_s_box(&mut self, value: &mut Variable) {
let v2 = self
.cs
.mul(BlsScalar::one(), *value, *value, BlsScalar::zero(), None);
let v4 = self
.cs
.mul(BlsScalar::one(), v2, v2, BlsScalar::zero(), None);
*value = self
.cs
.mul(BlsScalar::one(), v4, *value, BlsScalar::zero(), None);
}
- 3)MixLayer中的mul_matrix运算:当 t = 5 t=5 t=5时,可才分为2个Dusk Plonk自定义
big_add
gate表示:
// Implementation optimized for WIDTH = 5
//
// c is the next round constant.
// For the partial round, it is added only for the last element
//
// The resulting array `r` will be defined as
// r[x] = sum j 0..WIDTH ( MDS[x][j] * values[j] ) + c
//
// q_l = MDS[x][0]
// q_r = MDS[x][1]
// q_4 = MDS[x][2]
// w_l = values[0]
// w_r = values[1]
// w_4 = values[2]
// r[x] = q_l · w_l + q_r · w_r + q_4 · w_4;
//
// q_l = MDS[x][3]
// q_r = MDS[x][4]
// q_4 = 1
// w_l = values[3]
// w_r = values[4]
// w_4 = r[x]
// r[x] = q_l · w_l + q_r · w_r + q_4 · w_4 + c;