use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{debug, warn};
use crate::api::common::error::SecurityError;
use crate::dtls::DtlsConnection;
pub async fn generate_fingerprint(
connection: &Arc<Mutex<Option<DtlsConnection>>>,
) -> Result<String, SecurityError> {
let conn_guard = connection.lock().await;
if let Some(conn) = conn_guard.as_ref() {
if let Some(cert) = conn.local_certificate() {
let mut cert_copy = cert.clone();
match cert_copy.fingerprint("SHA-256") {
Ok(fingerprint) => Ok(fingerprint),
Err(e) => Err(SecurityError::Internal(format!(
"Failed to get fingerprint: {}",
e
))),
}
} else {
Err(SecurityError::Configuration(
"No certificate available".to_string(),
))
}
} else {
Err(SecurityError::NotInitialized(
"DTLS connection not initialized".to_string(),
))
}
}
pub async fn verify_fingerprint(
connection: &Arc<Mutex<Option<DtlsConnection>>>,
remote_fingerprint: &str,
remote_fingerprint_algorithm: &str,
) -> Result<bool, SecurityError> {
let conn_guard = connection.lock().await;
if let Some(conn) = conn_guard.as_ref() {
if let Some(cert) = conn.remote_certificate() {
let mut cert_copy = cert.clone();
let algorithm = match remote_fingerprint_algorithm.to_lowercase().as_str() {
"sha-1" => "SHA-1",
"sha-256" => "SHA-256",
"sha-384" => "SHA-384",
"sha-512" => "SHA-512",
_ => {
return Err(SecurityError::HandshakeVerification(format!(
"Unsupported fingerprint algorithm: {}",
remote_fingerprint_algorithm
)));
}
};
match cert_copy.fingerprint(algorithm) {
Ok(actual_fingerprint) => {
let expected = remote_fingerprint.replace(":", "").to_lowercase();
let actual = actual_fingerprint.replace(":", "").to_lowercase();
let matches = expected == actual;
if matches {
debug!("Fingerprint verification successful");
} else {
warn!(
"Fingerprint verification failed! Expected: {}, Actual: {}",
remote_fingerprint, actual_fingerprint
);
}
Ok(matches)
}
Err(e) => Err(SecurityError::HandshakeVerification(format!(
"Failed to generate fingerprint for verification: {}",
e
))),
}
} else {
Err(SecurityError::HandshakeVerification(
"No remote certificate available for verification".to_string(),
))
}
} else {
Err(SecurityError::NotInitialized(
"DTLS connection not initialized".to_string(),
))
}
}
pub fn get_fingerprint_algorithm() -> String {
"sha-256".to_string()
}