双线性映射
- $G_1, G_2, G_T$ 是三个阶为素数 $p$ 的循环群
- 群 $G_1$ 的生成元为 $g_1$,群 $G_2$ 的生成元为 $g_2$
- $e$ 为双线性映射 $G_1 \times G_2 \rightarrow G_T$
双线性映射性质
- 双线性:对任意 $a, b \in Z^*, u \in G_1, v \in G_2$,有 $e(u^a, v^b)=e(u, v)^{ab}$ 成立,即先指数运算再映射等于先映射后指数运算
- 非退化性:$e(g_1, g_2) \ne 1$
因此,$e(g_1, g_2)$ 是 $G_T$ 的生成元
BLS 签名
$(G_1, G_2)$ 是 co-GDH 群对,阶均为 $p$,哈希函数 $H: \left\{0,1\right\}^* \rightarrow G_1$
- 密钥生成:随机选择私钥 $x \in Z_p$,计算公钥 $v=g_2^x \in G_2$
- 签名:消息为 $m$,则签名为 $\sigma = H(m)^x \in G_1$
- 验证:$e(\sigma, g_2)=e(H(m), v)$
- 推导:$e(\sigma, g_2)=e(H(m)^x, g_2)=e(H(m), g_2)^x=e(H(m), g_2^x)=e(H(m), v)$
- 安全性:CDH 困难,则签名不可伪造
BLS 签名仅一个随机因子,即私钥,不用于交易签名,用于区块链共识投票。
BLS 聚合签名
假设 $n$ 个用户对同一个消息 $m$ 签名,则能实现批量验证。
- 随机选择 $n$ 个整数 $c_1, ...c_n \in [0, B]$,$B$ 为某个固定值
- 计算 $V = \prod_{i=1}^nv_i^{c_i} \in G_2$,$U = \prod_{i=1}^n\sigma_i^{c_i} \in G_1$
- 验证 $e(U, g_2)=e(H(m), V)$
随机数 $c_1, ..., c_n$ 起随机化作用
双线性映射计算复杂度高,尽量少算
其它群运算计算复杂度低,可以多算
推导:
$e(a\cdot b, c) = e(a, c) \cdot e(b,c)$
$e(\prod_{i=1}^na_i, b)=e(a_1 \cdot a_2... \cdot a_n, b) = e(a_1, b) \cdot ... \cdot e(a_n, b) = \prod_{i=1}^n e(a_i,b)$
$e(U, g_2)=e(\prod_{i=1}^nH(m^{x_ic_i}), g_2) = \prod_{i=1}^ne(H(m), g_2)^{x_ic_i}$
$e(H(m), V)=e(H(m), \prod_{i=1}^ng_2^{x_ic_i}) = \prod_{i=1}^ne(H(m), g_2)^{x_ic_i}= \prod_{i=1}^ne(H(m), g_2)^{x_ic_i}$
示例
#[allow(dead_code)]
fn gen_bls_signature(message: &[u8], bls_keypairs: &[(SecretKey, Vec<u8>)]) -> [u8; 96] {
let mut signatures = vec![];
let mut pubkeys = vec![];
// 用各自的私钥得到各自的签名
for (privkey, _) in bls_keypairs {
let signature = privkey.sign(message, DST.as_bytes(), &[]);
let pubkey = privkey.sk_to_pk();
signatures.push(signature);
pubkeys.push(pubkey);
}
// 把所有的签名聚合成一个签名
let signatures = signatures.iter().collect::<Vec<_>>();
let signature = AggregateSignature::aggregate(signatures.as_slice(), true)
.unwrap()
.to_signature();
// 把所有的公钥聚合成一个公钥,注意公钥的聚合顺序要和签名的聚合顺序保持一致
let pubkeys = pubkeys.iter().collect::<Vec<_>>();
let pubkey = AggregatePublicKey::aggregate(&pubkeys, false)
.unwrap()
.to_public_key();
// 用聚合后的公钥对聚合后的签名验签
let result = signature.verify(true, message, DST.as_bytes(), &[], &pubkey, false);
assert!(
result == blst::BLST_ERROR::BLST_SUCCESS,
"pubkeys not match signatures"
);
signature.compress()
}
没有评论