rust-native-tls — Bindings for native TLS libraries

Overview

rust-native-tls

Documentation

An abstraction over platform-specific TLS implementations.

Specifically, this crate uses SChannel on Windows (via the schannel crate), Secure Transport on macOS (via the security-framework crate), and OpenSSL (via the openssl crate) on all other platforms.

Installation

# Cargo.toml
[dependencies]
native-tls = "0.2"

Usage

An example client looks like:

extern crate native_tls;

use native_tls::TlsConnector;
use std::io::{Read, Write};
use std::net::TcpStream;

fn main() {
    let connector = TlsConnector::new().unwrap();

    let stream = TcpStream::connect("google.com:443").unwrap();
    let mut stream = connector.connect("google.com", stream).unwrap();

    stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
    let mut res = vec![];
    stream.read_to_end(&mut res).unwrap();
    println!("{}", String::from_utf8_lossy(&res));
}

To accept connections as a server from remote clients:

extern crate native_tls;

use native_tls::{Identity, TlsAcceptor, TlsStream};
use std::fs::File;
use std::io::{Read};
use std::net::{TcpListener, TcpStream};
use std::sync::Arc;
use std::thread;

fn main() {
    let mut file = File::open("identity.pfx").unwrap();
    let mut identity = vec![];
    file.read_to_end(&mut identity).unwrap();
    let identity = Identity::from_pkcs12(&identity, "hunter2").unwrap();

    let acceptor = TlsAcceptor::new(identity).unwrap();
    let acceptor = Arc::new(acceptor);

    let listener = TcpListener::bind("0.0.0.0:8443").unwrap();

    fn handle_client(stream: TlsStream<TcpStream>) {
        // ...
    }

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                let acceptor = acceptor.clone();
                thread::spawn(move || {
                    let stream = acceptor.accept(stream).unwrap();
                    handle_client(stream);
                });
            }
            Err(e) => { /* connection failed */ }
        }
    }
}

License

rust-native-tls is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses.

See LICENSE-APACHE, and LICENSE-MIT for details.

