No description
- Rust 100%
| .forgejo/workflows | ||
| src | ||
| tests | ||
| .gitignore | ||
| build.rs | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
estd-tls
A unified TLS/DTLS wrapper for Rust that supports OpenSSL, LibreSSL, and WolfSSL with a single idiomatic API. Using estd philosophies and patterns.
Features
- Unified API: Same Rust API regardless of underlying SSL library
- Feature-Based Selection: Choose your SSL backend at compile time
openssl(default)libresslwolfssl
- TCP TLS & UDP DTLS: Encrypted streams over both transports
- Mutual TLS (mTLS): Client certificate authentication
- Crypto Primitives: Sign, verify, encrypt, decrypt
- Key Generation: RSA and EC key pairs
- Certificate Generation: Self‑signed certs, CSRs, CA signing
- Async Support: Every blocking operation has an async counterpart via
estd::sync::go - Built on estd: Uses
estdpatterns, logging, env, fs, strings, sync - No External Dependencies: Only
estdand system SSL libraries
Quick Start
use estd_tls::{Connector, ConnectorConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let connector = Connector::new();
let mut stream = connector.connect("example.com:443")?;
use std::io::{Read, Write};
stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n")?;
let mut response = Vec::new();
stream.read_to_end(&mut response)?;
println!("Version: {}", stream.version()?);
println!("Cipher: {}", stream.cipher()?);
Ok(())
}
Modules
tcp — TLS over TCP
use estd_tls::tcp::Connector;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let connector = Connector::new(); // or ::with_config(config)
let stream = connector.connect("host:443")?; // -> TlsStream
Ok(())
}
udp — DTLS over UDP
use estd_tls::udp::Connector;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let connector = Connector::new();
let stream = connector.connect("host:4433")?; // -> DtlsStream
stream.send(b"hello")?;
Ok(())
}
mtls — Mutual TLS
use estd_tls::{ConnectorConfig, mtls};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = ConnectorConfig::new()
.cert_path(Some("/path/to/client.pem".into()))
.key_path(Some("/path/to/client-key.pem".into()));
let connector = mtls::Connector::new(config)?;
let stream = connector.connect("host:443")?;
Ok(())
}
crypto — Sign / Verify / Encrypt / Decrypt
use estd_tls::crypto::{self, SignatureAlgorithm, CipherAlgorithm};
let private_key = b"stub-private-key";
let public_key = b"stub-public-key";
let data = b"hello world";
// Sign & verify
let sig = crypto::sign(private_key, data, SignatureAlgorithm::RsaSha256).unwrap();
let ok = crypto::verify(public_key, data, &sig, SignatureAlgorithm::RsaSha256).unwrap();
// Encrypt & decrypt
let key = [0u8; 32];
let ct = crypto::encrypt(&key, b"secret", CipherAlgorithm::Aes256Gcm).unwrap();
let pt = crypto::decrypt(&key, &ct, CipherAlgorithm::Aes256Gcm).unwrap();
key — Key Generation
use estd_tls::key::{self, KeyType, EcCurve};
let rsa = key::generate(&KeyType::Rsa(4096)).unwrap();
let ec = key::generate(&KeyType::Ec(EcCurve::P256)).unwrap();
let pub_key = key::public_key_from(&rsa.private_key).unwrap();
cert — Certificate Generation
use estd_tls::cert::{self, Subject};
use estd_tls::key::{self as keygen, KeyType};
let kp = keygen::generate(&KeyType::Rsa(2048)).unwrap();
let subject = Subject::new("example.com").organisation("Acme").country("FR");
let self_cert = cert::self_signed(&kp.private_key, &subject, 365).unwrap();
let csr = cert::create_csr(&kp.private_key, &subject).unwrap();
let signed = cert::sign_csr(&kp.private_key, &self_cert, &csr, 365).unwrap();
async_tls — Async Wrappers
Every blocking operation has an async counterpart that runs on a
background goroutine (via estd::sync::go):
use estd_tls::{async_tls, ConnectorConfig};
use estd_tls::key::{KeyType, EcCurve};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let handle = async_tls::connect_tcp(ConnectorConfig::new(), "host:443".into());
let stream = handle.join().unwrap()?;
let handle = async_tls::generate_key(KeyType::Ec(EcCurve::P384));
let kp = handle.join().unwrap()?;
Ok(())
}
config — ConnectorConfig
Builder pattern, implements estd::patterns::Builder<tcp::Connector>:
use estd_tls::ConnectorConfig;
let config = ConnectorConfig::new()
.verify(true)
.ca_path(Some("/path/to/ca.pem".to_string()))
.server_name(Some("example.com".to_string()))
.alpn(vec!["h2".into(), "http/1.1".into()]);
Or from environment variables (TLS_VERIFY, TLS_CA_PATH, TLS_CERT_PATH, TLS_KEY_PATH):
use estd_tls::ConnectorConfig;
let config = ConnectorConfig::from_env();
License
ISC