use super::{Ed25519PublicKey, SkEd25519};
use crate::{
checked::CheckedSum, decode::Decode, encode::Encode, reader::Reader, writer::Writer, Algorithm,
Error, Result,
};
#[cfg(feature = "alloc")]
use super::{DsaPublicKey, RsaPublicKey};
#[cfg(feature = "ecdsa")]
use super::{EcdsaPublicKey, SkEcdsaSha2NistP256};
#[cfg(feature = "fingerprint")]
use crate::{Fingerprint, HashAlg};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum KeyData {
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
Dsa(DsaPublicKey),
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
Ecdsa(EcdsaPublicKey),
Ed25519(Ed25519PublicKey),
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
Rsa(RsaPublicKey),
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
SkEcdsaSha2NistP256(SkEcdsaSha2NistP256),
SkEd25519(SkEd25519),
}
impl KeyData {
pub fn algorithm(&self) -> Algorithm {
match self {
#[cfg(feature = "alloc")]
Self::Dsa(_) => Algorithm::Dsa,
#[cfg(feature = "ecdsa")]
Self::Ecdsa(key) => key.algorithm(),
Self::Ed25519(_) => Algorithm::Ed25519,
#[cfg(feature = "alloc")]
Self::Rsa(_) => Algorithm::Rsa { hash: None },
#[cfg(feature = "ecdsa")]
Self::SkEcdsaSha2NistP256(_) => Algorithm::SkEcdsaSha2NistP256,
Self::SkEd25519(_) => Algorithm::SkEd25519,
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn dsa(&self) -> Option<&DsaPublicKey> {
match self {
Self::Dsa(key) => Some(key),
_ => None,
}
}
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
pub fn ecdsa(&self) -> Option<&EcdsaPublicKey> {
match self {
Self::Ecdsa(key) => Some(key),
_ => None,
}
}
pub fn ed25519(&self) -> Option<&Ed25519PublicKey> {
match self {
Self::Ed25519(key) => Some(key),
#[allow(unreachable_patterns)]
_ => None,
}
}
#[cfg(feature = "fingerprint")]
#[cfg_attr(docsrs, doc(cfg(feature = "fingerprint")))]
pub fn fingerprint(&self, hash_alg: HashAlg) -> Fingerprint {
Fingerprint::new(hash_alg, self)
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn rsa(&self) -> Option<&RsaPublicKey> {
match self {
Self::Rsa(key) => Some(key),
_ => None,
}
}
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
pub fn sk_ecdsa_p256(&self) -> Option<&SkEcdsaSha2NistP256> {
match self {
Self::SkEcdsaSha2NistP256(sk) => Some(sk),
_ => None,
}
}
pub fn sk_ed25519(&self) -> Option<&SkEd25519> {
match self {
Self::SkEd25519(sk) => Some(sk),
_ => None,
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn is_dsa(&self) -> bool {
matches!(self, Self::Dsa(_))
}
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
pub fn is_ecdsa(&self) -> bool {
matches!(self, Self::Ecdsa(_))
}
pub fn is_ed25519(&self) -> bool {
matches!(self, Self::Ed25519(_))
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub fn is_rsa(&self) -> bool {
matches!(self, Self::Rsa(_))
}
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
pub fn is_sk_ecdsa_p256(&self) -> bool {
matches!(self, Self::SkEcdsaSha2NistP256(_))
}
pub fn is_sk_ed25519(&self) -> bool {
matches!(self, Self::SkEd25519(_))
}
pub(crate) fn decode_as(reader: &mut impl Reader, algorithm: Algorithm) -> Result<Self> {
match algorithm {
#[cfg(feature = "alloc")]
Algorithm::Dsa => DsaPublicKey::decode(reader).map(Self::Dsa),
#[cfg(feature = "ecdsa")]
Algorithm::Ecdsa { curve } => match EcdsaPublicKey::decode(reader)? {
key if key.curve() == curve => Ok(Self::Ecdsa(key)),
_ => Err(Error::Algorithm),
},
Algorithm::Ed25519 => Ed25519PublicKey::decode(reader).map(Self::Ed25519),
#[cfg(feature = "alloc")]
Algorithm::Rsa { .. } => RsaPublicKey::decode(reader).map(Self::Rsa),
#[cfg(feature = "ecdsa")]
Algorithm::SkEcdsaSha2NistP256 => {
SkEcdsaSha2NistP256::decode(reader).map(Self::SkEcdsaSha2NistP256)
}
Algorithm::SkEd25519 => SkEd25519::decode(reader).map(Self::SkEd25519),
#[allow(unreachable_patterns)]
_ => Err(Error::Algorithm),
}
}
pub(crate) fn encoded_key_data_len(&self) -> Result<usize> {
match self {
#[cfg(feature = "alloc")]
Self::Dsa(key) => key.encoded_len(),
#[cfg(feature = "ecdsa")]
Self::Ecdsa(key) => key.encoded_len(),
Self::Ed25519(key) => key.encoded_len(),
#[cfg(feature = "alloc")]
Self::Rsa(key) => key.encoded_len(),
#[cfg(feature = "ecdsa")]
Self::SkEcdsaSha2NistP256(sk) => sk.encoded_len(),
Self::SkEd25519(sk) => sk.encoded_len(),
}
}
pub(crate) fn encode_key_data(&self, writer: &mut impl Writer) -> Result<()> {
match self {
#[cfg(feature = "alloc")]
Self::Dsa(key) => key.encode(writer),
#[cfg(feature = "ecdsa")]
Self::Ecdsa(key) => key.encode(writer),
Self::Ed25519(key) => key.encode(writer),
#[cfg(feature = "alloc")]
Self::Rsa(key) => key.encode(writer),
#[cfg(feature = "ecdsa")]
Self::SkEcdsaSha2NistP256(sk) => sk.encode(writer),
Self::SkEd25519(sk) => sk.encode(writer),
}
}
}
impl Decode for KeyData {
fn decode(reader: &mut impl Reader) -> Result<Self> {
let algorithm = Algorithm::decode(reader)?;
Self::decode_as(reader, algorithm)
}
}
impl Encode for KeyData {
fn encoded_len(&self) -> Result<usize> {
[
self.algorithm().encoded_len()?,
self.encoded_key_data_len()?,
]
.checked_sum()
}
fn encode(&self, writer: &mut impl Writer) -> Result<()> {
self.algorithm().encode(writer)?;
self.encode_key_data(writer)
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl From<DsaPublicKey> for KeyData {
fn from(public_key: DsaPublicKey) -> KeyData {
Self::Dsa(public_key)
}
}
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
impl From<EcdsaPublicKey> for KeyData {
fn from(public_key: EcdsaPublicKey) -> KeyData {
Self::Ecdsa(public_key)
}
}
impl From<Ed25519PublicKey> for KeyData {
fn from(public_key: Ed25519PublicKey) -> KeyData {
Self::Ed25519(public_key)
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
impl From<RsaPublicKey> for KeyData {
fn from(public_key: RsaPublicKey) -> KeyData {
Self::Rsa(public_key)
}
}
#[cfg(feature = "ecdsa")]
#[cfg_attr(docsrs, doc(cfg(feature = "ecdsa")))]
impl From<SkEcdsaSha2NistP256> for KeyData {
fn from(public_key: SkEcdsaSha2NistP256) -> KeyData {
Self::SkEcdsaSha2NistP256(public_key)
}
}
impl From<SkEd25519> for KeyData {
fn from(public_key: SkEd25519) -> KeyData {
Self::SkEd25519(public_key)
}
}