use num_bigint::BigUint;
use serde::{Deserialize, Serialize};
use crate::{Hash, Identity, Rand, SchnorrGroup, Sig};
#[derive(Clone, Serialize, Deserialize)]
pub struct Identification<H: Hash, S: Sig>
where
S: Sig,
H: Hash,
{
group: SchnorrGroup,
_phantom: std::marker::PhantomData<(H, S)>,
}
impl<H, S> Identification<H, S>
where
S: Sig,
H: Hash,
{
pub fn from_str(p: &str, q: &str, a: &str) -> Option<Self> {
let group = SchnorrGroup::from_str(p, q, a)?;
Some(Self {
group,
_phantom: std::marker::PhantomData,
})
}
pub fn issue_params<R: Rand>(&self, i: Identity) -> (IssueSecret, IssueParams) {
let e = R::random_number(&self.group.q);
let v = self
.group
.a
.modpow(&e, &self.group.p)
.modinv(&self.group.p)
.unwrap();
(IssueSecret { e }, IssueParams { i, v })
}
pub fn issue_certificate(&self, issue_params: IssueParams) -> IssueCertificate {
let s = S::sign(H::hash(
[issue_params.i.to_bytes_le(), issue_params.v.to_bytes_le()].concat(),
));
IssueCertificate {
params: issue_params,
s,
}
}
pub fn verification_request<R: Rand>(
&self,
certificate: IssueCertificate,
) -> (VerificationRequestSecret, VerificationRequest) {
let k = R::random_number(&self.group.q);
let y = self.group.a.modpow(&k, &self.group.p);
(
VerificationRequestSecret { k },
VerificationRequest { certificate, y },
)
}
pub fn verification_challenge<R: Rand>(
&self,
request: VerificationRequest,
) -> Option<VerificationChallenge> {
if !S::verify(
H::hash(
[
request.certificate.params.i.to_bytes_le(),
request.certificate.params.v.to_bytes_le(),
]
.concat(),
),
&request.certificate.s,
) {
return None;
}
Some(VerificationChallenge {
r: R::random_number(&self.group.q),
})
}
pub fn verification_response(
&self,
challenge: VerificationChallenge,
iss_secret: IssueSecret,
ver_secret: VerificationRequestSecret,
) -> VerificationResponse {
VerificationResponse {
p: (&ver_secret.k + &(&challenge.r * &iss_secret.e)) % &self.group.q,
}
}
pub fn verification(
&self,
request: VerificationRequest,
challenge: VerificationChallenge,
response: VerificationResponse,
) -> bool {
let lhs = (&self.group.a.modpow(&response.p, &self.group.p)
* request
.certificate
.params
.v
.modpow(&challenge.r, &self.group.p))
% &self.group.p;
let rhs = request.y;
lhs == rhs
}
}
pub struct IssueSecret {
e: BigUint,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct IssueParams {
i: Identity,
v: BigUint,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct IssueCertificate {
params: IssueParams,
s: Vec<u8>,
}
pub struct VerificationRequestSecret {
k: BigUint,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct VerificationRequest {
certificate: IssueCertificate,
y: BigUint,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct VerificationChallenge {
r: BigUint,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct VerificationResponse {
p: BigUint,
}