#secret-sharing #shamir-secret-sharing #distributed #threshold #credentials #selective #issuance

coconut_sig

Coconut:带有分布式账本应用的阈值发行选择性披露凭证

1 个不稳定版本

0.2.2 2020年1月16日

#2260密码学

Apache-2.0

63KB
1K SLoC

Coconut:带有分布式账本应用的阈值发行选择性披露凭证

基于 Coconut 论文,arxiv 链接NDSS 提交。可以使用 Shamir 秘密共享或 Pedersen 可验证秘密共享(提供集中式和分布式版本)进行密钥生成。集中式密钥生成由可信第三方完成。该可信方的角色在密钥生成时结束。Pedersen 秘密共享的分布式版本可以用于避免可信第三方。

API

  1. 生成系统参数。

    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());
    
  2. 发行者的密钥生成。这可能是一个分布式密钥生成过程,或者由可信第三方完成。为了原型设计,代码使用了后者。

       // 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, &params);
       
       // 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, &params, &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_DVSStest_keygen_reconstruction_decentralized_verifiable_secret_sharingtest_sign_verify_decentralized_verifiable_secret_sharing_keygen 分别了解秘密共享、密钥生成和签名的示例。

  3. 用户获取其属性,生成 Elgamal 密钥对并创建一个签名请求发送给签名者(发行者)。

    let msgs = FieldElementVector::random(msg_count);
    let (elg_sk, elg_pk) = elgamal_keygen!(&params.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, &params);
    
  4. 创建对隐藏消息、Elgamal 秘密密钥等的知识证明。

    // Initiate proof of knowledge of various items of Signature request
    let sig_req_pok = SignatureRequestPoK::init(&sig_req, &elg_pk, &params);
    
    // 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();
    
  5. 每个签名者将验证该证明并创建一个盲签名发送回用户。

    assert!(sig_req_proof.verify(&sig_req, &elg_pk, &challenge, &params));
    let blinded_sig = BlindSignature::new(&sig_req, &sig_key);
    
  6. 用户解盲签名并验证签名的正确性。

    let unblinded_sig = blinded_sig.unblind(&elg_sk);
    unblinded_sig.verify(&msgs, &verkey, &params);
    
  7. 用户聚合未解盲的签名并验证聚合签名的正确性。

    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, &params));
    
  8. 为了证明对签名的知识,将验证密钥和签名转换为适当的结构,然后使用类似于上述的 Schnorr 协议。

    let ps_verkey = transform_to_PS_verkey(&aggr_vk, &params);
    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());
    
  9. 为了证明对签名和揭示一些消息的知识,证明者将揭示的消息索引指定给 PoKOfSignature

       let ps_verkey = transform_to_PS_verkey(&aggr_vk, &params);
       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());
    

待定

  1. 错误处理。从非测试代码中的断言开始。
  2. 文档
  3. 基准测试

依赖项

~5MB
~91K SLoC