diff --git a/https-tls/openssl/README.md b/https-tls/openssl/README.md index daa17c2..985726a 100644 --- a/https-tls/openssl/README.md +++ b/https-tls/openssl/README.md @@ -2,31 +2,40 @@ ## Usage -### Certificate +### Generating Trusted Certificate -We put the self-signed certificate in this directory as an example but your browser would complain that it isn't secure. So we recommend to use [`mkcert`] to trust it. To use local CA, you should run: +We put self-signed certificate in this directory as an example but your browser will complain that connections to the server aren't secure. We recommend to use [`mkcert`] to trust it. To use a local CA, you should run: ```sh mkcert -install ``` -If you want to generate your own cert/private key file, then run: +If you want to generate your own private key/certificate pair, then run: ```sh -mkcert 127.0.0.1 +mkcert 127.0.0.1 localhost +``` + +A new `key.pem` and `cert.pem` will be saved to the current directory. You will then need to modify `main.rs` where indicated. + +### Running Server + +```console +$ cd security/openssl +$ cargo run # (or `cargo watch -x run`) +starting HTTPS server at 127.0.0.1:8443 +``` + +### Using Client + +- curl: `curl -vk https://127.0.0.1:8443` +- curl (forced HTTP/1.1): `curl -vk --http1.1 https://127.0.0.1:8443` +- browser: + +## Self-Signed Encrypted Private Key Command + +```sh +openssl req -x509 -newkey rsa:4096 -keyout key-pass.pem -out cert-pass.pem -sha256 -days 365 ``` [`mkcert`]: https://github.com/FiloSottile/mkcert - -### server - -```sh -cd security/openssl -cargo run (or ``cargo watch -x run``) -# Started http server: 127.0.0.1:8443 -``` - -### web client - -- curl: `curl -v https://127.0.0.1:8443/index.html --compressed -k` -- browser: [https://127.0.0.1:8443/index.html](https://127.0.0.1:8443/index.html) diff --git a/https-tls/openssl/cert.pem b/https-tls/openssl/cert.pem index 0df775a..9e93a51 100644 --- a/https-tls/openssl/cert.pem +++ b/https-tls/openssl/cert.pem @@ -1,24 +1,29 @@ -----BEGIN CERTIFICATE----- -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 +5CAz3ZrF2CJVOg== -----END CERTIFICATE----- diff --git a/https-tls/openssl/key.pem b/https-tls/openssl/key.pem index f0d0531..541dfd0 100644 --- a/https-tls/openssl/key.pem +++ b/https-tls/openssl/key.pem @@ -1,28 +1,54 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDl9FQhsS/YOMGY -rv6zIZW+HcgVYOVWNT03vKnFq5Btc8cDOkBPOCEuembkKpAWhOcnADj/8Dznvvl2 -NxWWwBSp6fZliL7iNNh65EusAnR2StRLz/v5PR8bMZnyhsKwgjmJITYExLsDFuqV -C0KUN2Q3BwqsK7OuYjIwDwFzZXbfXEiBxYUnt6fw5pklGVhgruSnZwnyDQ9s+dWr -71MB8VhwoTIVaomxhhjfpsttbKphcYw60CHZuHL5gZgvcmGT5zDuIwKPJ7gVsMAh -DO31wfUoYYzZVZkWLCfpUmq5fVn6f0oCF/PG7NhAdKuUn5G376B7OlO03DyrXkqj -vyiK7sItAgMBAAECggEBAIabZmAukz4zwwe4cDm1kC0wy73P8Y9sLMCivJKMYkff -vQBjqd91kN7fIbmwPJYiCBlpZPRU0aIqxWZwyj9rgu0Pmn9G884AdzRAzRcMfNX9 -6ZXTUsFMCRhnCaHRRsgCAuIFwdQ6wOoHERxb8gZHAm+/vHyaPFz4+D3vmr7NBy+p -fgpdDCGwkltKI73efk6H4oAeyztDwNev/TZ3Y+O3UKuAUfVReBX0us/lYgEf/KXV -USd7envxACy+PDcqmn/HL6IUnbrc1zB92dmSSUUtLjOz//z1zM05ME/E2keMQwsW -7LDen0Lm0Nh6AcOCxmnN4u0lJ3nWzU7PsHJKY/LznPUCgYEA5kQq/AG6LlL9Iu1E -Y55AB1rkvseof41liaqXVccB5tr55IF75d0wPd6jF04W+x6LwmL6EUYPRGkkOdHE -raz9CDE3a7hWbAghxIwLrI1s+faT5aaHG9o6mTeDyfgEEoBg8X2nQHQJPayDJZcW -kiXQyHEtj/G4m/Y+WDFXastZz8MCgYEA/6c8+cI3Slvg3CZLG9f6rdAlrOSIQynF -muXyVeUaxrU0OPC9H3WEwWv7n4adQU2g0L6TBTdlOOiv5SPIsOPQVN2JZVdxwg0V -n5+7/WRrI9rAXnmu1x0q1e/TZ9Msggmrn5SdHaEfuug4DnHv4nct356joDwYB2i3 -xYl+yCSMd08CgYEAqduvOaasiG9/e7w6rqGV6dcK1hDCIxVSyXKloAjlRj5SCFXb -53x6kakh9ZcNLMEjp4kLnqJnsLc+mcg7pUHuhZSIpVWdqqN1BV+pXOgWc22JO+bT -05/vigaBmQLzPhKlcH6YWds+1dfkBl6lr7llgfa6/Wv6GlJTOwtqyMSow7ECgYEA -zGQ8j8ICymRihh/ndL9cH5KGTI/5kRjYb1rgQGQG4E8HDW8LBRfDp5BZf9Tz7L3P -kJSMnmMHflQqLJxLW4EHkpH7wxYCUQ589z2R4qhiMCw4GFBYxIsBMEGpVxyyPNTW -baM3afTjlV8LUiEtlHWMK3h9gSIKZAIIytl+jy0JUGkCgYA3wrpcG3wgXeuEtoie -ve/kFS5JRaOeV/9OLE2JGaGaumPlN0L14kCVvb6uqLa/P88BwBUxvGQ7FDBdh4sk -ypuSe9ZPCNDgnsbnfM8QgFqIW6MDdizLtj7no1SKeaUU3JWWc0kH2KWMw/sYZ7ec -0tcEInxEd7FbssGfMqF9fQtnNw== ------END PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +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 +HRReC0LmrD91l8GASZ4NVzAGlA== +-----END ENCRYPTED PRIVATE KEY----- diff --git a/https-tls/openssl/src/main.rs b/https-tls/openssl/src/main.rs index 2a9bd76..9b12d45 100644 --- a/https-tls/openssl/src/main.rs +++ b/https-tls/openssl/src/main.rs @@ -1,25 +1,39 @@ -use std::io; +use std::{ + fs::File, + io::{self, Read as _}, +}; use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer}; -use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; +use openssl::{ + pkey::{PKey, Private}, + ssl::{SslAcceptor, SslMethod}, +}; /// simple handle async fn index(req: HttpRequest) -> Result { println!("{req:?}"); Ok(HttpResponse::Ok() .content_type("text/plain") - .body("Welcome!")) + .body("Hello HTTPS World!")) } #[actix_web::main] async fn main() -> io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - // load TLS keys + // build TLS config from files let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + + // set the encrypted private key builder - .set_private_key_file("key.pem", SslFiletype::PEM) + .set_private_key(&load_encrypted_private_key()) .unwrap(); + + // set the unencrypted private key + // (uncomment if you generate your own key+cert with `mkcert`, and also remove the statement above) + // builder.set_private_key_file("key.pem").unwrap(); + + // set the certificate chain file location builder.set_certificate_chain_file("cert.pem").unwrap(); log::info!("starting HTTPS server at http://localhost:8443"); @@ -28,16 +42,19 @@ async fn main() -> io::Result<()> { App::new() // enable logger .wrap(middleware::Logger::default()) - // register simple handler, handle all methods - .service(web::resource("/index.html").to(index)) - // with path parameters - .service(web::resource("/").route(web::get().to(|| async { - HttpResponse::Found() - .append_header(("LOCATION", "/index.html")) - .finish() - }))) + // simple root handler + .service(web::resource("/").route(web::get().to(index))) }) .bind_openssl("127.0.0.1:8443", builder)? + .workers(2) .run() .await } + +fn load_encrypted_private_key() -> PKey { + let mut file = File::open("key.pem").unwrap(); + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer).expect("Failed to read file"); + + PKey::private_key_from_pem_passphrase(&buffer, b"password").unwrap() +}