use {Error, ErrorKind, KEYTYPE_ED25519, KEYTYPE_RSA, rsa_key_from_components};
use std;
use thrussh::encoding::Reader;
use thrussh::key;
use super::is_base64_char;
use hex::FromHex;
use base64::{decode_config, MIME};
use ring::signature;
use untrusted;
use yasna;
use ring;
use openssl::symm::{encrypt, decrypt, Cipher, Mode, Crypter};
use openssl::hash::{MessageDigest, Hasher};
use bcrypt_pbkdf;
const PBES2: &'static [u64] = &[1, 2, 840, 113549, 1, 5, 13];
const PBKDF2: &'static [u64] = &[1, 2, 840, 113549, 1, 5, 12];
const HMAC_SHA256: &'static [u64] = &[1, 2, 840, 113549, 2, 9];
const AES256CBC: &'static [u64] = &[2, 16, 840, 1, 101, 3, 4, 1, 42];
const ED25519: &'static [u64] = &[1, 3, 101, 112];
const RSA: &'static [u64] = &[1, 2, 840, 113549, 1, 1, 1];
fn decode_pkcs8(
secret: &[u8],
password: Option<&[u8]>,
) -> Result<(key::Algorithm, super::KeyPairComponents), Error> {
if let Some(pass) = password {
let secret = yasna::parse_der(&secret, |reader| {
reader.read_sequence(|reader| {
let parameters = reader.next().read_sequence(|reader| {
let oid = reader.next().read_oid()?;
debug!("oid = {:?} {:?}", oid, oid.components().as_slice() == PBES2);
if oid.components().as_slice() == PBES2 {
asn1_read_pbes2(reader)
} else {
Ok(Err(ErrorKind::UnknownAlgorithm(oid).into()))
}
})?;
let ciphertext = reader.next().read_bytes()?;
Ok(parameters.map(|p| p.decrypt(pass, &ciphertext)))
})
})???;
debug!("secret {:?}", secret);
let mut oid = None;
yasna::parse_der(&secret, |reader| {
reader.read_sequence(|reader| {
let version = reader.next().read_u64()?;
debug!("version = {:?}", version);
reader.next().read_sequence(|reader| {
oid = Some(reader.next().read_oid()?);
Ok(())
}).unwrap_or(());
Ok(())
})
}).unwrap_or(());
debug!("pkcs8 oid {:?}", oid);
let oid = if let Some(oid) = oid {
oid
} else {
return Err(ErrorKind::CouldNotReadKey.into())
};
if oid.components().as_slice() == ED25519 {
let components = signature::primitive::Ed25519KeyPairComponents::from_pkcs8(
untrusted::Input::from(&secret),
)?;
debug!("components!");
let keypair = signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&secret))?;
debug!("keypair!");
Ok((key::Algorithm::Ed25519(keypair),
super::KeyPairComponents::Ed25519(components)))
} else if oid.components().as_slice() == RSA {
let components = signature::primitive::RSAKeyPairComponents::from_pkcs8(
untrusted::Input::from(&secret),
)?;
let keypair = signature::RSAKeyPair::from_pkcs8(untrusted::Input::from(&secret))?;
Ok((
key::Algorithm::RSA(
std::sync::Arc::new(keypair),
key::RSAPublicKey {
n: components.n.as_slice_less_safe().to_vec(),
e: components.e.as_slice_less_safe().to_vec(),
hash: key::SignatureHash::SHA2_512,
},
),
super::KeyPairComponents::RSA(
super::RSAKeyPairComponents::from_components(&components),
),
))
} else {
Err(ErrorKind::CouldNotReadKey.into())
}
} else {
Err(ErrorKind::KeyIsEncrypted.into())
}
}
#[cfg(test)]
use env_logger;
#[test]
fn test_read_write_pkcs8() {
env_logger::init().unwrap_or(());
let r = ring::rand::SystemRandom::new();
let key = ring::signature::Ed25519KeyPair::generate_pkcs8(&r).unwrap();
let password = b"blabla";
let ciphertext = encode_pkcs8(&r, &key, Some(password), 100).unwrap();
let (_, comp) = decode_pkcs8(&ciphertext, Some(password)).unwrap();
use super::KeyPairComponents;
match comp {
KeyPairComponents::Ed25519(_) => debug!("Ed25519"),
KeyPairComponents::RSA(_) => debug!("RSA"),
}
}
use yasna::models::ObjectIdentifier;
pub fn encode_pkcs8<R:ring::rand::SecureRandom>(
rand: &R,
plaintext: &[u8],
password: Option<&[u8]>,
rounds: u32
) -> Result<Vec<u8>, Error> {
if let Some(pass) = password {
let mut salt = [0; 64];
rand.fill(&mut salt)?;
let mut iv = [0; 16];
rand.fill(&mut iv)?;
let mut key = [0; 32]; ring::pbkdf2::derive(&ring::digest::SHA256, rounds, &salt, pass, &mut key[..]);
debug!("key = {:?}", key);
let mut plaintext = plaintext.to_vec();
let padding_len = 32 - (plaintext.len() % 32);
plaintext.extend(std::iter::repeat(padding_len as u8).take(padding_len));
debug!("plaintext {:?}", plaintext);
let ciphertext = encrypt(Cipher::aes_256_cbc(), &key, Some(&iv), &plaintext)?;
let v = yasna::construct_der(|writer| {
writer.write_sequence(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(PBES2));
asn1_write_pbes2(writer.next(), rounds as u64, &salt, &iv)
});
writer.next().write_bytes(&ciphertext[..])
})
});
Ok(v)
} else {
Err(ErrorKind::KeyIsEncrypted.into())
}
}
fn asn1_write_pbes2(writer: yasna::DERWriter, rounds: u64, salt: &[u8], iv: &[u8]) {
writer.write_sequence(|writer| {
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(PBKDF2));
asn1_write_pbkdf2(writer.next(), rounds, salt)
});
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(AES256CBC));
writer.next().write_bytes(iv)
});
})
}
fn asn1_write_pbkdf2(writer: yasna::DERWriter, rounds: u64, salt: &[u8]) {
writer.write_sequence(|writer| {
writer.next().write_bytes(salt);
writer.next().write_u64(rounds);
writer.next().write_sequence(|writer| {
writer.next().write_oid(&ObjectIdentifier::from_slice(HMAC_SHA256));
writer.next().write_null()
})
})
}
enum Algorithms {
Pbes2(KeyDerivation, Encryption),
}
impl Algorithms {
fn decrypt(&self, password: &[u8], cipher: &[u8]) -> Result<Vec<u8>, Error> {
match *self {
Algorithms::Pbes2(ref der, ref enc) => {
let mut key = enc.key();
der.derive(password, &mut key);
let out = enc.decrypt(&key, cipher)?;
Ok(out)
}
}
}
}
impl KeyDerivation {
fn derive(&self, password: &[u8], key: &mut [u8]) {
match *self {
KeyDerivation::Pbkdf2 {
ref salt,
rounds,
digest,
} => ring::pbkdf2::derive(digest, rounds as u32, salt, password, key),
}
}
}
enum Key {
K128([u8; 16]),
K256([u8; 32]),
}
impl std::ops::Deref for Key {
type Target = [u8];
fn deref(&self) -> &[u8] {
match *self {
Key::K128(ref k) => k,
Key::K256(ref k) => k,
}
}
}
impl std::ops::DerefMut for Key {
fn deref_mut(&mut self) -> &mut [u8] {
match *self {
Key::K128(ref mut k) => k,
Key::K256(ref mut k) => k,
}
}
}
impl Encryption {
fn key(&self) -> Key {
match *self {
Encryption::Aes128Cbc(_) => Key::K128([0; 16]),
Encryption::Aes256Cbc(_) => Key::K256([0; 32]),
}
}
fn decrypt(&self, key: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error> {
let (cipher, iv) = match *self {
Encryption::Aes128Cbc(ref iv) => (Cipher::aes_128_cbc(), iv),
Encryption::Aes256Cbc(ref iv) => (Cipher::aes_256_cbc(), iv),
};
let mut dec = decrypt(
cipher,
&key,
Some(&iv[..]),
ciphertext
)?;
pkcs_unpad(&mut dec);
Ok(dec)
}
}
enum KeyDerivation {
Pbkdf2 {
salt: Vec<u8>,
rounds: u64,
digest: &'static ring::digest::Algorithm,
},
}
fn asn1_read_pbes2(
reader: &mut yasna::BERReaderSeq,
) -> Result<Result<Algorithms, Error>, yasna::ASN1Error> {
reader.next().read_sequence(|reader| {
let keygen = reader.next().read_sequence(|reader| {
let oid = reader.next().read_oid()?;
if oid.components().as_slice() == PBKDF2 {
asn1_read_pbkdf2(reader)
} else {
Ok(Err(ErrorKind::UnknownAlgorithm(oid).into()))
}
})?;
let algorithm = reader.next().read_sequence(|reader| {
let oid = reader.next().read_oid()?;
if oid.components().as_slice() == AES256CBC {
asn1_read_aes256cbc(reader)
} else {
Ok(Err(ErrorKind::UnknownAlgorithm(oid).into()))
}
})?;
Ok(keygen.and_then(|keygen| {
algorithm.map(|algo| Algorithms::Pbes2(keygen, algo))
}))
})
}
fn asn1_read_pbkdf2(
reader: &mut yasna::BERReaderSeq,
) -> Result<Result<KeyDerivation, Error>, yasna::ASN1Error> {
reader.next().read_sequence(|reader| {
let salt = reader.next().read_bytes()?;
let rounds = reader.next().read_u64()?;
let digest = reader.next().read_sequence(|reader| {
let oid = reader.next().read_oid()?;
if oid.components().as_slice() == HMAC_SHA256 {
reader.next().read_null()?;
Ok(Ok(&ring::digest::SHA256))
} else {
Ok(Err(ErrorKind::UnknownAlgorithm(oid).into()))
}
})?;
Ok(digest.map(|digest| {
KeyDerivation::Pbkdf2 {
salt,
rounds,
digest,
}
}))
})
}
fn asn1_read_aes256cbc(
reader: &mut yasna::BERReaderSeq,
) -> Result<Result<Encryption, Error>, yasna::ASN1Error> {
let iv = reader.next().read_bytes()?;
let mut i = [0; 16];
i.clone_from_slice(&iv);
Ok(Ok(Encryption::Aes256Cbc(i)))
}