Crafting a Secure Server-to-Server Handshake with Rust & OpenSSL

Hello there, fellow tech enthusiast! 🦀

Crafting a Secure Server-to-Server Handshake with Rust & OpenSSL

Hello there, fellow tech enthusiast! 🦀

If you’ve been itching to give your servers a unique secret handshake that only they understand, you’ve come to the right place. Today, we’re venturing into the world of secure server-to-server handshakes, using the powerful combo of Rust and OpenSSL.

Why Choose Rust & OpenSSL?

First off, Rust is like that reliable friend you can always count on. It promises safety without compromising on speed, making it a favorite for projects like ours. On the other side, we have OpenSSL, a time-tested toolkit for ensuring secure communications over digital networks. Combine these two, and you’ve got yourself a dynamic duo!

The openssl Crate in the Limelight

The openssl crate serves as a bridge between the Rust programming language and the OpenSSL library. OpenSSL itself is a titan in the world of security, boasting a storied history spanning decades. Given its crucial role in web security, having a performant and type-safe interface in Rust is immensely valuable. The openssl crate is more than just a wrapper; it integrates OpenSSL's raw power into the Rust paradigm, ensuring memory safety and concurrency benefits.

Deep Dive into Features

  1. Cryptography:
  • Symmetric Encryption: Using algorithms like AES, it supports encryption where the same key is used for both encryption and decryption.
  • Asymmetric Encryption: Enables public-private key pair operations with algorithms such as RSA. In this scheme, a public key encrypts data, while a private key decrypts it.
  • Message Digests and Hashing: Offers tools for creating digests of data, ensuring data integrity using algorithms like SHA256, MD5, and more.
  • Digital Signatures: Validates data authenticity and integrity. Using a private key, one can sign data, and using the corresponding public key, others can verify the signature.

2. SSL/TLS Framework:

  • Connection Handling: Initiates and manages both client and server-side connections, facilitating encrypted communication.
  • Context Configuration: Manages settings and callbacks for groups of connections, ensuring flexibility in handling SSL/TLS parameters.
  • Session Resumption: Speeds up the TLS handshake process by reusing session parameters, optimizing connection times.

3. X.509 Certificate Management:

  • Certificate Generation and Inspection: Allows for the creation of self-signed certificates and inspection of various certificate fields.
  • Certificate Verification: Validates the authenticity of a certificate against a set of trusted certificates.
  • Certificate Chains and Stores: Manages chains of certificates and stores of trusted CAs.

4. Key Management and Generation:

  • RSA, ECDSA, and DSA: Facilitates operations around various key types, from generation to serialization.
  • Private Key Security: Ensures private keys are kept secure, supporting both traditional PEM and the more secure PKCS8 formats.

5. ASN.1 and DER Functionality:

  • ASN.1 (Abstract Syntax Notation One) is the language used to define data structures.
  • DER (Distinguished Encoding Rules) is a specific method to encode ASN.1 data structures. This encoding is foundational in how certificates and keys are represented.

6. Custom Extensions and Plugins: The crate is extensible, allowing for the integration of custom cryptographic methods and extensions, ensuring that developers are not limited by the provided set of features.

Getting the Ball Rolling:

1. The Checklist:

  • A dash of Rust knowledge.
  • Rust and Cargo, ready to roll on your machine.
  • OpenSSL library, all set up.

2. Let’s Set Up Camp:

Kick things off with a brand new Rust project:

cargo new secure_handshake 
cd secure_handshake

3. The Right Tools for the Job:

Add in the crucial libraries to your Cargo.toml:

[dependencies] 
tokio = { version = "1", features = ["full"] } 
openssl = "0.10" 
tokio_openssl = "0.6"

4. Crafting the Digital Keys:

Let’s make some self-signed certificates.

At this point, I suggest you jump straight to the Rust’s Hands-On Digital Keys Generator we developed together on this article.

That will give your a much more in-depth understanding of how certificates and keys are generated at a low level.

Alternatively, if you don’t have the time now to read it, feel free to generate your keys manually by running:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Dive Right Into the Code:

1. Building Our Server’s Sanctuary:

Here, we’re setting up a server to handle the secret handshakes securely:

async fn run_server() { 
    let mut server_config = ServerConfig::new(NoClientAuth::new()); 
    server_config.set_single_cert(load_certs(), load_private_key()).unwrap(); 
    let server_config = Arc::new(server_config); 
 
    let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); 
 
    let acceptor = TlsAcceptor::from(server_config); 
 
    loop { 
        let (stream, _) = listener.accept().await.unwrap(); 
        let tls_stream = acceptor.accept(stream).await.unwrap(); 
        tokio::spawn(handle_client(tls_stream)); 
    } 
} 
 
async fn handle_client(mut tls_stream: tokio_rustls::server::TlsStream<TcpStream>) { 
    // Reads data from the TLS stream 
    let mut data = vec![0; 100]; 
 
    tls_stream.read(&mut data).await.unwrap(); 
 
    if &data[..5] == b"HELLO" { 
        tls_stream.write_all(b"HELLO_ACK").await.unwrap(); 
        println!("Received HELLO from client. Sent HELLO_ACK."); 
    } 
    // You can add more exchanges here. 
}