Comments
  • Add ability to disable verification

    Add ability to disable verification

    I know, I know, it's horrible. It is also a reality that many people deal with this, and so it would be useful to add a way to disable verification. It can and probably should be a terrifying long name, very_insecure_disable_verification or what-have-you.

    cc https://github.com/seanmonstar/reqwest/issues/15

    opened by seanmonstar 30
  • Loading pkcs12 der formatted bytes fails on macOS

    Loading pkcs12 der formatted bytes fails on macOS

    This change:

    https://github.com/sfackler/rust-native-tls/commit/94a150379d42b9ee6b2d2dbbadde02cde88e5159

    To get rid of the temp file, appears to have caused an error in my builds. Rolling back this change fixes my issues. I'm running into the unwrap() on

    https://github.com/sfackler/rust-native-tls/commit/94a150379d42b9ee6b2d2dbbadde02cde88e5159#diff-9cef9dd6c1ba7275f2ad10014dd7697fR82

    I was not running into this error before the change.

    FYI: @BlameOmar

    opened by bluejekyll 28
  • Add PKCS8 Support

    Add PKCS8 Support

    Squashed and rebased #147, then updated the tests to use test-cert-gen like the other tests.

    Closes #27


    • [x] Reject other formats in openssl and security_framework. Done by simply checking the start of the key.
    • [x] Update from_pkcs8 tests to use PKCS#8 keys. test_cert_gen doesn't support it, so generated RSA keys are converted using openssl pkcs8 -topk8 -nocrypt.
    • [x] Fix Windows failing two_servers test. Fixed by using unique container names.
    opened by kazk 21
  • Unable to specify a private key / certificate chain for mutual TLS

    Unable to specify a private key / certificate chain for mutual TLS

    In native-tls 0.1, it was possible to do this, as follows:

    let mut ssl =
                openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap();
    
     // Server authentication 
     ssl.set_ca_file(ca_certificate.clone()).unwrap(); 
      
     // Client authentication 
     ssl.set_private_key_file(client_key.clone(), openssl::x509::X509_FILETYPE_PEM) 
         .unwrap(); 
     ssl.set_certificate_chain_file(client_certificate.clone()) 
         .unwrap(); 
     ssl.check_private_key().unwrap(); 
      
     let builder: native_tls::TlsConnectorBuilder = 
         native_tls::backend::openssl::TlsConnectorBuilderExt::from_openssl(ssl); 
    

    It's not possible to do this in native tls 0.2, as TlsConnectorBuilderExt has been removed, and TlsConnectorBuilder doesn't implement this functionality natively.

    opened by richardwhiuk 20
  • Switch `TlsAcceptor::builder` input from PKCS#12 to PKCS#8 + cert list

    Switch `TlsAcceptor::builder` input from PKCS#12 to PKCS#8 + cert list

    For background, see https://unmitigatedrisk.com/?p=543 and https://www.cs.auckland.ac.nz/~pgut001/cryptlib/faq.html#Q5.

    Although it seems simple for rust-native-tls to use PKCS#12 as its standard format for server key/certificate configuration, it is actually quite problematic.

    First, PKCS#12 cryptography is stone-aged (3DES, RC2, etc.). This is a huge burden on any crypto library that itself wasn't forged in the stone ages of cryptography. Also, it is common for implementations to use way too few rounds of PBKDF2 (or PKBDF1), making the password-based encryption limited value unless the password itself is a strong random key.

    Secondly, the interop is limited due to poor defaults and lack of following recommendations. For example, the AES-CBC encryption that the latest IETF spec recommends isn't supported by most (all?) versions of Windows. As another example, many versions of OpenSSL (and, IIRC, NSS) use RC2 as the default (in some cases only) encryption format.

    Thirdly, it is pretty rare for private keys and certificate chains to be in PKCS#12 format. Usually they are in a collection of unencrypted PEM files. Even in the case where the TLS server does want to encrypt the private key key, usually that encryption is done using a key management system that (in my experience) isn't based on PKCS#12. For example, the ACME protocol (Let's Encrypt's certificate distribution protocol) defaults to PEM-based formats; see https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-6.4.2.

    Fourth, PKCS#12 is unnecessarily difficult to implement correctly and safely, and difficult to test and verify.

    I propose instead that the constructor for TlsAcceptor be changed to accept an unencrypted PKCS#8 private key and a list of certificates (maybe just a list of DER-encoded certificates in &[u8] slices). Then support for encrypted key/cert management, including PKCS#12, and also hopefully including better systems than PKCS#12, can be provided by separate crates.

    help wanted 
    opened by briansmith 19
  • get client's certificate from server's TlsStream?

    get client's certificate from server's TlsStream?

    Is there a way to get the client's certificate from a native_tls::TlsStream on the server's side? I couldn't find a method to do so. It seems like there should be a 'peer_certificate' accessor or something like that as there is on openssl::SslRef (available via openssl::SslStream::ssl).

    opened by udpip7 15
  • feature =

    feature = "dummy"

    Can rust-native-tls crate have feature = "dummy"? When this option is enabled, client code can be compiled with native_tls crate, but any call results in error.

    Why.

    HTTP client or server implementation may have optional TLS. Even if it is enabled, there's runtime switch that enables TLS.

    Some people want to avoid compiling OpenSSL (or whateven implementation native-tls uses), because they don't use TLS.

    So I need to provide a feature in my library to disable TLS.

    Currently I need to have a hundred conditionals in the library code and two builds to verify that code works with and without TLS.

    If native-tls crate had an option to effectively disable TLS, I'd just forward that feature flag to native-tls crate.

    opened by stepancheg 13
  • How to retrieve the TcpStream back on failure

    How to retrieve the TcpStream back on failure

    Hello, I am using native_tls for an app and everything is working fine except for one small issue. I have registered multiple TcpStreams in mio poll and want to retrieve the stream back in case the handshake fails so that I can de-register it before the underlying socket closes. I have currently implemented Drop trait for the stream but since it needs a mutable reference to the poll registry, I have to resort to use raw pointer and unsafe code. Is there any better way to do this ?

    opened by vasishath 11
  • Relax bounds for get_ref and get_mut

    Relax bounds for get_ref and get_mut

    It should not be necessary to have S: Read + Write to get at references to S through TlsStream<S>, so this patch removes those bounds. This matters little in practice, since you likely can't construct a TlsStream on an S that isn't Read + Write, but it does mean that downstream crates that wrap TlsStream do not have to repeat the Read + Write bounds for their get_ methods.

    opened by jonhoo 11
  • [WIP] Support ALPN on Security Framework

    [WIP] Support ALPN on Security Framework

    This change exposes security-framework's ALPN methods through native-tls.

    security-framework 0.2.1 doesn't have ALPN methods yet. So the build wouldn't succeed now.

    opened by kzys 10
  • ALPN support

    ALPN support

    At the recent all-hands we discussed TLS-in-Rust a bit and one of the nice features to add to this library would be ALPN support, especially in support of HTTP/2. For the backends native-tls has:

    • openssl crate already has ALPN support
    • security-framework does not have ALPN support. This may be available in the upcoming high sierra OSX though? And this may be available through private APIs in historical releases of OSX? It may be possible to write a shim that works with all this.
    • schannel doesn't have ALPN support but it's suspected that it does indeed exist in Windows, we just need to bind it.
    opened by alexcrichton 10
  • Upcoming PKCS#12 compatibility issue warning

    Upcoming PKCS#12 compatibility issue warning

    Recent changes in OpenSSL moved RC2 cipher into a "legacy" provider, some PKCS#12 files using the old cipher suite pbeWithSHA1And40BitRC2-CBC will fail to load, resulting in this error:

    error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:373:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()
    

    It would maybe be good to mention in the docs for native_tls::Identity::from_pkcs12() that when you run into this error you need to re-create the PKCS#12 file in a more modern format. In my case, I have used openssl pkcs12 -legacy to dump the certs and key and re-created the file with openssl pkcs12 -export:

    openssl pkcs12 -legacy --password pass:changeit -in bad.p12 -noenc -out fixme.pem
    openssl pkcs12 -export --password pass:changeit -inkey fixme.pem -in fixme.pem -out fixed.p12
    

    This probem so far manifests itself on Arch linux, but will spread to other distros with the new openssl version.

    Alternatively, you could provide the users with a way to enable the legacy openssl provider (didn't find any)

    opened by hlavaatch 1
  • the problem for Acceptor

    the problem for Acceptor

    hello,I have a truble in rust-tls::Acceptor(mio::TcpStream),can you help me?

    rust-tls::Acceptor(mio::TcpStream) ret: err: the handshake process was interrupted

    rust-tls::Acceptor(net::TcpStream)' ret: ok

    I dont know why.

    opened by zybmajia1 0
  • Problem with elliptic private keys

    Problem with elliptic private keys

    Greetings!

    Extent of this: https://github.com/sfackler/rust-native-tls/issues/221

    I got 2 keys: keys.tgz

    If I try to use them, I got error. If I try convert openssl pkcs8 -in server.pem -topk8 -nocrypt -outform pem -out new-server.pem I got error. If I remove EC from -----BEGIN EC PRIVATE KEY----- everything work fine. But in Docker with musl target I got error.

    What I do wrong?

    opened by BratSinot 0
  • Accepting non-TLS WebSocket makes TspListener hang?

    Accepting non-TLS WebSocket makes TspListener hang?

    Description

    While trying to write a secured WebSocket server using tungstenite-rs, I found this strange behavior of native-tls (it does not require tungstenite to reproduce). When a client incorrectly requests a non-TLS WebSocket handshake to the server, TlsAcceptor::accept(&self, stream) goes into an infinite loop and never returns unless the client explicitly closes the connection. Even worse, it makes the server (= TcpListener) stop handling other (TLS secured) WebSocket requests. I'm new to Rust so I couldn't determine why accepting one wrong request in the separated thread makes TcpListener in the main thread stop working.

    Environment

    • native-tls = "0.2.10"
    • rustc 1.63.0 (4b91a6ea7 2022-08-08)
    • cargo 1.63.0 (fd9c4297c 2022-07-01)
    • Windows 11
    • Microsoft Edge

    How to reproduce

    1. Run the below program

      use std::sync::Arc;
      use std::thread;
      use std::{fs::File, net::TcpListener};
      use std::io::{Read};
      
      use native_tls::{TlsAcceptor, Identity};
      
      fn main() {
          let mut file = File::open("./cert/server.pfx").unwrap();
          let mut identity = vec![];
          file.read_to_end(&mut identity).unwrap();
          let identity = Identity::from_pkcs12(&identity, "").unwrap();
          let acceptor = TlsAcceptor::new(identity).unwrap();
          let acceptor = Arc::new(acceptor);
      
          let server = TcpListener::bind("127.0.0.1:8080").unwrap();
          let t = thread::spawn(move || {
              for stream in server.incoming() {
                  println!("incoming!");
                  let acceptor = acceptor.clone();
                  thread::spawn(move || {
                      acceptor.accept(stream.unwrap()).unwrap();
                      println!("accepted!");
                  });
              }
          });
      
          t.join().unwrap();
      }
      
    2. Send a non-TLS WebSocket request from a browser

      > var ws = new WebSocket('ws://127.0.0.1:8080');
      
    3. The server prints "incoming!" but not "accepted!"

    4. Send another (but this time using TLS) WebSocketSecure request from a browser

      > var ws = new WebSocket('wss://127.0.0.1:8080');
      
    5. The server prints neither "incoming!" nor "accepted!", which means TcpListener itself is hanging?

    opened by tkntkn 0
Releases(v0.2.11)
Owner
Steven Fackler
Steven Fackler
[INACTIVE] TLS 1.2 implementation in Rust

suruga is Rust implementation of TLS 1.2. It currently implements some core parts of TLS 1.2, NIST P-256 ECDHE and chacha20-poly1305. Usage extern cra

klutzy/defunct 123 Dec 27, 2022
A Rust implementation of Trojan with QUIC tunnel, Lite-TLS and more.

Trojan-Oxide A Rust implementation of Trojan with QUIC tunnel, Lite-TLS and more. Overview Full support for the original Trojan Protocol, including TC

null 13 Oct 17, 2022
OpenSSL compatibility layer for the Rust SSL/TLS stack

An OpenSSL compatibility layer for the Rust SSL/TLS stack. MesaLink is an OpenSSL compatibility layer for the Rust SSL/TLS stack, namely rustls, webpk

MesaLock Linux 1.5k Dec 23, 2022
A modern TLS library in Rust

Rustls is a modern TLS library written in Rust. It uses ring for cryptography and libwebpki for certificate verification. Status Rustls is ready for u

null 4k Jan 9, 2023
A no-std / no-alloc TLS 1.3 client

puny-tls - no-std/no-alloc TLS 1.3 client This is an improvement over tiny-tls-rs to make it more useable. However the only reason this exists is to r

Björn Quentin 2 Aug 22, 2022
rust client libraries to deal with the current cardano mainnet (byron / cardano-sl)

Rust implementation of Cardano primitives, helpers, and related applications Cardano Rust is a modular toolbox of Cardano’s cryptographic primitives,

Input Output 275 Oct 9, 2022
Collect libraries and packages about cryptography in Rust.

Awesome Cryptography Rust Collect libraries and packages about cryptography in Rust. Collection Library Symmetric Public-key / Asymmetric One-way Hash

Rust Cryptography Community 282 Dec 25, 2022
Rust starter project for building CLI and libraries, with great CI

Using the starter project: find where bumblefoot is and replace it with the name of your project. $ rg bumblefoot This is a dual library and binary pr

Rusty Ferris Club 19 Nov 19, 2022
Automated security testing for open source libraries and applications.

autovet continuously searches for security breaches in open source libraries and applications. Recently processed packages package version channel las

null 5 Aug 23, 2022
A collection of libraries to be implemented for Automated Market Makers built in Sway.

?? ?? Executor AMM ?? ?? The Executor AMM is a reference implementation of Concentrated Liquidity in Sway. To run on the FuelVM many modifications had

Sway Libraries 54 Dec 21, 2022
Rust-native building blocks for the Cardano blockchain ecosystem

Pallas Rust-native building blocks for the Cardano blockchain ecosystem. Introduction Pallas is an expanding collection of modules that re-implements

null 78 Dec 6, 2022
egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native

?? egui: an easy-to-use GUI in pure Rust ?? Click to run the web demo ?? egui is a simple, fast, and highly portable immediate mode GUI library for Ru

Cronus Diamond 7 Aug 13, 2022
USN - the first NEAR-native stablecoin

USN USN is a NEAR-native USD stable coin. The contract implements fungible token API according to the following standards: NEP-141 (ERC-20 fashioned)

DecentralBank 52 Nov 2, 2022
Utilities for working with native solc and compiling projects.

foundry-compilers Utilities for working with native solc and compiling projects. To also compile contracts during cargo build (so that ethers abigen!

Foundry 9 Oct 4, 2023
Sodium Oxide: Fast cryptographic library for Rust (bindings to libsodium)

sodiumoxide |Crate|Documentation|Gitter| |:---:|:-----------:|:--------:|:-----:|:------:|:----:| |||| NaCl (pronounced "salt") is a new easy-to-use h

sodiumoxide 642 Dec 17, 2022
OpenSSL bindings for Rust

rust-openssl OpenSSL bindings for the Rust programming language. Documentation. Release Support The current supported release of openssl is 0.10 and o

Steven Fackler 1k Jan 7, 2023
Rust FFI bindings for StarkWare's crypto-cpp library

starkware-crypto-rs Rust FFI bindings for StarkWare's crypto-cpp library Note that currently target x86_64-pc-windows-msvc is not supported. If you're

Jonathan LEI 11 Aug 22, 2022
Python bindings for rage (age in Rust)

pyrage Python bindings for the Rust implementation of age. Index Installation Usage Development Licensing Installation You can install pyrage with pip

William Woodruff 14 Nov 23, 2022
Rust bindings for Solidity's AST and visitors

solc-ast solc-ast provides rust bindings for the solidity AST and visitors. The visitors were built to be 1-1 compatible with the visitors from solc.

Hari 35 May 7, 2023