use std::sync::Arc;
use tokio::sync::Mutex;
use tracing::{debug, error, info, 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()
}