scal3 0.4.1

Verify that systems operate under your sole control (prototype, patent pending)
Documentation
use crate::api::*;
use crate::domain;
use crate::domain::{challenge_from_bytes, pk_recipient_from_bytes, pk_sender_from_bytes, KemPublicKey};
use hpke::{Deserializable, Serializable};
use p256::elliptic_curve::generic_array::GenericArray;
use p256::elliptic_curve::sec1::ToEncodedPoint;
use rand_chacha::rand_core::SeedableRng;
use rand_chacha::ChaCha20Rng;

pub(crate) fn register(
    mask: &Mask,
    randomness: &Randomness,
    provider: &Key,
) -> Option<(Key, Verifier)> {
    let provider = p256::PublicKey::from_sec1_bytes(provider).ok()?;
    let pk_kem_provider: KemPublicKey = KemPublicKey::from_bytes(&provider.to_encoded_point(false).as_bytes()).ok()?;
    let mut rng = ChaCha20Rng::from_seed(*randomness);
    let verifier = domain::Verifier::new(&pk_kem_provider, mask, &mut rng);
    let mut subscriber: Key = [0u8; 33];
    subscriber.copy_from_slice(
        p256::PublicKey::from_sec1_bytes(&verifier.pk_kem_subscriber.to_bytes())
            .ok()?
            .to_encoded_point(true)
            .as_bytes(),
    );
    let mut verifier_array = [0u8; 250];
    verifier_array.copy_from_slice(&verifier.to_bytes());
    Some((subscriber, verifier_array))
}

pub(crate) fn authenticate(
    mask: &Mask,
    randomness: &Randomness,
    provider: &Key,
    subscriber: &Key,
    verifier: &Verifier,
    challenge: &Challenge,
    client_data_hash: &Digest,
) -> Option<(domain::Authentication, Digest)> {
    let provider = pk_recipient_from_bytes(provider)?;
    let subscriber = pk_sender_from_bytes(subscriber)?;
    let verifier = domain::Verifier::from_bytes(verifier)?;
    if subscriber.to_bytes() != verifier.pk_kem_subscriber.to_bytes() {
        return None
    }
    let challenge = challenge_from_bytes(challenge)?;
    let mut rng = ChaCha20Rng::from_seed(*randomness);
    let authentication = verifier.authenticate(mask, &challenge, &provider, &mut rng, client_data_hash);
    let digest = authentication.to_device_sign;
    Some((authentication, digest))
}

pub(crate) fn pass(authentication: domain::Authentication, proof: &Proof) -> Option<(Key, Pass)> {
    let bytes = GenericArray::clone_from_slice(proof);
    let signature = p256::ecdsa::Signature::from_bytes(&bytes).ok()?;
    let pass = &authentication.finalize(&signature);
    let key = p256::PublicKey::from_sec1_bytes(&authentication.pk_s.to_bytes()).ok()?;
    let mut buf = [0u8; 33];
    buf.copy_from_slice(key.to_encoded_point(true).as_bytes());
    Some((buf, pass.to_bytes()))
}