更加具体的介绍,网上很多,此处不赘述。
1、 p k pk pk代表私钥, P = p k ∗ G P=pk*G P=pk∗G代表公钥, m s g msg msg代表要签名的消息
2、签名: S i g = p k ∗ H ( m s g ) Sig=pk*H(msg) Sig=pk∗H(msg) ,其中 H ( m s g ) H(msg) H(msg)为 m s g msg msg经过哈希运算得到的摘要信息
我们可以使用公钥 P P P来验证签名。
验证过程可理解为:验证 公钥 和 消息 的哈希值(曲线上的两点) 与 曲线基点 G G G(也称:生成点)和 签名(曲线上的另外两个点)是否映射到同一个数。
e ( P , H ( m s g ) ) = e ( G , S i g ) e(P,H(msg))=e(G,Sig) e(P,H(msg))=e(G,Sig)
对于比特币来说,BLS极度优美。
一个区块中包含若干笔交易,每笔交易都有对应的签名(记为 s i g n sig_n sign),将每笔交易的签名进行简单聚合,可得到聚合签名 S i g Sig Sig
S i g = S i g 1 + S i g 2 + S i g 3 + . . . + S i g n Sig=Sig_1+Sig_2+Sig_3+...+Sig_n Sig=Sig1+Sig2+Sig3+...+Sign
聚合签名验证即为验证:
e ( G , S i g ) = e ( P 1 , H ( m s g 1 ) ) ∗ e ( P 2 , H ( m s g 2 ) ) ∗ . . . ∗ e ( P n , H ( m s g n ) ) e(G,Sig)=e(P_1,H(msg_1))*e(P_2,H(msg_2))*...*e(P_n,H(msg_n)) e(G,Sig)=e(P1,H(msg1))∗e(P2,H(msg2))∗...∗e(Pn,H(msgn))
即:知晓聚合签名、签名者的公钥、和每笔交易的摘要信息,即可同时验证多比交易。
上述等式推导过程:(选择性观看)
e ( G , S i g ) = e ( G , S i g 1 + S i g 2 + S i g 3 + . . . + S i g n ) = e ( G , p k 1 ∗ H ( m s g 1 ) + p k 2 ∗ H ( m s g 2 ) + . . . + p k n ∗ H ( m s g n ) ) = e ( G , p k 1 ∗ H ( m s g 1 ) ) ∗ e ( G , p k 2 ∗ H ( m s g 2 ) ) ∗ . . ∗ e ( G , p k n ∗ H ( m s g n ) ) = e ( p k 1 ∗ G , H ( m s g 1 ) ∗ e ( p k 2 ∗ G , H ( m s g 2 ) ∗ . . . ∗ e ( p k n ∗ G , H ( m s g n ) = e ( P 1 , H ( m s g 1 ) ) ∗ e ( P 2 , H ( m s g 2 ) ) ∗ . . . ∗ e ( P n , H ( m s g n ) ) e(G,Sig)\\=e(G,Sig_1+Sig_2+Sig_3+...+Sig_n)\\=e(G,pk_1*H(msg_1)+pk_2*H(msg_2)+...+pk_n*H(msg_n))\\=e(G,pk_1*H(msg_1))*e(G,pk_2*H(msg_2))*..*e(G,pk_n*H(msg_n))\\=e(pk_1*G,H(msg_1)*e(pk_2*G,H(msg_2)*...*e(pk_n*G,H(msg_n)\\=e(P_1,H(msg_1))*e(P_2,H(msg_2))*...*e(P_n,H(msg_n)) e(G,Sig)=e(G,Sig1+Sig2+Sig3+...+Sign)=e(G,pk1∗H(msg1)+pk2∗H(msg2)+...+pkn∗H(msgn))=e(G,pk1∗H(msg1))∗e(G,pk2∗H(msg2))∗..∗e(G,pkn∗H(msgn))=e(pk1∗G,H(msg1)∗e(pk2∗G,H(msg2)∗...∗e(pkn∗G,H(msgn)=e(P1,H(msg1))∗e(P2,H(msg2))∗...∗e(Pn,H(msgn))
应用聚合签名技术,可大大提升区块的验证速度!!!
主要考虑应用到联盟链共识机制中,收集投票信息时采用!!!
可以降低主副节点间的通信复杂度!!!敲重点!!!
实际场景:系统内的所有节点需要针对一个信息(记为 m s g msg msg)进行投票
其中:
i - 节点私钥: p k i pk_i pki
ii - 节点公钥: P i = p k i ∗ G P_i=pk_i*G Pi=pki∗G
1、聚合:
(1)聚合公钥: P = p k 1 + p k 2 + . . . + p k n P=pk_1+pk_2+...+pk_n P=pk1+pk2+...+pkn
(ps:聚合公钥的计算方式有很多种,为了提升系统的安全系数,一般不会仅是进行加减法!!!本文方便理解,以加法为例。)
(2)聚合签名: S i g = S i g 1 + S i g 2 + S i g 3 + . . . + S i g n Sig=Sig_1+Sig_2+Sig_3+...+Sig_n Sig=Sig1+Sig2+Sig3+...+Sign
2、签名验证:
即为验证: e ( G , S i g ) = e ( P , H ( m s g ) ) e(G,Sig)=e(P,H(msg)) e(G,Sig)=e(P,H(msg))
推导:(选择性看)
e ( G , S i g ) = e ( G , S i g 1 + S i g 2 + . . . + S i g n ) = e ( G , ( p k 1 + p k 2 + . . . + p k n ) ∗ H ( m s g ) ) = e ( ( p k 1 + p k 2 + . . . + p k n ) ∗ G , H ( m s g ) ) = e ( P 1 + P 2 + . . . + P 3 , H ( m s g ) ) = e ( P , H ( m s g ) ) e(G,Sig)\\=e(G,Sig_1+Sig_2+...+Sig_n)\\=e(G,(pk_1+pk_2+...+pk_n)*H(msg)) \\=e((pk_1+pk_2+...+pk_n)*G,H(msg))\\ =e(P_1+P_2+...+P_3,H(msg))\\=e(P,H(msg)) e(G,Sig)=e(G,Sig1+Sig2+...+Sign)=e(G,(pk1+pk2+...+pkn)∗H(msg))=e((pk1+pk2+...+pkn)∗G,H(msg))=e(P1+P2+...+P3,H(msg))=e(P,H(msg))
实际场景:系统内的部分节点对一个信息进行投票。
同样:
i - 节点私钥: p k i pk_i pki
ii - 节点公钥: P i = p k i ∗ G P_i=pk_i*G Pi=pki∗G
两个哈希函数:(注意区分)
i - 普通哈希函数 h a s h ( m ) hash(m) hash(m),结果为 一个 数字;
ii - 曲线哈希函数 H ( x ) H(x) H(x),结果为曲线上的点!!!
步骤:
1、初始化:保证签名者之后无需通信
(1)聚合公钥: P = a 1 ∗ P 1 + a 2 ∗ P 2 + . . . + a n ∗ P n P=a_1*P_1+a_2*P_2+...+a_n*P_n P=a1∗P1+a2∗P2+...+an∗Pn
补充说明:关于 a n a_n an, a n a_n an是一个数字,计算方式有多种,本文取
a i = h a s h ( P i , ( P 1 , P 2 , . . . , P n ) ) a_i=hash(P_i,(P_1,P_2,...,P_n)) ai=hash(Pi,(P1,P2,...,Pn))
(2)成员密钥:
成员密钥的作用:验证 该成员 确实是 签名组 (我自己起的名字,可能不太准确)内的成员!!!
M K i = ( a 1 ∗ p k 1 ) ∗ H ( P , i ) + ( a 2 ∗ p k 2 ) ∗ H ( P , i ) + . . . + ( a n ∗ p k n ) ∗ H ( P , i ) MK_i=(a_1*pk_1)*H(P,i)+(a_2*pk_2)*H(P,i)+...+(a_n*pk_n)*H(P,i) MKi=(a1∗pk1)∗H(P,i)+(a2∗pk2)∗H(P,i)+...+(an∗pkn)∗H(P,i)
成员密钥的验证: e ( G , M K i ) = e ( P , H ( P , i ) ) e(G,MK_i)=e(P,H(P,i)) e(G,MKi)=e(P,H(P,i))
推导:(选择性观看!!!)
e ( G , M K i ) = e ( G , ( a 1 ∗ p k 1 ) ∗ H ( P , i ) + ( a 2 ∗ p k 2 ) ∗ H ( P , i ) + . . . + ( a n ∗ p k n ) ∗ H ( P , i ) ) = e ( G , ( a 1 ∗ p k 1 + a 2 ∗ p k 2 + . . . + a n ∗ p k n ) ∗ H ( P , i ) ) = e ( ( a 1 ∗ p k 1 + a 2 ∗ p k 2 + . . . + a n ∗ p k n ) ∗ G , H ( P , i ) ) = e ( a 1 ∗ ( p k 1 ∗ G ) + a 2 ∗ ( p k 2 ∗ G ) + . . . + a n ∗ ( p k n ∗ G ) , H ( P , i ) ) = e ( a 1 ∗ P 1 + a 2 ∗ P 2 + . . . + a n ∗ P n , H ( P , i ) ) = e ( P , H ( P , i ) ) e(G,MK_i)\\=e(G,(a_1*pk_1)*H(P,i)+(a_2*pk_2)*H(P,i)+...+(a_n*pk_n)*H(P,i))\\=e(G,(a_1*pk_1+a_2*pk_2+...+a_n*pk_n)*H(P,i))\\=e((a_1*pk_1+a_2*pk_2+...+a_n*pk_n)*G,H(P,i))\\=e(a_1*(pk_1*G)+a_2*(pk_2*G)+...+a_n*(pk_n*G),H(P,i))\\=e(a_1*P_1+a_2*P_2+...+a_n*P_n,H(P,i))\\=e(P,H(P,i)) e(G,MKi)=e(G,(a1∗pk1)∗H(P,i)+(a2∗pk2)∗H(P,i)+...+(an∗pkn)∗H(P,i))=e(G,(a1∗pk1+a2∗pk2+...+an∗pkn)∗H(P,i))=e((a1∗pk1+a2∗pk2+...+an∗pkn)∗G,H(P,i))=e(a1∗(pk1∗G)+a2∗(pk2∗G)+...+an∗(pkn∗G),H(P,i))=e(a1∗P1+a2∗P2+...+an∗Pn,H(P,i))=e(P,H(P,i))
2、聚合签名
如果使用私钥 p k 1 , p k 2 , . . . , p k m pk_1,pk_2,...,pk_m pk1,pk2,...,pkm对交易进行签名,我们会生成m个签名:
S i g 1 = p k 1 ∗ H ( P , m ) + M K 1 Sig_1=pk_1*H(P,m)+MK_1 Sig1=pk1∗H(P,m)+MK1
S i g 2 = p k 2 ∗ H ( P , m ) + M K 2 Sig_2=pk_2*H(P,m)+MK_2 Sig2=pk2∗H(P,m)+MK2
…
S i g m = p k m ∗ H ( P , m ) + M K m Sig_m=pk_m*H(P,m)+MK_m Sigm=pkm∗H(P,m)+MKm
聚合签名:
( S ′ , P ′ ) = ( S i g 1 + S i g 2 + . . . + S i g m , P 1 + P 2 + . . . . + P m ) (S',P')=(Sig_1+Sig_2+...+Sig_m,P_1+P_2+....+P_m) (S′,P′)=(Sig1+Sig2+...+Sigm,P1+P2+....+Pm)
3、签名验证
(m,n)多重签名验证即为验证等式:
e ( G , S ′ ) = e ( P ′ , H ( p , m ) ) ∗ e ( P ′ , H ( P , 1 ) + H ( P , 2 ) + . . . + H ( P , m ) ) e(G,S')=e(P',H(p,m))*e(P',H(P,1)+H(P,2)+...+H(P,m)) e(G,S′)=e(P′,H(p,m))∗e(P′,H(P,1)+H(P,2)+...+H(P,m))
推导:(选择性看!!!)
e ( G , S ′ ) = e ( G , S i g 1 + S i g 2 + . . . + S i g m ) = e ( G , p k 1 ∗ H ( P , m ) + p k 2 ∗ H ( P , m ) + . . . + p k m ∗ H ( P , m ) + M K 1 + M K 2 + . . . + M K m ) = e ( G , p k 1 ∗ H ( P , m ) + p k 2 ∗ H ( P , m ) + . . . + p k m ∗ H ( P , m ) ) ∗ e ( G , M K 1 + M K 2 + . . . + M K m ) = e ( G ∗ ( p k 1 + p k 2 + . . . + p k m ) , H ( P , m ) ) ∗ e ( G , ( a 1 ∗ p k 1 + a 2 ∗ p k 2 + . . . + a m ∗ p k m ) ∗ ( H ( P , 1 ) + H ( P , 2 ) + . . . + H ( P , m ) ) ) = e ( P ′ , H ( P , m ) ) ∗ e ( P ′ , H ( P , 1 ) + H ( P , 2 ) + . . . + H ( P , m ) ) e(G,S')\\=e(G,Sig_1+Sig_2+...+Sig_m)\\=e(G,pk_1*H(P,m)+pk_2*H(P,m)+...+pk_m*H(P,m)+MK_1+MK_2+...+MK_m)\\=e(G,pk_1*H(P,m)+pk_2*H(P,m)+...+pk_m*H(P,m))*e(G,MK_1+MK_2+...+MK_m)\\=e(G*(pk_1+pk_2+...+pk_m),H(P,m))*\\e(G,(a_1*pk_1+a_2*pk_2+...+a_m*pk_m)*(H(P,1)+H(P,2)+...+H(P,m)))\\=e(P',H(P,m))*e(P',H(P,1)+H(P,2)+...+H(P,m)) e(G,S′)=e(G,Sig1+Sig2+...+Sigm)=e(G,pk1∗H(P,m)+pk2∗H(P,m)+...+pkm∗H(P,m)+MK1+MK2+...+MKm)=e(G,pk1∗H(P,m)+pk2∗H(P,m)+...+pkm∗H(P,m))∗e(G,MK1+MK2+...+MKm)=e(G∗(pk1+pk2+...+pkm),H(P,m))∗e(G,(a1∗pk1+a2∗pk2+...+am∗pkm)∗(H(P,1)+H(P,2)+...+H(P,m)))=e(P′,H(P,m))∗e(P′,H(P,1)+H(P,2)+...+H(P,m))
1、配对函数不好得到;
2、配对消耗时间,签名验证不高效
很早以前写的了,不保证能运行成功。
public class Pki<R, T> {
Map
public static Map<Integer, BigInteger> privKeys = new HashMap<>();//分私钥(PKI保存)
//Map
public static Map<Integer, Element> pubKeys = new HashMap<>();//分公钥(需要公布)
//Map
public static Map<Integer, KeyInfo> keyInfos = new HashMap<>();
//初始化 - 一旦生成,就不可变!
public static final Pairing bp = PairingFactory.getPairing("a.properties");
public static final Field G1 = bp.getG1();
public static final Field Zr = bp.getZr();
public static final Element g = G1.newRandomElement().getImmutable();
public static final int CERTAINTY = 256;
public static final SecureRandom random = new SecureRandom();
//(Element)主公钥/主私钥
//(BigInteger)主私钥(Element)转换称为(BigInteger)形式,作为(secret)进行分割
private static final Element privateMaster = Zr.newRandomElement();//主私钥(私有)
public static final Element publicMaster = g.duplicate().powZn(privateMaster);//主公钥(目前没有什么作用)
private static final BigInteger secret = privateMaster.toBigInteger();
public static final BigInteger prime = new BigInteger(secret.bitLength() + 1, CERTAINTY, random);
public static void split(final BigInteger secret, int needed, int available, BigInteger prime, Random random) {
/*
* split(final BigInteger secret, int needed, int available, BigInteger prime, Random random)
* - secret - 待分割的秘密
* - needed - 几份可拼凑成完整的
* - available - 分成几份
* - prime - 大素数
* - random - 随机数
*
* 此函数执行后,会将:privKeys,pubKeys填满
* */
final BigInteger[] coeff = new BigInteger[needed];
coeff[0] = secret;
for (int i = 1; i < needed; i++) {
BigInteger r;
while (true) {
r = new BigInteger(prime.bitLength(), random);
//r>0 && r
if (r.compareTo(BigInteger.ZERO) > 0 && r.compareTo(prime) < 0) {
break;//强制为+
}
}
coeff[i] = r;
}
for (int x = 1; x <= available; x++) {
BigInteger privKey = secret;
for (int exp = 1; exp < needed; exp++) {
privKey = privKey.add(coeff[exp].multiply(BigInteger.valueOf(x).pow(exp)));
}
privKeys.put(x, privKey);
Element pubKey = g.pow(privKey).getImmutable();
pubKeys.put(x, pubKey);
KeyInfo keyInfo = new KeyInfo(pubKey, privKey);
keyInfos.put(x, keyInfo);
}
}
}
KeyInfo
import it.unisa.dia.gas.jpbc.Element;
import java.math.BigInteger;
public class KeyInfo {
private Element publicKey;
private BigInteger privKey;
public KeyInfo() {
}
public KeyInfo(Element publicKey, BigInteger privKey) {
this.publicKey = publicKey;
this.privKey = privKey;
}
@Override
public String toString() {
return "KeyInfo{" +
"publicKey=" + publicKey +
", privKey=" + privKey +
'}';
}
public Element getPublicKey() {
return this.publicKey;
}
public void setPublicKey(Element publicKey) {
this.publicKey = publicKey;
}
public BigInteger getPrivKey() {
return this.privKey;
}
public void setPrivKey(BigInteger privKey) {
this.privKey = privKey;
}
}
关于属性是否私有的设置:public ,private
根据个人需要,自行设置即可!
一般要做数据传输的话,privateKey会设置成private(非全网可见),publicKey设置成public(全网可见)
此程序存在一定的缺陷,此处列出:
1.关于prime,没有进行处理;只是简单实现了门限签名的原理
不添加prime,可以成功分割签名,但是做不到聚合签名验证,验证会出现不一致!实际与理想 差了一个mod prime!!! 如有需要,请自己补充!(ps:博主能力有限,想了好几天没搞出来)