Merge pull request #80 from jamwt/no-openssl

No openssl feature
This commit is contained in:
Lewin Bormann
2019-01-08 10:51:37 +01:00
committed by GitHub
3 changed files with 61 additions and 5 deletions

View File

@@ -11,6 +11,7 @@ script:
- travis-cargo test
- travis-cargo build -- --manifest-path examples/drive_example/Cargo.toml
- travis-cargo build -- --manifest-path examples/service_account/Cargo.toml
- travis-cargo test -- --no-default-features --features no-openssl
after_success:
- "[[ $TRAVIS_OS_NAME = linux ]] && travis-cargo --only stable coveralls"
env:

View File

@@ -17,12 +17,17 @@ hyper = "0.10.2"
hyper-native-tls = "0.3"
itertools = "0.7"
log = "0.3"
openssl = "0.10"
openssl = {version = "0.10", optional = true}
rustls = {version = "0.14", optional = true}
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
url = "1"
[features]
default = ["openssl"]
no-openssl = ["rustls"]
[dev-dependencies]
getopts = "0.2"
open = "1.1"

View File

@@ -25,10 +25,23 @@ use crate::types::{StringError, Token};
use hyper::header;
use url::form_urlencoded;
use openssl::sign::Signer;
use openssl::hash::MessageDigest;
use openssl::pkey::{PKey, Private};
use openssl::rsa::Padding;
#[cfg(not(feature = "no-openssl"))]
use openssl::{
sign::Signer,
hash::MessageDigest,
pkey::{PKey, Private},
rsa::Padding,
};
#[cfg(feature = "no-openssl")]
use rustls::{
self,
PrivateKey,
sign::{self, SigningKey},
internal::pemfile,
};
#[cfg(feature = "no-openssl")]
use std::io;
use base64;
use chrono;
@@ -43,11 +56,30 @@ fn encode_base64<T: AsRef<[u8]>>(s: T) -> String {
base64::encode_config(s.as_ref(), base64::URL_SAFE)
}
#[cfg(not(feature = "no-openssl"))]
fn decode_rsa_key(pem_pkcs8: &str) -> Result<PKey<Private>, Box<error::Error>> {
let private = pem_pkcs8.to_string().replace("\\n", "\n").into_bytes();
Ok(PKey::private_key_from_pem(&private)?)
}
#[cfg(feature = "no-openssl")]
fn decode_rsa_key(pem_pkcs8: &str) -> Result<PrivateKey, Box<error::Error>> {
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);
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")))
}
}
/// JSON schema of secret service account key. You can obtain the key from
/// the Cloud Console at https://console.cloud.google.com/.
///
@@ -101,6 +133,7 @@ impl JWT {
head
}
#[cfg(not(feature = "no-openssl"))]
fn sign(&self, private_key: &str) -> Result<String, Box<error::Error>> {
let mut jwt_head = self.encode_claims();
let key = decode_rsa_key(private_key)?;
@@ -115,6 +148,23 @@ impl JWT {
Ok(jwt_head)
}
#[cfg(feature = "no-openssl")]
fn sign(&self, private_key: &str) -> Result<String, Box<error::Error>> {
let mut jwt_head = self.encode_claims();
let key = decode_rsa_key(private_key)?;
let signing_key = sign::RSASigningKey::new(&key)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "Couldn't initialize signer"))?;
let signer = signing_key.choose_scheme(&[rustls::SignatureScheme::RSA_PKCS1_SHA256])
.ok_or(io::Error::new(io::ErrorKind::Other, "Couldn't choose signing scheme"))?;
let signature = signer.sign(jwt_head.as_bytes())?;
let signature_b64 = encode_base64(signature);
jwt_head.push_str(".");
jwt_head.push_str(&signature_b64);
Ok(jwt_head)
}
}
fn init_claims_from_key<'a, I, T>(key: &ServiceAccountKey, scopes: I) -> Claims