mod cert_encoding;
mod crypto_disabled;
mod ids;
mod url_verification;
#[cfg(feature = "xmlsec")]
mod xmlsec;
use crate::schema::CipherValue;
pub use cert_encoding::*;
pub use ids::*;
use thiserror::Error;
pub use url_verification::{sign_url, UrlVerifier, UrlVerifierError};
#[cfg(feature = "xmlsec")]
pub use xmlsec::*;
#[cfg(feature = "xmlsec")]
pub type Crypto = XmlSec;
#[cfg(not(feature = "xmlsec"))]
pub type Crypto = crypto_disabled::NoCrypto;
#[derive(Debug, Error)]
pub enum CryptoError {
#[error("Encountered an invalid signature")]
InvalidSignature,
#[error("base64 decoding Error: {}", error)]
Base64Error {
#[from]
error: base64::DecodeError,
},
#[error("The given XML is missing a root element")]
XmlMissingRootElement,
#[error("Crypto Provider Error")]
CryptoProviderError(#[source] Box<dyn std::error::Error + Send + Sync>),
#[error("The encryption method {method} is not supported for the assertion key")]
EncryptedAssertionKeyMethodUnsupported { method: String },
#[error("The encryption method {method} is not supported for the assertion value")]
EncryptedAssertionValueMethodUnsupported { method: String },
#[error("The crypto provider is not enabled so encryption and signing methods are disabled")]
CryptoDisabled,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CertificateDer(Vec<u8>);
impl CertificateDer {
pub fn der_data(&self) -> &[u8] {
&self.0
}
}
impl From<Vec<u8>> for CertificateDer {
fn from(cert_der: Vec<u8>) -> Self {
Self(cert_der)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AllowedSignatureAlgorithm {
RsaSha256,
EcdsaSha256,
RsaSha224,
RsaSha384,
RsaSha512,
EcdsaSha224,
EcdsaSha384,
EcdsaSha512,
DsaSha256,
}
impl AllowedSignatureAlgorithm {
pub fn signature_uri(&self) -> &'static str {
match self {
Self::RsaSha256 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
Self::EcdsaSha256 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
Self::RsaSha224 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha224",
Self::RsaSha384 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
Self::RsaSha512 => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
Self::EcdsaSha224 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224",
Self::EcdsaSha384 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
Self::EcdsaSha512 => "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
Self::DsaSha256 => "http://www.w3.org/2009/xmldsig11#dsa-sha256",
}
}
pub fn digest_uri(&self) -> &'static str {
match self {
Self::RsaSha224 | Self::EcdsaSha224 => "http://www.w3.org/2001/04/xmldsig-more#sha224",
Self::RsaSha256 | Self::EcdsaSha256 | Self::DsaSha256 => {
"http://www.w3.org/2001/04/xmlenc#sha256"
}
Self::RsaSha384 | Self::EcdsaSha384 => "http://www.w3.org/2001/04/xmldsig-more#sha384",
Self::RsaSha512 | Self::EcdsaSha512 => "http://www.w3.org/2001/04/xmlenc#sha512",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReduceMode {
PreDigest,
ValidateAndMark,
ValidateAndMarkNoAncestors,
}
impl Default for ReduceMode {
fn default() -> Self {
Self::ValidateAndMarkNoAncestors
}
}
pub trait CryptoProvider {
type PrivateKey;
fn verify_signed_xml<Bytes: AsRef<[u8]>>(
xml: Bytes,
x509_cert_der: &CertificateDer,
id_attribute: Option<&str>,
) -> Result<(), CryptoError>;
fn reduce_xml_to_signed(
xml_str: &str,
certs_der: &[CertificateDer],
reduce_mode: ReduceMode,
) -> Result<String, CryptoError> {
Self::reduce_xml_to_signed_with_allowed_algorithms(xml_str, certs_der, reduce_mode, None)
}
fn reduce_xml_to_signed_with_allowed_algorithms(
xml_str: &str,
certs_der: &[CertificateDer],
reduce_mode: ReduceMode,
allowed_algorithms: Option<&[AllowedSignatureAlgorithm]>,
) -> Result<String, CryptoError>;
fn decrypt_assertion_key_info(
cipher_value: &CipherValue,
method: &str,
decryption_key: &Self::PrivateKey,
) -> Result<Vec<u8>, CryptoError>;
fn decrypt_assertion_value_info(
cipher_value: &CipherValue,
method: &str,
decryption_key: &[u8],
) -> Result<Vec<u8>, CryptoError>;
fn sign_xml<Bytes: AsRef<[u8]>>(
xml: Bytes,
private_key_der: &[u8],
) -> Result<String, CryptoError>;
}