1 个不稳定版本
0.2.2 | 2020年1月16日 |
---|
#2260 在 密码学
63KB
1K SLoC
Coconut:带有分布式账本应用的阈值发行选择性披露凭证
基于 Coconut 论文,arxiv 链接,NDSS 提交。可以使用 Shamir 秘密共享或 Pedersen 可验证秘密共享(提供集中式和分布式版本)进行密钥生成。集中式密钥生成由可信第三方完成。该可信方的角色在密钥生成时结束。Pedersen 秘密共享的分布式版本可以用于避免可信第三方。
API
-
生成系统参数。
let threshold = 3; // threshold number of participants let total = 5; // total number of participants let msg_count = 6; // total attributes in credential let count_hidden = 2; // number of attributes hidden from issuers. let params = Params::new(msg_count, "test-label".as_bytes());
-
发行者的密钥生成。这可能是一个分布式密钥生成过程,或者由可信第三方完成。为了原型设计,代码使用了后者。
// Below is an example of keys generated with Shamir secret sharing // signers is a vector of struct `Signer` which corresponds to a single signer and contains a signer id, a signing and a // verification key pub struct Signer { pub id: usize, pub sigkey: Sigkey, pub verkey: Verkey, } let (_, _, signers: Vec<Signer>) = trusted_party_SSS_keygen(threshold, total, ¶ms); // Below is an example of Pedersen verifiable secret sharing let (g, h) = PedersenVSS::gens("testPVSS-label".as_bytes()); // `secret_x` and `secret_y` are the combined secrets and should never be given away. Only use for testing. // `x_shares` an `y_shares` are shares of the secrets x and y (vector) // `comm_coeff_x` and `comm_coeff_y` are commitments to coefficients of polynomial used to share `secret_x` and `secret_y` // `signers` is a vector of struct `Signer` like above let ( secret_x, secret_y, signers, _, comm_coeff_x, x_shares, x_t_shares, _, comm_coeff_y, y_shares, y_t_shares, ) = trusted_party_PVSS_keygen(threshold, total, ¶ms, &g, &h); // Each participant can verify its share as PedersenVSS::verify_share( threshold, participant_id, (&x_shares[&i], &x_t_shares[&i]), &comm_coeff_x, &g, &h ) PedersenVSS::verify_share( threshold, participant_id, (&y_shares[j][&i], &y_t_shares[j][&i]), &comm_coeff_y[j], &g, &h )
还提供了一种分布式(无需可信第三方)的可验证秘密共享,可用于密钥生成。使用
PedersenDVSSParticipant
。查看测试test_Pedersen_DVSS
、test_keygen_reconstruction_decentralized_verifiable_secret_sharing
、test_sign_verify_decentralized_verifiable_secret_sharing_keygen
分别了解秘密共享、密钥生成和签名的示例。 -
用户获取其属性,生成 Elgamal 密钥对并创建一个签名请求发送给签名者(发行者)。
let msgs = FieldElementVector::random(msg_count); let (elg_sk, elg_pk) = elgamal_keygen!(¶ms.g1); // sig_req is the signature request. randomness will be used to create proof of knowledge of // various elements in the signature request let (sig_req, randomness) = SignatureRequest::new(&msgs, count_hidden, &elg_pk, ¶ms);
-
创建对隐藏消息、Elgamal 秘密密钥等的知识证明。
// Initiate proof of knowledge of various items of Signature request let sig_req_pok = SignatureRequestPoK::init(&sig_req, &elg_pk, ¶ms); // The challenge can include other things also (if proving other predicates) let challenge = FieldElement::from_msg_hash(&sig_req_pok.to_bytes()); // Create proof once the challenge is finalized let hidden_msgs: FieldElementVector = msgs .iter() .take(count_hidden) .map(|m| m.clone()) .collect::<Vec<FieldElement>>() .into(); let sig_req_proof = sig_req_pok .gen_proof(&hidden_msgs, randomness, &elg_sk, &challenge) .unwrap();
-
每个签名者将验证该证明并创建一个盲签名发送回用户。
assert!(sig_req_proof.verify(&sig_req, &elg_pk, &challenge, ¶ms)); let blinded_sig = BlindSignature::new(&sig_req, &sig_key);
-
用户解盲签名并验证签名的正确性。
let unblinded_sig = blinded_sig.unblind(&elg_sk); unblinded_sig.verify(&msgs, &verkey, ¶ms);
-
用户聚合未解盲的签名并验证聚合签名的正确性。
let aggr_sig = Signature::aggregate(threshold, unblinded_sigs); // keys is a vector of tuples containing signer id and verification key (usize, Verkey) let aggr_vk = Verkey::aggregate( threshold, keys ); assert!(aggr_sig.verify(&msgs, &aggr_vk, ¶ms));
-
为了证明对签名的知识,将验证密钥和签名转换为适当的结构,然后使用类似于上述的 Schnorr 协议。
let ps_verkey = transform_to_PS_verkey(&aggr_vk, ¶ms); let ps_sig = transform_to_PS_sig(&aggr_sig); // Empty HashSet indicates that no message is being revealed, only knowledge of signature is proved let pok = PoKOfSignature::init(&ps_sig, &ps_verkey, msgs.as_slice(), HashSet::new()).unwrap(); let chal = FieldElement::from_msg_hash(&pok.to_bytes()); let proof = pok.gen_proof(&chal).unwrap(); // The verifier verifies the proof. Empty HashMap indicates the no message was revealed assert!(proof.verify(&ps_verkey, HashMap::new(), &chal).unwrap());
-
为了证明对签名和揭示一些消息的知识,证明者将揭示的消息索引指定给
PoKOfSignature
。let ps_verkey = transform_to_PS_verkey(&aggr_vk, ¶ms); let ps_sig = transform_to_PS_sig(&aggr_sig); // Reveal the following messages to the verifier let mut revealed_msg_indices = HashSet::new(); revealed_msg_indices.insert(3); revealed_msg_indices.insert(5); let pok = PoKOfSignature::init(&ps_sig, &ps_verkey, msgs.as_slice(), revealed_msg_indices.clone()).unwrap(); let chal = FieldElement::from_msg_hash(&pok.to_bytes()); let proof = pok.gen_proof(&chal).unwrap(); // The prover reveals these messages let mut revealed_msgs = HashMap::new(); for i in &revealed_msg_indices { revealed_msgs.insert(i.clone(), msgs[*i].clone()); } // The verifier verifies the proof, passing the revealed messages assert!(proof.verify(&ps_verkey, revealed_msgs.clone(), &chal).unwrap());
待定
- 错误处理。从非测试代码中的断言开始。
- 文档
- 基准测试
依赖项
~5MB
~91K SLoC