use crate::error::{self, Result};
use crate::schema::key::Key;
use ring::rand::SecureRandom;
use ring::signature::{KeyPair, RsaKeyPair};
use snafu::ResultExt;
use std::collections::HashMap;
pub trait Sign: Sync + Send {
fn tuf_key(&self) -> crate::schema::key::Key;
fn sign(&self, msg: &[u8], rng: &dyn SecureRandom) -> Result<Vec<u8>>;
}
impl Sign for RsaKeyPair {
fn tuf_key(&self) -> Key {
use crate::schema::key::{RsaKey, RsaScheme};
Key::Rsa {
keyval: RsaKey {
public: self.public_key().as_ref().to_vec().into(),
_extra: HashMap::new(),
},
scheme: RsaScheme::RsassaPssSha256,
_extra: HashMap::new(),
}
}
fn sign(&self, msg: &[u8], rng: &dyn SecureRandom) -> Result<Vec<u8>> {
let mut signature = vec![0; self.public_modulus_len()];
self.sign(&ring::signature::RSA_PSS_SHA256, rng, msg, &mut signature)
.context(error::Sign)?;
Ok(signature)
}
}
pub fn parse_keypair(key: &[u8]) -> Result<impl Sign> {
if let Ok(pem) = pem::parse(key) {
match pem.tag.as_str() {
"PRIVATE KEY" => {
if let Ok(rsa_key_pair) = RsaKeyPair::from_pkcs8(&pem.contents) {
Ok(rsa_key_pair)
} else {
error::KeyUnrecognized.fail()
}
}
"RSA PRIVATE KEY" => {
Ok(RsaKeyPair::from_der(&pem.contents).context(error::KeyRejected)?)
}
_ => error::KeyUnrecognized.fail(),
}
} else {
error::KeyUnrecognized.fail()
}
}