当前位置:网站首页>tokio_ Rustls self signed certificate
tokio_ Rustls self signed certificate
2022-06-24 01:47:00 【to listen attentively】
1 Purpose of using self signed certificates
The purpose of using self signed certificates in this article :
- Used by the server to verify whether the client is legal , Avoid connecting any client to the server .
- be based on TLS, Encrypt the transmission data between the server and the client .
2 Self signed certificate verification process
3 principle
3.1 digital certificate
The server uses its own domain name to CA(Certificate Authority, Certification authority ) Apply for a certificate .
CA The certificate issued contains the public key 、 Certificate owner 、 The period of validity 、CA Use your private key to generate signatures and other information .
If the client wants to verify whether the certificate of the server is legal , Can see if it works CA Public key to unlock the signature on the certificate , If you can untie , The certificate of the server is legal . But how to confirm CA Your public key is legal , In case someone pretends to be CA What do I do , At this time, you can go through CA Of CA To verify , Go all the way up , Until it goes back to the famous root CA.
3.2 TLS
TLS(Transport Layer Security, Secure transport layer ),TLS yes Built on the transport layer TCP The agreement over the agreement , Serving the application layer , Its predecessor is SSL(Secure Socket Layer, Secure socket layer ), It realizes the encryption of the message in the application layer and then handed over to TCP Transmission function .
TLS The transmission process is roughly divided into two stages :
- The first stage : The client and server use asymmetric encryption to exchange information , Used to generate the required for symmetric encrypted transmission key.
- In the process , Use the private key to encrypt the data , Decrypt the data using the public key in the opposite certificate .
- The second stage : Use generated key Encrypt and decrypt the communication data .
4 Self signed certificate generation
Reference resources rustls The example given has been modified .
- Do it yourself CA, Generate CA cert, In the future CA cert It can be trusted by the server and the client .
- utilize CA cert Issue the server and client SSL certificate . Server and client SSL The certificate generation steps are the same , As follows :
- Generate private key .
- Using private key to generate certificate request .
- Utilize certificate requests and CA cert Generate Certificate ,CA Will use its own private key to generate a certificate signature .
build-a-pki.sh:
#!/bin/sh
set -xe
work_dir=$(cd $(dirname $0); pwd)
dir='dev'
if [ $# -eq 1 ]; then
while getopts ":r" opt
do
case $opt in
r)
dir='release'
;;
?)
echo "Unknow input"
exit 1
;;
esac
done
fi
dir=$work_dir/$dir
rm -rf $dir
mkdir $dir
openssl req -nodes \
-x509 \
-days 3650 \
-newkey rsa:4096 \
-keyout $dir/ca.key \
-out $dir/ca.cert \
-sha256 \
-batch \
-subj "/CN=ponytown RSA CA"
openssl req -nodes \
-newkey rsa:2048 \
-keyout $dir/server.key \
-out $dir/server.req \
-sha256 \
-batch \
-subj "/CN=testserver.com"
openssl rsa \
-in $dir/server.key \
-out $dir/server.rsa
openssl req -nodes \
-newkey rsa:2048 \
-keyout $dir/client.key \
-out $dir/client.req \
-sha256 \
-batch \
-subj "/CN=ponytown client"
for kt in $dir ; do
openssl x509 -req \
-in $kt/server.req \
-out $kt/server.cert \
-CA $kt/ca.cert \
-CAkey $kt/ca.key \
-sha256 \
-days 2000 \
-set_serial 456 \
-extensions v3_server -extfile openssl.cnf
openssl x509 -req \
-in $kt/client.req \
-out $kt/client.cert \
-CA $kt/ca.cert \
-CAkey $kt/ca.key \
-sha256 \
-days 2000 \
-set_serial 789 \
-extensions v3_client -extfile openssl.cnf
cat $kt/server.cert $kt/ca.cert > $kt/server.fullchain
done
rm $dir/*.req
rm $dir/ca.key
rm $dir/server.cert $dir/server.keyopenssl.cnf:
[ v3_server ] basicConstraints = critical,CA:false keyUsage = nonRepudiation, digitalSignature subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always subjectAltName = @alt_names [ v3_client ] basicConstraints = critical,CA:false keyUsage = nonRepudiation, digitalSignature extendedKeyUsage = critical, clientAuth subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always [ alt_names ] DNS.1 = testserver.com DNS.2 = second.testserver.com DNS.3 = localhost
4 Use the self signed certificate example
This article is based on rust in tokio_rustls Library implementation TLS.TLS yes Based on the TCP Above , Serving the application layer , It encrypts the message of the application layer and then submits it to TCP transmitted .
client :
- Certificate of loading , Generate rustls::ClientConfig
- utilize rustls::ClientConfig Generate rustls::TlsConnector
- utilize rustls::TlsConnector take tokio::net::TcpStream To tokio_rustls::client::TlsStream, Available later TlsStream Sending and receiving data
Server side :
- Certificate of loading , Generate rustls::ServerConfig
- utilize rustls::ServerConfig Generate rustls::TlsAcceptor
- utilize rustls::TlsAcceptor take tokio::net::TcpStream To tokio_rustls::server::TlsStream, Available later TlsStream Sending and receiving data
use std::convert::TryFrom;
use std::fs::File;
use std::io;
use std::io::BufReader;
use std::sync::Arc;
use std::net::{
SocketAddr,
ToSocketAddrs,
};
use rustls::{
RootCertStore,
server::{AllowAnyAuthenticatedClient},
};
use tokio::net::{TcpStream};
use tokio_rustls::{
TlsAcceptor,
TlsConnector,
rustls::{self},
client::TlsStream as ClientTlsStream,
};
pub fn load_certs(filename: &str) -> Vec<rustls::Certificate> {
let certfile = File::open(filename).expect("cannot open certificate file");
let mut reader = BufReader::new(certfile);
rustls_pemfile::certs(&mut reader)
.unwrap()
.iter()
.map(|v| rustls::Certificate(v.clone()))
.collect()
}
pub fn load_private_key(filename: &str) -> rustls::PrivateKey {
let keyfile = File::open(filename).expect("cannot open private key file");
let mut reader = BufReader::new(keyfile);
loop {
match rustls_pemfile::read_one(&mut reader).expect("cannot parse private key .pem file") {
Some(rustls_pemfile::Item::RSAKey(key)) => return rustls::PrivateKey(key),
Some(rustls_pemfile::Item::PKCS8Key(key)) => return rustls::PrivateKey(key),
None => break,
_ => {}
}
}
panic!(
"no keys found in {:?} (encrypted keys not supported)",
filename
);
}
pub fn lookup_ipv4(host: &str, port: u16) -> SocketAddr {
let addrs = (host, port).to_socket_addrs().unwrap();
for addr in addrs {
if let SocketAddr::V4(_) = addr {
return addr;
}
}
unreachable!("Cannot lookup address");
}
fn make_client_config(ca_file: &str, certs_file: &str, key_file: &str) -> Arc<rustls::ClientConfig> {
let cert_file = File::open(&ca_file).expect("Cannot open CA file");
let mut reader = BufReader::new(cert_file);
let mut root_store = RootCertStore::empty();
root_store.add_parsable_certificates(&rustls_pemfile::certs(&mut reader).unwrap());
let suites = rustls::DEFAULT_CIPHER_SUITES.to_vec();
let versions = rustls::DEFAULT_VERSIONS.to_vec();
let certs = load_certs(certs_file);
let key = load_private_key(key_file);
let config = rustls::ClientConfig::builder()
.with_cipher_suites(&suites)
.with_safe_default_kx_groups()
.with_protocol_versions(&versions)
.expect("inconsistent cipher-suite/versions selected")
.with_root_certificates(root_store)
.with_single_cert(certs, key)
.expect("invalid client auth certs/key");
Arc::new(config)
}
fn make_server_config(certs: &str, key_file: &str) -> Arc<rustls::ServerConfig> {
let roots = load_certs(certs);
let certs = roots.clone();
let mut client_auth_roots = RootCertStore::empty();
for root in roots {
client_auth_roots.add(&root).unwrap();
}
let client_auth = AllowAnyAuthenticatedClient::new(client_auth_roots);
let privkey = load_private_key(key_file);
let suites = rustls::ALL_CIPHER_SUITES.to_vec();
let versions = rustls::ALL_VERSIONS.to_vec();
let mut config = rustls::ServerConfig::builder()
.with_cipher_suites(&suites)
.with_safe_default_kx_groups()
.with_protocol_versions(&versions)
.expect("inconsistent cipher-suites/versions specified")
.with_client_cert_verifier(client_auth)
.with_single_cert_with_ocsp_and_sct(certs, privkey, vec![], vec![])
.expect("bad certificates/private key");
config.key_log = Arc::new(rustls::KeyLogFile::new());
config.session_storage = rustls::server::ServerSessionMemoryCache::new(256);
Arc::new(config)
}
pub async fn new_tls_stream(domain: &str, addr: std::net::SocketAddr,
ca_file: &str, cert_file: &str, key_file: &str) -> ClientTlsStream<TcpStream> {
let config = make_client_config(&ca_file, &cert_file, &key_file);
let connector = TlsConnector::from(config);
let stream = TcpStream::connect(&addr).await.unwrap();
let domain = rustls::ServerName::try_from(domain)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "invalid dnsname")).unwrap();
let stream = connector.connect(domain, stream).await.unwrap();
stream
}
pub fn new_tls_acceptor(cert_file: &str, key_file: &str) -> TlsAcceptor {
let config = make_server_config(&cert_file, &key_file);
let acceptor = TlsAcceptor::from(config);
acceptor
}
#[cfg(test)]
mod tests {
use super::*;
use tokio::net::TcpListener;
use tokio::io::{AsyncWriteExt, AsyncReadExt};
const CA_FILE: &str = "cert/dev/ca.cert";
const CLIENT_CERT_FILE: &str = "cert/dev/client.cert";
const CLIENT_KEY_FILE: &str = "cert/dev/client.key";
const SERVER_CERT_FILE: &str = "cert/dev/server.fullchain";
const SERVER_KEY_FILE: &str = "cert/dev/server.rsa";
#[tokio::test]
async fn tls() {
let msg = b"Hello world\n";
let mut buf = [0; 12];
start_server().await;
start_client(msg, &mut buf).await;
assert_eq!(&buf, msg);
}
async fn start_server() {
let tls_acceptor = new_tls_acceptor(SERVER_CERT_FILE, SERVER_KEY_FILE);
let listener = TcpListener::bind("0.0.0.0:5002").await.unwrap();
tokio::spawn(async move {
let (stream, _peer_addr) = listener.accept().await.unwrap();
let mut tls_stream = tls_acceptor.accept(stream).await.unwrap();
println!("server: Accepted client conn with TLS");
let mut buf = [0; 12];
tls_stream.read(&mut buf).await.unwrap();
println!("server: got data: {:?}", buf);
tls_stream.write(&buf).await.unwrap();
println!("server: flush the data out");
});
}
async fn start_client(msg: &[u8], buf: &mut [u8]) {
let addr = lookup_ipv4("127.0.0.1", 5002);
let mut tls_stream =
new_tls_stream("localhost", addr, CA_FILE, CLIENT_CERT_FILE, CLIENT_KEY_FILE).await;
tls_stream.write(msg).await.unwrap();
println!("client: send data");
tls_stream.read(buf).await.unwrap();
println!("client: read echoed data");
}
}Reference resources
Liu chao . HTTPS agreement : The process of ordering takeout turns out to be so complicated .
https://www.jscape.com/blog/client-certificate-authentication
https://www.makethenmakeinstall.com/2014/05/ssl-client-authentication-step-by-step/
边栏推荐
- [dry goods] configure failover active/acitve in transparent mode on Cisco ASA firewall
- [planting grass by technology] three big gifts prepared by Tencent cloud for you on the double 11, welcome to touch~
- Five things programmers need to consider when developing with low code – thenewstack
- Moment. JS how to use epoch time to construct objects
- How to make a fixed asset identification card
- A marriage app_ T signature analysis
- [technology for grass planting] lightweight 248 helps individual developers go to the cloud
- If the program exits abnormally, how to catch the fatal error through the go language?
- Tcapulusdb database: the king behind the "Tianya Mingyue swordsman Tour"
- Zoom supports automatic generation of subtitles; Shareplay goes online; Safari update leads to a large number of bugs | webrtc wind direction
猜你喜欢
![[SQL injection 12] user agent injection foundation and Practice (based on burpsuite tool and sqli labs LESS18 target machine platform)](/img/c8/f6c2a62b8ab8fa88bd2b3d8f35f592.jpg)
[SQL injection 12] user agent injection foundation and Practice (based on burpsuite tool and sqli labs LESS18 target machine platform)

It's too difficult for me. Ali has had 7 rounds of interviews (5 years of experience and won the offer of P7 post)
![[SQL injection 13] referer injection foundation and Practice (based on burpseuite tool and sqli labs less19 target platform)](/img/b5/a8c4bbaf868dd20b7dc9449d2a4378.jpg)
[SQL injection 13] referer injection foundation and Practice (based on burpseuite tool and sqli labs less19 target platform)

I, a 27 year old female programmer, feel that life is meaningless, not counting the accumulation fund deposit of 430000
随机推荐
Application analysis of video edge computing gateway easynvr in video overall monitoring solution
Typescript type system
Spatial4j introduction practice
Best practices cloud development cloudbase multi environment management practices
Go language core 36 lectures (go language practice and application VII) -- learning notes
How to develop the industrial Internet platform?
How to realize court face recognition / flow statistics based on easycvr technology?
Can the server be restarted through the fortress machine? How are the fortress machines connected to the server
Virtual currency mining detection and defense
Tcapulusdb database: the king behind the "Tianya Mingyue swordsman Tour"
If the program exits abnormally, how to catch the fatal error through the go language?
How to do AI speech synthesis? How to download the voice of AI speech synthesis?
What is pension finance? What are the pension financial products?
Collation of commonly used glusterfs commands
What is function point analysis - FPA
Digital case show ‖ made in China for the first time! Tencent cloud tdsql landed in Zhangjiagang bank and worked together to build financial business
It's too difficult for me. Ali has had 7 rounds of interviews (5 years of experience and won the offer of P7 post)
3、 Shell variable substring
Ppt layout design how to make pages not messy
Cost composition and calculation method of system software