#[cfg(feature = "openssl")]
use crate::ecdsa::{EcdsaPrivateKey, EcdsaPublicKey};
#[cfg(feature = "openssl")]
use crate::eddsa::{Ed25519PrivateKey, Ed25519PublicKey};
#[cfg(feature = "openssl")]
use crate::rsa::RsaPrivateKey;
#[cfg(any(feature = "openssl", feature = "aws-lc"))]
use crate::rsa::RsaPublicKey;
#[cfg(feature = "openssl")]
use crate::Error;
use crate::{jwk::Jwk, PrivateKeyToJwk, PublicKeyToJwk, Result, SigningKey, VerificationKey};
#[non_exhaustive]
#[derive(Debug)]
pub enum SomePrivateKey {
#[cfg(feature = "openssl")]
Ed25519(Ed25519PrivateKey),
#[cfg(feature = "openssl")]
Ecdsa(EcdsaPrivateKey),
#[cfg(feature = "openssl")]
Rsa(RsaPrivateKey),
}
#[non_exhaustive]
#[derive(Debug)]
pub enum SomePublicKey {
#[cfg(feature = "openssl")]
Ed25519(Ed25519PublicKey),
#[cfg(feature = "openssl")]
Ecdsa(EcdsaPublicKey),
#[cfg(any(feature = "openssl", feature = "aws-lc"))]
Rsa(RsaPublicKey),
}
#[cfg(feature = "openssl")]
impl From<Ed25519PrivateKey> for SomePrivateKey {
#[inline]
fn from(k: Ed25519PrivateKey) -> SomePrivateKey {
SomePrivateKey::Ed25519(k)
}
}
#[cfg(feature = "openssl")]
impl From<EcdsaPrivateKey> for SomePrivateKey {
#[inline]
fn from(k: EcdsaPrivateKey) -> SomePrivateKey {
SomePrivateKey::Ecdsa(k)
}
}
#[cfg(feature = "openssl")]
impl From<RsaPrivateKey> for SomePrivateKey {
#[inline]
fn from(k: RsaPrivateKey) -> SomePrivateKey {
SomePrivateKey::Rsa(k)
}
}
#[cfg(feature = "openssl")]
impl From<Ed25519PublicKey> for SomePublicKey {
#[inline]
fn from(k: Ed25519PublicKey) -> SomePublicKey {
SomePublicKey::Ed25519(k)
}
}
#[cfg(feature = "openssl")]
impl From<EcdsaPublicKey> for SomePublicKey {
#[inline]
fn from(k: EcdsaPublicKey) -> SomePublicKey {
SomePublicKey::Ecdsa(k)
}
}
#[cfg(any(feature = "openssl", feature = "aws-lc"))]
impl From<RsaPublicKey> for SomePublicKey {
#[inline]
fn from(k: RsaPublicKey) -> SomePublicKey {
SomePublicKey::Rsa(k)
}
}
#[cfg(feature = "openssl")]
impl SomePrivateKey {
pub fn from_pem(pem: &[u8], if_rsa_algorithm: crate::rsa::RsaAlgorithm) -> Result<Self> {
use openssl::pkey::{Id, PKey};
let pk = PKey::private_key_from_pem(pem)?;
match pk.id() {
Id::RSA => Ok(Self::Rsa(RsaPrivateKey::from_pkey(pk, if_rsa_algorithm)?)),
Id::EC => {
let k = EcdsaPrivateKey::from_pkey(pk)?;
Ok(Self::Ecdsa(k))
}
Id::ED25519 => {
let k = Ed25519PrivateKey::from_pkey(pk)?;
Ok(Self::Ed25519(k))
}
_ => Err(Error::UnsupportedOrInvalidKey),
}
}
pub fn private_key_to_pem_pkcs8(&self) -> Result<String> {
match self {
SomePrivateKey::Ed25519(ed) => ed.private_key_to_pem_pkcs8(),
SomePrivateKey::Ecdsa(ec) => ec.private_key_to_pem_pkcs8(),
SomePrivateKey::Rsa(rsa) => rsa.private_key_to_pem_pkcs8(),
}
}
pub fn public_key_to_pem(&self) -> Result<String> {
match self {
SomePrivateKey::Ed25519(ed) => ed.public_key_to_pem(),
SomePrivateKey::Ecdsa(ec) => ec.public_key_to_pem(),
SomePrivateKey::Rsa(rsa) => rsa.public_key_to_pem(),
}
}
}
#[cfg(feature = "openssl")]
impl SomePublicKey {
pub fn from_pem(pem: &[u8]) -> Result<Self> {
use openssl::pkey::{Id, PKey};
let pk = PKey::public_key_from_pem(pem)?;
match pk.id() {
Id::RSA => Ok(Self::Rsa(RsaPublicKey::from_pkey(pk, None)?)),
Id::EC => {
let k = EcdsaPublicKey::from_pkey(pk)?;
Ok(Self::Ecdsa(k))
}
Id::ED25519 => {
let k = Ed25519PublicKey::from_pkey(pk)?;
Ok(Self::Ed25519(k))
}
_ => Err(Error::UnsupportedOrInvalidKey),
}
}
pub fn to_pem(&self) -> Result<String> {
match self {
SomePublicKey::Ed25519(ed) => ed.to_pem(),
SomePublicKey::Ecdsa(ec) => ec.to_pem(),
SomePublicKey::Rsa(rsa) => rsa.to_pem(),
}
}
}
impl PublicKeyToJwk for SomePrivateKey {
fn public_key_to_jwk(&self) -> Result<Jwk> {
match self {
#[cfg(feature = "openssl")]
SomePrivateKey::Ed25519(ed) => ed.public_key_to_jwk(),
#[cfg(feature = "openssl")]
SomePrivateKey::Ecdsa(ec) => ec.public_key_to_jwk(),
#[cfg(feature = "openssl")]
SomePrivateKey::Rsa(rsa) => rsa.public_key_to_jwk(),
#[cfg(not(feature = "openssl"))]
_ => unreachable!(),
}
}
}
impl PrivateKeyToJwk for SomePrivateKey {
fn private_key_to_jwk(&self) -> Result<Jwk> {
match self {
#[cfg(feature = "openssl")]
SomePrivateKey::Ed25519(ed) => ed.private_key_to_jwk(),
#[cfg(feature = "openssl")]
SomePrivateKey::Ecdsa(ec) => ec.private_key_to_jwk(),
#[cfg(feature = "openssl")]
SomePrivateKey::Rsa(rsa) => rsa.private_key_to_jwk(),
#[cfg(not(feature = "openssl"))]
_ => unreachable!(),
}
}
}
impl SigningKey for SomePrivateKey {
fn alg(&self) -> &'static str {
match self {
#[cfg(feature = "openssl")]
SomePrivateKey::Ed25519(ed) => ed.alg(),
#[cfg(feature = "openssl")]
SomePrivateKey::Ecdsa(ec) => ec.alg(),
#[cfg(feature = "openssl")]
SomePrivateKey::Rsa(rsa) => rsa.alg(),
#[cfg(not(feature = "openssl"))]
_ => unreachable!(),
}
}
fn sign(&self, _v: &[u8]) -> crate::Result<smallvec::SmallVec<[u8; 64]>> {
match self {
#[cfg(feature = "openssl")]
SomePrivateKey::Ed25519(ed) => ed.sign(_v),
#[cfg(feature = "openssl")]
SomePrivateKey::Ecdsa(ec) => ec.sign(_v),
#[cfg(feature = "openssl")]
SomePrivateKey::Rsa(rsa) => rsa.sign(_v),
#[cfg(not(feature = "openssl"))]
_ => unreachable!(),
}
}
}
impl VerificationKey for SomePrivateKey {
fn verify(&self, _v: &[u8], _sig: &[u8], _alg: &str) -> crate::Result<()> {
match self {
#[cfg(feature = "openssl")]
SomePrivateKey::Ed25519(ed) => ed.verify(_v, _sig, _alg),
#[cfg(feature = "openssl")]
SomePrivateKey::Ecdsa(ec) => ec.verify(_v, _sig, _alg),
#[cfg(feature = "openssl")]
SomePrivateKey::Rsa(rsa) => rsa.verify(_v, _sig, _alg),
#[cfg(not(feature = "openssl"))]
_ => unreachable!(),
}
}
}
impl VerificationKey for SomePublicKey {
fn verify(&self, _v: &[u8], _sig: &[u8], _alg: &str) -> crate::Result<()> {
match self {
#[cfg(feature = "openssl")]
SomePublicKey::Ed25519(ed) => ed.verify(_v, _sig, _alg),
#[cfg(feature = "openssl")]
SomePublicKey::Ecdsa(ec) => ec.verify(_v, _sig, _alg),
#[cfg(any(feature = "openssl", feature = "aws-lc"))]
SomePublicKey::Rsa(rsa) => rsa.verify(_v, _sig, _alg),
#[cfg(not(any(feature = "openssl", feature = "aws-lc")))]
_ => unreachable!(),
}
}
}
impl PublicKeyToJwk for SomePublicKey {
fn public_key_to_jwk(&self) -> Result<Jwk> {
match self {
#[cfg(feature = "openssl")]
SomePublicKey::Ed25519(ed) => ed.public_key_to_jwk(),
#[cfg(feature = "openssl")]
SomePublicKey::Ecdsa(ec) => ec.public_key_to_jwk(),
#[cfg(any(feature = "openssl", feature = "aws-lc"))]
SomePublicKey::Rsa(rsa) => rsa.public_key_to_jwk(),
#[cfg(not(any(feature = "openssl", feature = "aws-lc")))]
_ => unreachable!(),
}
}
}