use const_oid::db::{
rfc5753::ID_EC_PUBLIC_KEY,
rfc5912::{RSA_ENCRYPTION, SECP_256_R_1, SECP_384_R_1, SECP_521_R_1},
rfc8410::{ID_ED_448, ID_ED_25519},
};
use der::{Decode, asn1::OctetString, pem::PemLabel};
use pkcs8::DecodePrivateKey;
use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey};
use spki::DecodePublicKey;
use crate::{
EdwardsSigningKey, EdwardsVerifyingKey, EllipticSigningKey, EllipticVerifyingKey,
RsaSigningKey, RsaVerifyingKey,
};
pub enum VerifyingKey {
Rsa(RsaVerifyingKey),
Elliptic(EllipticVerifyingKey),
Edwards(EdwardsVerifyingKey),
}
#[expect(clippy::large_enum_variant)]
pub enum SigningKey {
Rsa(RsaSigningKey),
Elliptic(EllipticSigningKey),
Edwards(EdwardsSigningKey),
}
impl VerifyingKey {
pub fn from_pem(pem: &[u8]) -> Option<Self> {
let (label, der) = der::pem::decode_vec(pem).ok()?;
match label {
spki::SubjectPublicKeyInfoOwned::PEM_LABEL => {
let spki = spki::SubjectPublicKeyInfoRef::from_der(&der).ok()?;
match spki.algorithm.oid {
ID_EC_PUBLIC_KEY => match spki.algorithm.parameters_oid().ok()? {
SECP_256_R_1 => {
let key = p256::ecdsa::VerifyingKey::from_public_key_der(&der).ok()?;
Some(Self::Elliptic(EllipticVerifyingKey::Prime256(key)))
}
SECP_384_R_1 => {
let key = p384::ecdsa::VerifyingKey::from_public_key_der(&der).ok()?;
Some(Self::Elliptic(EllipticVerifyingKey::Prime384(key)))
}
SECP_521_R_1 => {
let key = p521::ecdsa::VerifyingKey::from_public_key_der(&der).ok()?;
Some(Self::Elliptic(EllipticVerifyingKey::Prime521(key)))
}
_ => None,
},
RSA_ENCRYPTION => {
let key = rsa::RsaPublicKey::from_public_key_der(&der).ok()?;
Some(Self::Rsa(RsaVerifyingKey(key)))
}
ID_ED_25519 => {
let key = ed25519_dalek::VerifyingKey::from_public_key_der(&der).ok()?;
Some(Self::Edwards(EdwardsVerifyingKey::Ed25519(key)))
}
ID_ED_448 => {
let key = ed448_goldilocks::VerifyingKey::from_public_key_der(&der).ok()?;
Some(Self::Edwards(EdwardsVerifyingKey::Ed448(key)))
}
_ => None,
}
}
rsa::pkcs1::RsaPublicKey::PEM_LABEL => {
let key = rsa::RsaPublicKey::from_pkcs1_der(&der).ok()?;
Some(Self::Rsa(RsaVerifyingKey(key)))
}
_ => None,
}
}
pub fn key_id(&self) -> Vec<u8> {
match &self {
Self::Rsa(key) => key.key_id(),
Self::Elliptic(key) => key.key_id(),
Self::Edwards(key) => key.key_id(),
}
}
}
impl SigningKey {
pub fn from_pem(pem: &[u8]) -> Option<Self> {
let (label, der) = der::pem::decode_vec(pem).ok()?;
match label {
sec1::EcPrivateKey::PEM_LABEL => {
let sec1 = sec1::EcPrivateKey::from_der(&der).ok()?;
let curve = sec1.parameters?.named_curve()?;
match curve {
SECP_256_R_1 => {
let key = p256::ecdsa::SigningKey::from_slice(sec1.private_key).ok()?;
Some(Self::Elliptic(EllipticSigningKey::Prime256(key)))
}
SECP_384_R_1 => {
let key = p384::ecdsa::SigningKey::from_slice(sec1.private_key).ok()?;
Some(Self::Elliptic(EllipticSigningKey::Prime384(key)))
}
SECP_521_R_1 => {
let key = p521::ecdsa::SigningKey::from_slice(sec1.private_key).ok()?;
Some(Self::Elliptic(EllipticSigningKey::Prime521(key)))
}
_ => None,
}
}
rsa::pkcs1::RsaPrivateKey::PEM_LABEL => {
let key = rsa::RsaPrivateKey::from_pkcs1_der(&der).ok()?;
Some(Self::Rsa(RsaSigningKey(key)))
}
pkcs8::PrivateKeyInfoOwned::PEM_LABEL => {
let pkcs8 = pkcs8::PrivateKeyInfoRef::from_der(&der).ok()?;
let algorithm = pkcs8.algorithm.oid;
match algorithm {
ID_EC_PUBLIC_KEY => match pkcs8.algorithm.parameters_oid().ok()? {
SECP_256_R_1 => {
let key = p256::ecdsa::SigningKey::from_pkcs8_der(&der).ok()?;
Some(Self::Elliptic(EllipticSigningKey::Prime256(key)))
}
SECP_384_R_1 => {
let key = p384::ecdsa::SigningKey::from_pkcs8_der(&der).ok()?;
Some(Self::Elliptic(EllipticSigningKey::Prime384(key)))
}
SECP_521_R_1 => {
let key = p521::ecdsa::SigningKey::from_pkcs8_der(&der).ok()?;
Some(Self::Elliptic(EllipticSigningKey::Prime521(key)))
}
_ => None,
},
RSA_ENCRYPTION => {
let key = rsa::RsaPrivateKey::from_pkcs8_der(&der).ok()?;
Some(Self::Rsa(RsaSigningKey(key)))
}
ID_ED_25519 => {
let key = ed25519_dalek::SigningKey::from_pkcs8_der(&der).ok()?;
Some(Self::Edwards(EdwardsSigningKey::Ed25519(key)))
}
ID_ED_448 => {
let octet_string =
<OctetString as Decode>::from_der(pkcs8.private_key.as_bytes()).ok()?;
let secret_key =
ed448_goldilocks::SecretKey::try_from(octet_string.as_bytes()).ok()?;
let key = ed448_goldilocks::SigningKey::from(secret_key);
Some(Self::Edwards(EdwardsSigningKey::Ed448(key)))
}
_ => None,
}
}
_ => None,
}
}
pub fn verifying_key(&self) -> VerifyingKey {
match &self {
Self::Rsa(key) => VerifyingKey::Rsa(key.verifying_key()),
Self::Elliptic(key) => VerifyingKey::Elliptic(key.verifying_key()),
Self::Edwards(key) => VerifyingKey::Edwards(key.verifying_key()),
}
}
}