Download Now!


2. The Other Side — The Client:

Our client needs to be just as savvy, ensuring the handshake is legit:

async fn run_client() { 
    let mut config = ClientConfig::new(); 
    let dns_name = DNSNameRef::try_from_ascii_str("localhost").unwrap(); 
 
    let cert = load_certs(); 
    config.root_store.add(&cert[0]).unwrap(); 
 
    let connector = TlsConnector::from(Arc::new(config)); 
 
    let stream = TcpStream::connect("127.0.0.1:8080").await.unwrap(); 
 
    let mut tls_stream = connector.connect(dns_name, stream).await.unwrap(); 
 
    // Read an Write Data 
    tls_stream.write_all(b"HELLO").await.unwrap(); 
 
    let mut buffer = vec![0; 100]; 
 
    tls_stream.read(&mut buffer).await.unwrap(); 
 
    if &buffer[..9] == b"HELLO_ACK" { 
        println!("Received HELLO_ACK from server."); 
    } 
 
}

3. Validating the Keys:

fn load_certs() -> Vec<Certificate> { 
    let cert_file = File::open("localhost.crt").expect("Cannot open certificate file"); 
    let mut cert_reader = BufReader::new(cert_file); 
 
    certs(&mut cert_reader).unwrap_or_else(|_| { 
        panic!("Failed to read certificate"); 
    }) 
} 
 
fn load_private_key() -> rustls::PrivateKey { 
    let key_file = &mut BufReader::new(File::open("localhost.key").unwrap()); 
    let keys = pkcs8_private_keys(key_file).unwrap_or_else(|_| panic!("Failed to load keys")); 
 
    if keys.is_empty() { 
        panic!("No keys found!"); 
    } 
    keys[0].clone() 
}

4. The Grand Finale:

Finally, integrate everything into a main function, setting the stage for our servers to start their secret handshakes!

#[tokio::main] 
async fn main() { 
 
    tokio::spawn(run_server()); 
 
    // Giving server some time to start. 
    tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; 
 
    run_client().await; 
 
}

Run the project now, and you will see the outputs as this:

Finished dev [unoptimized + debuginfo] target(s) in 0.04s 
     Running `target/debug/rustprotosrv` 
 
Received HELLO from client. Sent HELLO_ACK. 
Received HELLO_ACK from server. 
 
Process finished with exit code 0

There you have it! With just a sprinkle of code and the power of Rust & OpenSSL, your servers are now equipped with a secret handshake protocol.

Now, go forth and let them communicate with confidence! 🚀

Wrapping up

Well, that wraps up our dive into crafting a Secure Server-to-Server Handshake with Rust & OpenSSL.

If you’re looking to get a closer look at the code or perhaps want to try it out yourself, I’ve got you covered.

You can find the complete implementation over at my GitHub repository: https://github.com/luishsr/rust-tls-handshake.

Your feedback, suggestions, or contributions are always welcome.


Download Now!


Check out some interesting hands-on Rust articles:

🌟 Developing a Fully Functional API Gateway in Rust — Discover how to set up a robust and scalable gateway that stands as the frontline for your microservices.

🌟 Implementing a Network Traffic Analyzer — Ever wondered about the data packets zooming through your network? Unravel their mysteries with this deep dive into network analysis.

🌟 Building an Application Container in Rust — Join us in creating a lightweight, performant, and secure container from scratch! Docker’s got nothing on this. 😉

🌟 Crafting a Secure Server-to-Server Handshake with Rust & OpenSSL — 
If you’ve been itching to give your servers a unique secret handshake that only they understand, you’ve come to the right place. Today, we’re venturing into the world of secure server-to-server handshakes, using the powerful combo of Rust and OpenSSL.

🌟Building a Function-as-a-Service (FaaS) in Rust: If you’ve been exploring cloud computing, you’ve likely come across FaaS platforms like AWS Lambda or Google Cloud Functions. In this article, we’ll be creating our own simple FaaS platform using Rust.

🌟 Rusting Up Your Own Self-Signed Certificate Generator — Let’s walk through the process of crafting your very own self-signed certificate generator, all using the versatile Rust programming language and the rust-openssl crate.Happy coding, and keep those Rust gears turning! 🦀

🌟 Implementing a Secret Vault in Rust: We’re about to dive into some cryptography, play around with key derivations, and even wrestle with user input, all to keep our most prized digital possessions under lock and key.

Happy coding, and keep those Rust gears turning!


Read more articles about Rust in my Rust Programming Library!


Happy coding, and keep those Rust gears turning! 🦀

Read more articles about Rust in my Rust Programming Library!

Visit my Blog for more articles, news, and software engineering stuff!

Follow me on Medium, LinkedIn, and Twitter.

Leave a comment, and drop me a message!

All the best,

Luis Soares

CTO | Tech Lead | Senior Software Engineer | Cloud Solutions Architect | Rust 🦀 | Golang | Java | ML AI & Statistics | Web3 & Blockchain

Thanks for coming along on this journey, and I hope the repository proves useful for your projects!

Read more