use crate::artifacts::{PicPcaPayload, PicTransitionPayload};
use crate::authority::indexed::IndexedAuthorityMap;
use crate::cose::{CoseError, SigningAlgorithm};
pub trait ArtifactSigner {
fn kid(&self) -> &str;
fn cose_algorithm(&self) -> SigningAlgorithm;
fn jws_algorithm(&self) -> &str;
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, CoseError>;
}
pub trait ArtifactVerifier {
fn verify(&self, data: &[u8], signature: &[u8]) -> bool;
fn expected_jws_algorithm(&self) -> Option<&'static str> {
None
}
fn expected_cose_algorithm(&self) -> Option<SigningAlgorithm> {
None
}
}
#[cfg(feature = "ed25519")]
mod ed25519_impl {
use super::*;
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
#[derive(Debug, Clone)]
pub struct Ed25519Signer {
key: SigningKey,
kid: String,
}
impl Ed25519Signer {
pub fn new(key: SigningKey, kid: impl Into<String>) -> Self {
Self {
key,
kid: kid.into(),
}
}
pub fn verifying_key(&self) -> VerifyingKey {
self.key.verifying_key()
}
}
impl ArtifactSigner for Ed25519Signer {
fn kid(&self) -> &str {
&self.kid
}
fn cose_algorithm(&self) -> SigningAlgorithm {
SigningAlgorithm::EdDSA
}
fn jws_algorithm(&self) -> &str {
"EdDSA"
}
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, CoseError> {
Ok(self.key.sign(data).to_bytes().to_vec())
}
}
#[derive(Debug, Clone)]
pub struct Ed25519Verifier {
key: VerifyingKey,
}
impl Ed25519Verifier {
pub fn new(key: VerifyingKey) -> Self {
Self { key }
}
}
impl ArtifactVerifier for Ed25519Verifier {
fn verify(&self, data: &[u8], signature: &[u8]) -> bool {
let Ok(sig) = Signature::from_slice(signature) else {
return false;
};
self.key.verify(data, &sig).is_ok()
}
fn expected_jws_algorithm(&self) -> Option<&'static str> {
Some("EdDSA")
}
fn expected_cose_algorithm(&self) -> Option<SigningAlgorithm> {
Some(SigningAlgorithm::EdDSA)
}
}
}
#[cfg(feature = "ed25519")]
pub use ed25519_impl::{Ed25519Signer, Ed25519Verifier};
pub trait TrustedCheckpoint {
fn is_current_checkpoint(&self, exact_pca_bytes: &[u8]) -> bool;
}
pub trait RevocationCheck {
fn is_revoked(&self, checkpoint: &PicPcaPayload, exact_pca_bytes: &[u8]) -> bool;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct NoRevocation;
impl RevocationCheck for NoRevocation {
fn is_revoked(&self, _checkpoint: &PicPcaPayload, _exact_pca_bytes: &[u8]) -> bool {
false
}
}
pub trait SettlementPolicy {
fn request_binding(&self, _transition: &PicTransitionPayload) -> bool {
true
}
fn conformance(&self, _checkpoint: &PicPcaPayload, _transition: &PicTransitionPayload) -> bool {
true
}
fn policy(&self, _checkpoint: &PicPcaPayload, _next_authority: &IndexedAuthorityMap) -> bool {
true
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct DefaultPolicy;
impl SettlementPolicy for DefaultPolicy {}
#[derive(Debug, Clone, Default)]
pub struct InMemoryCheckpoints {
current: Vec<Vec<u8>>,
}
impl InMemoryCheckpoints {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, exact_pca_bytes: Vec<u8>) {
self.current.push(exact_pca_bytes);
}
pub fn replace(&mut self, old_exact_pca_bytes: &[u8], new_exact_pca_bytes: Vec<u8>) {
self.current.retain(|b| b != old_exact_pca_bytes);
self.current.push(new_exact_pca_bytes);
}
}
impl TrustedCheckpoint for InMemoryCheckpoints {
fn is_current_checkpoint(&self, exact_pca_bytes: &[u8]) -> bool {
self.current.iter().any(|b| b == exact_pca_bytes)
}
}