DKIM, ARC, SPF and DMARC authentication in Rust
DKIM Signature Verification
Section titled “DKIM Signature Verification” // Create a resolver using Cloudflare DNS let resolver = Resolver::new_cloudflare_tls().unwrap();
// Parse message let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();
// Validate signature let result = resolver.verify_dkim(&authenticated_message).await;
// Make sure all signatures passed verification assert!(result.iter().all(|s| s.result() == &DKIMResult::Pass));DKIM Signing
Section titled “DKIM Signing” // Sign an e-mail message using RSA-SHA256 let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); let signature_rsa = Signature::new() .headers(["From", "To", "Subject"]) .domain("example.com") .selector("default") .sign(RFC5322_MESSAGE.as_bytes(), &pk_rsa) .unwrap();
// Sign an e-mail message using ED25519-SHA256 let pk_ed = PrivateKey::from_ed25519( &base64_decode(ED25519_PUBLIC_KEY.as_bytes()).unwrap(), &base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(), ) .unwrap(); let signature_ed = Signature::new() .headers(["From", "To", "Subject"]) .domain("example.com") .selector("default-ed") .sign(RFC5322_MESSAGE.as_bytes(), &pk_ed) .unwrap();
// Print the message including both signatures to stdout println!( "{}{}{}", signature_rsa.to_header(), signature_ed.to_header(), RFC5322_MESSAGE );ARC Chain Verification
Section titled “ARC Chain Verification” // Create a resolver using Cloudflare DNS let resolver = Resolver::new_cloudflare_tls().unwrap();
// Parse message let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();
// Validate ARC chain let result = resolver.verify_arc(&authenticated_message).await;
// Make sure ARC passed verification assert_eq!(result.result(), &DKIMResult::Pass);ARC Chain Sealing
Section titled “ARC Chain Sealing” // Create a resolver using Cloudflare DNS let resolver = Resolver::new_cloudflare_tls().unwrap();
// Parse message to be sealed let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();
// Verify ARC and DKIM signatures let arc_result = resolver.verify_arc(&authenticated_message).await; let dkim_result = resolver.verify_dkim(&authenticated_message).await;
// Build Authenticated-Results header let auth_results = AuthenticationResults::new("mx.mydomain.org") .with_arc_result(&arc_result, "127.0.0.1".parse().unwrap());
// Seal message if arc_result.can_be_sealed() { // Seal the e-mail message using RSA-SHA256 let pk_rsa = PrivateKey::from_rsa_pkcs1_pem(RSA_PRIVATE_KEY).unwrap(); let arc_set = ARC::new(&auth_results) .domain("example.org") .selector("default") .headers(["From", "To", "Subject", "DKIM-Signature"]) .seal(&authenticated_message, &arc_result, &pk_rsa) .unwrap();
// Print the sealed message to stdout println!("{}{}", arc_set.to_header(), RFC5322_MESSAGE) } else { eprintln!("The message could not be sealed, probably an ARC chain with cv=fail was found.") }SPF Policy Evaluation
Section titled “SPF Policy Evaluation” // Create a resolver using Cloudflare DNS let resolver = Resolver::new_cloudflare_tls().unwrap();
// Verify HELO identity let result = resolver .verify_spf_helo("127.0.0.1".parse().unwrap(), "gmail.com") .await; assert_eq!(result.result(), SPFResult::Fail);
// Verify MAIL-FROM identity let result = resolver .await; assert_eq!(result.result(), SPFResult::Fail);DMARC Policy Evaluation
Section titled “DMARC Policy Evaluation” // Create a resolver using Cloudflare DNS let resolver = Resolver::new_cloudflare_tls().unwrap();
// Verify DKIM signatures let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap(); let dkim_result = resolver.verify_dkim(&authenticated_message).await;
// Verify SPF MAIL-FROM identity let spf_result = resolver .await;
// Verify DMARC let dmarc_result = resolver .verify_dmarc( &authenticated_message, &dkim_result, "example.org", &spf_result, ) .await; assert_eq!(dmarc_result.dkim_result(), &DMARCResult::Pass); assert_eq!(dmarc_result.spf_result(), &DMARCResult::Pass);More examples available on Github under the examples directory.