1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::errors::prelude::*;
use crate::keys::prelude::*;
use crate::pok_sig::prelude::*;
/// The verifier of a signature or credential asks for messages to be revealed from
/// a prover and checks the signature proof of knowledge against a trusted issuer's public key.
use crate::{
    HashElem, ProofChallenge, ProofNonce, ProofRequest, RandomElem, SignatureMessage,
    SignatureProof,
};
use std::collections::BTreeSet;

/// This struct represents an Verifier of signatures.
/// Provided are methods for generating a context to ask for revealed messages
/// and the prover keep all others hidden.
pub struct Verifier;

impl Verifier {
    /// Create a nonce used for the zero-knowledge proof context
    /// verkey: issuer's public key
    pub fn new_proof_request(
        revealed_message_indices: &[usize],
        verkey: &PublicKey,
    ) -> Result<ProofRequest, BBSError> {
        let revealed_messages = revealed_message_indices
            .iter()
            .copied()
            .collect::<BTreeSet<usize>>();
        for i in &revealed_messages {
            if *i > verkey.h.len() {
                return Err(BBSErrorKind::PublicKeyGeneratorMessageCountMismatch(
                    *i,
                    verkey.h.len(),
                )
                .into());
            }
        }
        Ok(ProofRequest {
            revealed_messages,
            verification_key: verkey.clone(),
        })
    }

    /// Check a signature proof of knowledge and selective disclosure proof
    pub fn verify_signature_pok(
        proof_request: &ProofRequest,
        signature_proof: &SignatureProof,
        nonce: &ProofNonce,
    ) -> Result<Vec<SignatureMessage>, BBSError> {
        let mut challenge_bytes = signature_proof.proof.get_bytes_for_challenge(
            proof_request.revealed_messages.clone(),
            &proof_request.verification_key,
        );
        challenge_bytes.extend_from_slice(&nonce.to_bytes_uncompressed_form()[..]);

        let challenge_verifier = ProofChallenge::hash(&challenge_bytes);
        match signature_proof.proof.verify(
            &proof_request.verification_key,
            &signature_proof.revealed_messages,
            &challenge_verifier,
        )? {
            PoKOfSignatureProofStatus::Success => Ok(signature_proof
                .revealed_messages
                .iter()
                .map(|(_, m)| m.clone())
                .collect::<Vec<SignatureMessage>>()),
            e => Err(BBSErrorKind::InvalidProof { status: e }.into()),
        }
    }

    /// Create a nonce used for the proof request context
    pub fn generate_proof_nonce() -> ProofNonce {
        ProofNonce::random()
    }
}