use crate::error::DatError;
use crate::signature_algorithm::DatSignatureAlgorithm;
use aws_lc_rs::signature::{EcdsaKeyPair, KeyPair, UnparsedPublicKey, ECDSA_P256_SHA256_FIXED, ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED, ECDSA_P384_SHA384_FIXED_SIGNING, ECDSA_P521_SHA512_FIXED, ECDSA_P521_SHA512_FIXED_SIGNING};
use strum_macros::{Display, EnumString};
#[repr(u8)]
#[derive(Debug, Display, EnumString, Clone, Copy, Eq, PartialEq)]
pub enum DatSignatureKeyOutOption {
FULL,
SIGNING,
VERIFYING,
}
pub struct DatSignatureKey {
algorithm: DatSignatureAlgorithm,
signing_key: Option<EcdsaKeyPair>,
signing_key_bytes: Vec<u8>,
verifying_key: UnparsedPublicKey<Vec<u8>>,
}
impl DatSignatureKey {
pub fn generate(algorithm: DatSignatureAlgorithm) -> Result<Self, DatError> {
Self::from_or_new(true, algorithm, &[], &[])
}
pub fn from_bytes(algorithm: DatSignatureAlgorithm, signing_key_bytes: &[u8], verifying_key_bytes: &[u8]) -> Result<DatSignatureKey, DatError> {
Self::from_or_new(false, algorithm, signing_key_bytes, verifying_key_bytes)
}
fn from_or_new(new: bool, algorithm: DatSignatureAlgorithm, signing_key_bytes: &[u8], verifying_key_bytes: &[u8]) -> Result<DatSignatureKey, DatError> {
let (sa, va) = match algorithm {
DatSignatureAlgorithm::P256 => &(ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P256_SHA256_FIXED),
DatSignatureAlgorithm::P384 => &(ECDSA_P384_SHA384_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED),
DatSignatureAlgorithm::P521 => &(ECDSA_P521_SHA512_FIXED_SIGNING, ECDSA_P521_SHA512_FIXED),
};
let rng = aws_lc_rs::rand::SystemRandom::new();
let mut signing_key_bytes = Vec::from(signing_key_bytes);
let mut verifying_key_bytes = Vec::from(verifying_key_bytes);
let pkcs8_private_key = if new {
let pkcs8_private_key = Vec::from(EcdsaKeyPair::generate_pkcs8(sa, &rng).map_err(|_| DatError::CreateDatSigningKeyError)?.as_ref());
signing_key_bytes = to_raw(algorithm, &pkcs8_private_key)?;
pkcs8_private_key
} else {
to_pkcs8_der(algorithm, &signing_key_bytes)?
};
let signing_key: Option<EcdsaKeyPair> = if pkcs8_private_key.is_empty() {
None
} else {
let sk = EcdsaKeyPair::from_pkcs8(sa, &*pkcs8_private_key)
.map_err(|_| { DatError::ParseDatSigningKeyError })?;
if verifying_key_bytes.is_empty() {
verifying_key_bytes = Vec::from(sk.public_key().as_ref());
}
Some(sk)
};
if verifying_key_bytes.is_empty() {
return Err(DatError::ParseDatVerifyingKeyError);
}
let verifying_key = UnparsedPublicKey::new(va, verifying_key_bytes);
Ok(DatSignatureKey {
algorithm,
signing_key,
signing_key_bytes,
verifying_key,
})
}
pub fn algorithm(&self) -> DatSignatureAlgorithm {
self.algorithm
}
pub fn signature_size(&self) -> usize {
match self.algorithm {
DatSignatureAlgorithm::P256 => 64,
DatSignatureAlgorithm::P384 => 96,
DatSignatureAlgorithm::P521 => 132,
}
}
pub fn raw_signing_key_size(&self) -> usize {
match self.algorithm {
DatSignatureAlgorithm::P256 => 32,
DatSignatureAlgorithm::P384 => 48,
DatSignatureAlgorithm::P521 => 66,
}
}
pub fn to_bytes(&self) -> (Box<[u8]>, Box<[u8]>) {
(Box::from(&*self.signing_key_bytes), Box::from(&*self.verifying_key.as_ref()))
}
pub fn sign(&self, data: &[u8]) -> Result<Box<[u8]>, DatError> {
self.signing_key.as_ref().ok_or_else(|| DatError::VerifyOnlyKey)?
.sign(&aws_lc_rs::rand::SystemRandom::new(), data)
.map(|x| Box::from(x.as_ref()))
.map_err(|_| DatError::DatSignatureError)
}
pub fn verify(&self, body: &[u8], sign: &[u8]) -> Result<(), DatError> {
self.verifying_key.verify(body, sign).map_err(|_| DatError::InvalidDat)
}
pub fn has_signing_key(&self) -> bool {
self.signing_key.is_some()
}
}
impl Clone for DatSignatureKey {
fn clone(&self) -> Self {
let (k, v) = self.to_bytes();
DatSignatureKey::from_bytes(self.algorithm(), &*k, &*v).unwrap()
}
}
pub fn to_pkcs8_der(algorithm: DatSignatureAlgorithm, signing_key: &[u8]) -> Result<Vec<u8>, DatError> {
if signing_key.is_empty() {
return Ok(Vec::new());
}
Ok(match algorithm {
DatSignatureAlgorithm::P256 => {
let k = p256::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?;
p256::pkcs8::EncodePrivateKey::to_pkcs8_der(&k).map_err(|_| DatError::ParseDatSigningKeyError)?.as_bytes().to_vec()
},
DatSignatureAlgorithm::P384 => {
let k = p384::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?;
p384::pkcs8::EncodePrivateKey::to_pkcs8_der(&k).map_err(|_| DatError::ParseDatSigningKeyError)?.as_bytes().to_vec()
},
DatSignatureAlgorithm::P521 => {
let k = p521::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?;
p521::pkcs8::EncodePrivateKey::to_pkcs8_der(&k).map_err(|_| DatError::ParseDatSigningKeyError)?.as_bytes().to_vec()
},
})
}
pub fn to_raw(algorithm: DatSignatureAlgorithm, pkcs8_der: &[u8]) -> Result<Vec<u8>, DatError> {
if pkcs8_der.is_empty() {
return Ok(Vec::new());
}
Ok(match algorithm {
DatSignatureAlgorithm::P256 => {
let k: p256::ecdsa::SigningKey = p256::pkcs8::DecodePrivateKey::from_pkcs8_der(pkcs8_der).map_err(|_| DatError::ParseDatSigningKeyError)?;
k.to_bytes().to_vec()
},
DatSignatureAlgorithm::P384 => {
let k: p384::ecdsa::SigningKey = p384::pkcs8::DecodePrivateKey::from_pkcs8_der(pkcs8_der).map_err(|_| DatError::ParseDatSigningKeyError)?;
k.to_bytes().to_vec()
},
DatSignatureAlgorithm::P521 => {
let k: p521::ecdsa::SigningKey = p521::pkcs8::DecodePrivateKey::from_pkcs8_der(pkcs8_der).map_err(|_| DatError::ParseDatSigningKeyError)?;
k.to_bytes().to_vec()
},
})
}