use ring::rand::{SecureRandom, SystemRandom};
use std::fmt::{self, Debug};
use ring::signature::ECDSAKeyPair as ECDSAPrivateKey;
use ring::signature::{Signature, ECDSA_P256_SHA256_ASN1_SIGNING};
use untrusted;
use AsymmetricAlg;
pub(crate) const ECDSA_KEY_PAIR_SIZE: usize = 96;
pub(crate) const ECDSA_PUBLIC_KEY_SIZE: usize = 64;
pub(crate) struct ECDSAKeyPair {
pub algorithm: AsymmetricAlg,
pub private_key_bytes: Vec<u8>,
pub public_key_bytes: Vec<u8>,
}
impl ECDSAKeyPair {
pub fn generate(algorithm: AsymmetricAlg, csprng: &SecureRandom) -> Self {
let signing_algorithm = match algorithm {
AsymmetricAlg::EC_P256 => &ECDSA_P256_SHA256_ASN1_SIGNING,
_ => panic!("unsupported ECDSA algorithm: {:?}", algorithm),
};
let private_key_bytes = Vec::from(
ECDSAPrivateKey::generate_pkcs8(signing_algorithm, csprng)
.unwrap()
.as_ref(),
);
let private_key_len = private_key_bytes.len();
let public_key_bytes =
Vec::from(&private_key_bytes[(private_key_len - ECDSA_PUBLIC_KEY_SIZE)..]);
Self {
algorithm,
private_key_bytes,
public_key_bytes,
}
}
pub fn sign<T: AsRef<[u8]>>(&self, message: T) -> Signature {
let signing_algorithm = match self.algorithm {
AsymmetricAlg::EC_P256 => &ECDSA_P256_SHA256_ASN1_SIGNING,
_ => panic!("unsupported ECDSA algorithm: {:?}", self.algorithm),
};
let private_key = ECDSAPrivateKey::from_pkcs8(
signing_algorithm,
untrusted::Input::from(&self.private_key_bytes),
).unwrap();
private_key
.sign(
untrusted::Input::from(message.as_ref()),
&SystemRandom::new(),
).unwrap()
}
}
impl Debug for ECDSAKeyPair {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ECDSAKeyPair {{ alg: {:?} }}", self.algorithm)
}
}