mirror of https://github.com/ctz/rustls
Support PKCS8 private keys
Also follow upstream changes in ring/base64
This commit is contained in:
parent
1a1904ee4b
commit
dac2274e80
22
Cargo.toml
22
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "rustls"
|
||||
version = "0.5.8"
|
||||
version = "0.6.0"
|
||||
authors = ["Joseph Birr-Pixton <jpixton@gmail.com>"]
|
||||
license = "Apache-2.0/ISC/MIT"
|
||||
readme = "README.md"
|
||||
|
@ -10,24 +10,24 @@ repository = "https://github.com/ctz/rustls"
|
|||
categories = ["network-programming", "cryptography"]
|
||||
|
||||
[dependencies]
|
||||
untrusted = "0.3.1"
|
||||
time = "0.1.35"
|
||||
base64 = "~0.2.0"
|
||||
untrusted = "0.5"
|
||||
time = "0.1.37"
|
||||
base64 = "0.5"
|
||||
log = { version = "0.3.6", optional = true }
|
||||
ring = { version = "0.7", features = ["rsa_signing"] }
|
||||
webpki = "0.10"
|
||||
ring = { version = "0.8", features = ["rsa_signing"] }
|
||||
webpki = "0.11"
|
||||
|
||||
[features]
|
||||
default = ["logging"]
|
||||
logging = ["log"]
|
||||
|
||||
[dev-dependencies]
|
||||
log = "0.3.6"
|
||||
env_logger = "0.3.3"
|
||||
mio = "0.5.1"
|
||||
docopt = "0.6"
|
||||
log = "0.3.7"
|
||||
env_logger = "0.4.2"
|
||||
mio = "0.5"
|
||||
docopt = "0.7"
|
||||
rustc-serialize = "0.3"
|
||||
webpki-roots = "0.7"
|
||||
webpki-roots = "0.9"
|
||||
regex = "0.2"
|
||||
|
||||
[[example]]
|
||||
|
|
|
@ -396,7 +396,7 @@ Options:
|
|||
\
|
||||
--key KEYFILE Read private key from KEYFILE. This should be a RSA
|
||||
\
|
||||
private key, in PEM format.
|
||||
private key or PKCS8-encoded private key, in PEM format.
|
||||
--auth CERTFILE Enable client authentication, and accept \
|
||||
certificates
|
||||
signed by those roots provided in CERTFILE.
|
||||
|
@ -470,11 +470,29 @@ fn load_certs(filename: &str) -> Vec<rustls::Certificate> {
|
|||
}
|
||||
|
||||
fn load_private_key(filename: &str) -> rustls::PrivateKey {
|
||||
let keyfile = fs::File::open(filename).expect("cannot open private key file");
|
||||
let mut reader = BufReader::new(keyfile);
|
||||
let keys = rustls::internal::pemfile::rsa_private_keys(&mut reader).unwrap();
|
||||
assert!(keys.len() == 1);
|
||||
keys[0].clone()
|
||||
let rsa_keys = {
|
||||
let keyfile = fs::File::open(filename)
|
||||
.expect("cannot open private key file");
|
||||
let mut reader = BufReader::new(keyfile);
|
||||
rustls::internal::pemfile::rsa_private_keys(&mut reader)
|
||||
.expect("file contains invalid rsa private key")
|
||||
};
|
||||
|
||||
let pkcs8_keys = {
|
||||
let keyfile = fs::File::open(filename)
|
||||
.expect("cannot open private key file");
|
||||
let mut reader = BufReader::new(keyfile);
|
||||
rustls::internal::pemfile::pkcs8_private_keys(&mut reader)
|
||||
.expect("file contains invalid pkcs8 private key (encrypted keys not supported)")
|
||||
};
|
||||
|
||||
// prefer to load pkcs8 keys
|
||||
if !pkcs8_keys.is_empty() {
|
||||
pkcs8_keys[0].clone()
|
||||
} else {
|
||||
assert!(!rsa_keys.is_empty());
|
||||
rsa_keys[0].clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_config(args: &Args) -> Arc<rustls::ServerConfig> {
|
||||
|
|
|
@ -218,7 +218,7 @@ mod key;
|
|||
pub mod internal {
|
||||
/// Functions for parsing PEM files containing certificates/keys.
|
||||
pub mod pemfile {
|
||||
pub use pemfile::{certs, rsa_private_keys};
|
||||
pub use pemfile::{certs, rsa_private_keys, pkcs8_private_keys};
|
||||
}
|
||||
|
||||
/// Low-level TLS message parsing and encoding functions.
|
||||
|
|
|
@ -32,7 +32,10 @@ fn extract<A>(rd: &mut io::BufRead,
|
|||
|
||||
if line.starts_with(end_mark) {
|
||||
take_base64 = false;
|
||||
let der = try!(base64::decode_ws(&b64buf).map_err(|_| ()));
|
||||
let der = try! {
|
||||
base64::decode_config(&b64buf, base64::MIME)
|
||||
.map_err(|_| ())
|
||||
};
|
||||
ders.push(f(der));
|
||||
b64buf = String::new();
|
||||
continue;
|
||||
|
@ -62,3 +65,12 @@ pub fn rsa_private_keys(rd: &mut io::BufRead) -> Result<Vec<key::PrivateKey>, ()
|
|||
"-----END RSA PRIVATE KEY-----",
|
||||
&|v| key::PrivateKey(v))
|
||||
}
|
||||
|
||||
/// Extract all PKCS8-encoded private keys from rd, and return a vec of
|
||||
/// `key::PrivateKey`s containing the der-format contents.
|
||||
pub fn pkcs8_private_keys(rd: &mut io::BufRead) -> Result<Vec<key::PrivateKey>, ()> {
|
||||
extract(rd,
|
||||
"-----BEGIN PRIVATE KEY-----",
|
||||
"-----END PRIVATE KEY-----",
|
||||
&|v| key::PrivateKey(v))
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use ring::hmac;
|
|||
|
||||
use std::io::Write;
|
||||
|
||||
fn concat_sign(key: &hmac::SigningKey, a: &[u8], b: &[u8]) -> digest::Digest {
|
||||
fn concat_sign(key: &hmac::SigningKey, a: &[u8], b: &[u8]) -> hmac::Signature {
|
||||
let mut ctx = hmac::SigningContext::with_key(key);
|
||||
ctx.update(a);
|
||||
ctx.update(b);
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
/// for our own use. These functions never fail,
|
||||
/// they panic on error.
|
||||
|
||||
use ring;
|
||||
use ring::rand::{SystemRandom, SecureRandom};
|
||||
use msgs::codec;
|
||||
|
||||
/// Fill the whole slice with random material.
|
||||
pub fn fill_random(bytes: &mut [u8]) {
|
||||
ring::rand::SystemRandom::new()
|
||||
SystemRandom::new()
|
||||
.fill(bytes)
|
||||
.unwrap();
|
||||
}
|
||||
|
|
|
@ -232,7 +232,8 @@ struct AlwaysResolvesChain {
|
|||
|
||||
impl AlwaysResolvesChain {
|
||||
fn new_rsa(chain: Vec<key::Certificate>, priv_key: &key::PrivateKey) -> AlwaysResolvesChain {
|
||||
let key = sign::RSASigner::new(priv_key).expect("Invalid RSA private key");
|
||||
let key = sign::RSASigner::new(priv_key)
|
||||
.expect("Invalid RSA private key");
|
||||
AlwaysResolvesChain {
|
||||
chain: chain,
|
||||
key: Arc::new(Box::new(key)),
|
||||
|
|
36
src/sign.rs
36
src/sign.rs
|
@ -3,6 +3,7 @@ use util;
|
|||
use untrusted;
|
||||
use ring;
|
||||
use ring::signature;
|
||||
use ring::signature::RSAKeyPair;
|
||||
use std::sync::Arc;
|
||||
use key;
|
||||
|
||||
|
@ -22,27 +23,28 @@ pub type CertChainAndSigner = (Vec<key::Certificate>, Arc<Box<Signer>>);
|
|||
|
||||
/// A Signer for RSA-PKCS1 or RSA-PSS
|
||||
pub struct RSASigner {
|
||||
key: Arc<signature::RSAKeyPair>,
|
||||
schemes: Vec<SignatureScheme>,
|
||||
key: Arc<RSAKeyPair>,
|
||||
schemes: &'static [SignatureScheme],
|
||||
}
|
||||
|
||||
fn all_schemes() -> Vec<SignatureScheme> {
|
||||
vec![SignatureScheme::RSA_PSS_SHA512,
|
||||
SignatureScheme::RSA_PSS_SHA384,
|
||||
SignatureScheme::RSA_PSS_SHA256,
|
||||
SignatureScheme::RSA_PKCS1_SHA512,
|
||||
SignatureScheme::RSA_PKCS1_SHA384,
|
||||
SignatureScheme::RSA_PKCS1_SHA256]
|
||||
}
|
||||
static ALL_SCHEMES: &'static [SignatureScheme] = &[
|
||||
SignatureScheme::RSA_PSS_SHA512,
|
||||
SignatureScheme::RSA_PSS_SHA384,
|
||||
SignatureScheme::RSA_PSS_SHA256,
|
||||
SignatureScheme::RSA_PKCS1_SHA512,
|
||||
SignatureScheme::RSA_PKCS1_SHA384,
|
||||
SignatureScheme::RSA_PKCS1_SHA256,
|
||||
];
|
||||
|
||||
impl RSASigner {
|
||||
pub fn new(der: &key::PrivateKey) -> Result<RSASigner, ()> {
|
||||
let key = signature::RSAKeyPair::from_der(untrusted::Input::from(&der.0));
|
||||
key.map(|s| {
|
||||
RSASigner {
|
||||
key: Arc::new(s),
|
||||
schemes: all_schemes(),
|
||||
}
|
||||
RSAKeyPair::from_der(untrusted::Input::from(&der.0))
|
||||
.or_else(|_| RSAKeyPair::from_pkcs8(untrusted::Input::from(&der.0)))
|
||||
.map(|s| {
|
||||
RSASigner {
|
||||
key: Arc::new(s),
|
||||
schemes: ALL_SCHEMES,
|
||||
}
|
||||
})
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
@ -50,7 +52,7 @@ impl RSASigner {
|
|||
|
||||
impl Signer for RSASigner {
|
||||
fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<SignatureScheme> {
|
||||
util::first_in_both(&self.schemes, offered)
|
||||
util::first_in_both(self.schemes, offered)
|
||||
}
|
||||
|
||||
fn sign(&self, scheme: SignatureScheme, message: &[u8]) -> Result<Vec<u8>, ()> {
|
||||
|
|
Loading…
Reference in New Issue