Rust version: 1.78 stable
OS: Windows 11
I try use quinn to made a simple app to build a QUIC connection, here is code below:
// Server code
use std::{fs, sync::Arc};
use quinn::crypto::rustls::QuicServerConfig;
use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
pub const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"];
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv()?;
env_logger::init();
rustls::crypto::ring::default_provider()
.install_default()
.expect("Failed to install rustls crypto provider");
let cert = fs::read("C:/Projects/certificates/certificate.der")?;
let key = fs::read("C:/Projects/certificates/private_key.der")?;
let cert = CertificateDer::from(cert);
let key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::try_from(key)?);
let mut server_config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(vec![cert], key)?;
server_config.alpn_protocols = ALPN_QUIC_HTTP.iter().map(|&x| x.into()).collect();
let server_config =
quinn::ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(server_config)?));
let endpoint = quinn::Endpoint::server(server_config, "127.0.0.1:8898".parse()?)?;
let mut b = [0u8; 1024];
while let Some(conn) = endpoint.accept().await {
let (mut send, mut recv) = conn.await?.open_bi().await?;
while let Ok(_) = recv.read(&mut b).await {
send.write_all(&mut b).await?;
}
}
Ok(())
}
// Client
use std::fs;
use std::sync::Arc;
use quinn::crypto::rustls::QuicClientConfig;
use rustls::pki_types::CertificateDer;
pub const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"];
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv::dotenv()?;
env_logger::init();
rustls::crypto::ring::default_provider()
.install_default()
.expect("Failed to install rustls crypto provider");
// let cert = fs::read("C:/Projects/certificates/server.crt")?;
// let cert = CertificateDer::from(cert);
let mut roots = rustls::RootCertStore::empty();
roots.add(CertificateDer::from(fs::read(
"C:/Projects/certificates/certificate.der",
)?))?;
let mut client_crypto = rustls::ClientConfig::builder()
.with_root_certificates(roots)
.with_no_client_auth();
client_crypto.alpn_protocols = ALPN_QUIC_HTTP.iter().map(|&x| x.into()).collect();
let client_config =
quinn::ClientConfig::new(Arc::new(QuicClientConfig::try_from(client_crypto)?));
let mut endpoint = quinn::Endpoint::client("0.0.0.0:0".parse()?)?;
endpoint.set_default_client_config(client_config);
let conn = endpoint
.connect("127.0.0.1:8898".parse()?, "localhost")?
.await?;
Ok(())
}
Very simple code, please note the certificating part of code, the key and the certificate files: private_key.der
and certificate.der
, is self-signed certificate by OpenSSL.
But when I run server code and client code it would appears error:
Error: ConnectionClosed(ConnectionClose { error_code: Code::crypto(2e), frame_type: None, reason: b"invalid peer certificate: Other(OtherError(UnsupportedCertVersion))" })
error: process didn't exit successfully: `C:Projectsfriendstargetdebugserver.exe` (exit code: 1)
I thought maybe I signed wrong, here are some commands I used:
openssl genpkey -algorithm RSA -out ca_key.pem
openssl req -x509 -new -nodes -key ca_key.pem -sha256 -days 3650 -out ca_cert.crt
openssl genpkey -algorithm RSA -out server_key.pem
openssl req -new -key server_key.pem -out server_csr.pem
openssl x509 -req -in server_csr.pem -CA ca_cert.pem -CAkey ca_key.pem -CAcreateserial -out server_cert.pem -days 365 -sha256
openssl pkcs8 -topk8 -inform PEM -outform DER -in server_key.pem -out private_key.der -nocrypt
openssl x509 -outform der -in server_cert.pem.pem -out certificate.der
And the CA ca_cert.crt
, I had been trust it on the certmgr
I don’t why it was not work, anyone has idea?