From f6d0fa026097212154933a279d7b5fd4a057caa1 Mon Sep 17 00:00:00 2001 From: Martell Malone Date: Sun, 25 Jun 2017 17:28:57 +0100 Subject: [PATCH] feat(jwt): use rustls and remove openssl This removes the need for the remaining C interfaces. Building any rust library with openssl adds a bunch of depends such as foreign types via ffi and pkgconfg. You are also required to have a prebuilt openssl. Cross building and keeping up to date should be easier with a pure rust implementation. --- Cargo.lock | 66 +----------------------------------------- Cargo.toml | 2 +- src/lib.rs | 2 +- src/service_account.rs | 38 ++++++++++++++---------- 4 files changed, 26 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 747e024..80edd7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ dependencies = [ "itertools 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -35,11 +35,6 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.0.0" @@ -64,25 +59,11 @@ name = "dtoa" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "foreign-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "gcc" version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "gdi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "getopts" version = "0.2.14" @@ -229,35 +210,6 @@ name = "open" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "openssl" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "pkg-config" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "quote" version = "0.3.15" @@ -470,15 +422,6 @@ dependencies = [ "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "user32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "uuid" version = "0.2.3" @@ -528,14 +471,11 @@ dependencies = [ [metadata] "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" -"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" "checksum deque 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a694dae478589798d752c7125542f8a5ae8b6e59476172baf2eed67357bdfa27" "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" -"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" "checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" "checksum hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36e108e0b1fa2d17491cbaac4bc460dc0956029d10ccf83c913dd0e5db3e7f07" @@ -556,9 +496,6 @@ dependencies = [ "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" "checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" -"checksum openssl 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "241bcf67b1bb8d19da97360a925730bdf5b6176d434ab8ded55b4ca632346e3a" -"checksum openssl-sys 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e0fd64cb2fa018ed2e7b2c8d9649114fe5da957c9a67432957f01e5dcc82e9" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" "checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20" @@ -586,7 +523,6 @@ dependencies = [ "checksum untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b65243989ef6aacd9c0d6bd2b822765c3361d8ed352185a6f3a41f3a718c673" "checksum url 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4a3440c1ed62af4a2aee71c6fb78ef32ddcb75cfa24bf42f45e07c02b6d6a2f6" "checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" "checksum uuid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "885acc3b17fdef6230d1f7765dff1106dfd5e75a93c2f26459fbf600ed6dcc14" "checksum webpki 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e499345fc4c6b7c79a5b8756d4592c4305510a13512e79efafe00dfbd67bbac6" "checksum webpki-roots 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bfb3f50499f21ad2317f442845e3b5805b007f1e728f59885c99e61b8c181a7" diff --git a/Cargo.toml b/Cargo.toml index 75ef407..1c57540 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ hyper = "0.10.2" hyper-rustls = "0.6.1" itertools = "0.4" log = "0.3" -openssl = "0.9.11" +rustls = "0.9.0" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" diff --git a/src/lib.rs b/src/lib.rs index 38500f7..2222c56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,9 +73,9 @@ extern crate serde_json; extern crate base64; extern crate chrono; -extern crate openssl; extern crate hyper; extern crate hyper_rustls; +extern crate rustls; #[cfg(test)] extern crate log; diff --git a/src/service_account.rs b/src/service_account.rs index 224aa88..082b58d 100644 --- a/src/service_account.rs +++ b/src/service_account.rs @@ -14,7 +14,7 @@ use std::borrow::BorrowMut; use std::default::Default; use std::error; -use std::io::Read; +use std::io::{self, Read}; use std::result; use std::str; @@ -25,10 +25,13 @@ use types::{StringError, Token}; use hyper::header; use url::form_urlencoded; +use rustls::{self, PrivateKey}; +use rustls::sign::{self, Signer}; +use rustls::internal::pemfile; + use base64; use chrono; use hyper; -use openssl; use serde_json; const GRANT_TYPE: &'static str = "urn:ietf:params:oauth:grant-type:jwt-bearer"; @@ -39,13 +42,20 @@ fn encode_base64>(s: T) -> String { base64::encode_config(s.as_ref(), base64::URL_SAFE) } -fn decode_rsa_key(pem_pkcs8: &str) -> Result> { - let private = pem_pkcs8.to_string().replace("\\n", "\n"); - let private_key = openssl::rsa::Rsa::private_key_from_pem(&mut private.as_bytes()); +fn decode_rsa_key(pem_pkcs8: &str) -> Result> { + let private = pem_pkcs8.to_string().replace("\\n", "\n").into_bytes(); + let mut private_reader: &[u8] = private.as_ref(); + let private_keys = pemfile::pkcs8_private_keys(&mut private_reader); - match private_key { - Err(e) => Err(Box::new(e)), - Ok(key) => Ok(key), + if let Ok(pk) = private_keys { + if pk.len() > 0 { + Ok(pk[0].clone()) + } else { + Err(Box::new(io::Error::new(io::ErrorKind::InvalidInput, + "Not enough private keys in PEM"))) + } + } else { + Err(Box::new(io::Error::new(io::ErrorKind::InvalidInput, "Error reading key from PEM"))) } } @@ -105,13 +115,11 @@ impl JWT { fn sign(&self, private_key: &str) -> Result> { let mut jwt_head = self.encode_claims(); let key = try!(decode_rsa_key(private_key)); - let pkey = try!(openssl::pkey::PKey::from_rsa(key)); - - let mut signer = - try!(openssl::sign::Signer::new( - openssl::hash::MessageDigest::sha256(), &pkey)); - signer.update(&jwt_head.as_bytes()).unwrap(); - let signature = signer.finish().unwrap(); + let signer = try!(sign::RSASigner::new(&key) + .map_err(|_| io::Error::new(io::ErrorKind::Other, "Couldn't initialize signer"))); + let signature = try!(signer.sign(rustls::SignatureScheme::RSA_PKCS1_SHA256, + jwt_head.as_bytes()) + .map_err(|_| io::Error::new(io::ErrorKind::Other, "Couldn't sign claims"))); let signature_b64 = encode_base64(signature); jwt_head.push_str(".");