use crate::tools::types::{Id, PQCommitmentBytes, VerificationKeyBytes};
use crate::tools::{hashing};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct ClientId {
pub verification_key_bytes: VerificationKeyBytes,
pub pq_commitment_bytes: PQCommitmentBytes,
pub id: Id,
}
impl ClientId {
pub fn id_hex(&self) -> String {
hex::encode(self.id)
}
}
impl fmt::Display for ClientId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "id={}", self.id_hex(), )
}
}
impl ClientId {
pub fn new(verification_key_bytes: VerificationKeyBytes, pq_commitment_bytes: PQCommitmentBytes) -> anyhow::Result<Self> {
let id = ClientId::id_from_parts(&verification_key_bytes, &pq_commitment_bytes)?;
Ok(Self {
verification_key_bytes,
pq_commitment_bytes,
id,
})
}
pub fn verify(&self) -> anyhow::Result<()> {
let id = ClientId::id_from_parts(&self.verification_key_bytes, &self.pq_commitment_bytes)?;
if id != self.id {
anyhow::bail!("ClientID pow does not verify");
}
Ok(())
}
pub fn id_from_parts(verification_key_bytes: &VerificationKeyBytes, pq_commitment_bytes: &PQCommitmentBytes) -> anyhow::Result<Id> {
let hash = hashing::hash_multiple(&[verification_key_bytes.as_ref(), pq_commitment_bytes.as_ref()]);
Id::from_hash(hash)
}
}
#[cfg(test)]
mod tests {
use crate::tools::client_id::ClientId;
use crate::tools::keys::Keys;
#[tokio::test]
async fn verify_test() -> anyhow::Result<()> {
let keys = Keys::from_rnd(false)?;
let client_id = ClientId::new(keys.verification_key_bytes, keys.pq_commitment_bytes)?;
client_id.verify()?;
{
let mut client_id = client_id.clone();
client_id.verification_key_bytes.0[0] = 255 - client_id.verification_key_bytes.0[0];
let result = client_id.verify();
anyhow::ensure!(result.is_err(), "Verification should fail when verification key is modified");
}
{
let mut client_id = client_id.clone();
client_id.pq_commitment_bytes.0[0] = 255 - client_id.pq_commitment_bytes.0[0];
let result = client_id.verify();
anyhow::ensure!(result.is_err(), "Verification should fail when pq_commitment_bytes is modified");
}
Ok(())
}
}