use std::fmt;
use failure::Error;
use serde::ser::{Serialize, Serializer};
use serde::de::{self, Deserialize, Deserializer, Visitor};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub enum Algorithm {
RSA_PKCS1_SHA1 = 0x01,
RSA_PKCS1_SHA256 = 0x02,
RSA_PKCS1_SHA384 = 0x03,
RSA_PKCS1_SHA512 = 0x04,
RSA_PSS_SHA1 = 0x05,
RSA_PSS_SHA256 = 0x06,
RSA_PSS_SHA384 = 0x07,
RSA_PSS_SHA512 = 0x08,
RSA2048 = 0x09,
RSA3072 = 0x0a,
RSA4096 = 0x0b,
EC_P256 = 0x0c,
EC_P384 = 0x0d,
EC_P521 = 0x0e,
EC_K256 = 0x0f,
EC_BP256 = 0x10,
EC_BP384 = 0x11,
EC_BP512 = 0x12,
HMAC_SHA1 = 0x13,
HMAC_SHA256 = 0x14,
HMAC_SHA384 = 0x15,
HMAC_SHA512 = 0x16,
EC_ECDSA_SHA1 = 0x17,
EC_ECDH = 0x18,
RSA_OAEP_SHA1 = 0x19,
RSA_OAEP_SHA256 = 0x1a,
RSA_OAEP_SHA384 = 0x1b,
RSA_OAEP_SHA512 = 0x1c,
AES128_CCM_WRAP = 0x1d,
OPAQUE_DATA = 0x1e,
OPAQUE_X509_CERT = 0x1f,
MGF1_SHA1 = 0x20,
MGF1_SHA256 = 0x21,
MGF1_SHA384 = 0x22,
MGF1_SHA512 = 0x23,
TEMPL_SSH = 0x24,
YUBICO_OTP_AES128 = 0x25,
YUBICO_AES_AUTH = 0x26,
YUBICO_OTP_AES192 = 0x27,
YUBICO_OTP_AES256 = 0x28,
AES192_CCM_WRAP = 0x29,
AES256_CCM_WRAP = 0x2a,
EC_ECDSA_SHA256 = 0x2b,
EC_ECDSA_SHA384 = 0x2c,
EC_ECDSA_SHA512 = 0x2d,
EC_ED25519 = 0x2e,
EC_P224 = 0x2f,
}
impl Algorithm {
pub fn from_u8(byte: u8) -> Result<Self, Error> {
Ok(match byte {
0x01 => Algorithm::RSA_PKCS1_SHA1,
0x02 => Algorithm::RSA_PKCS1_SHA256,
0x03 => Algorithm::RSA_PKCS1_SHA384,
0x04 => Algorithm::RSA_PKCS1_SHA512,
0x05 => Algorithm::RSA_PSS_SHA1,
0x06 => Algorithm::RSA_PSS_SHA256,
0x07 => Algorithm::RSA_PSS_SHA384,
0x08 => Algorithm::RSA_PSS_SHA512,
0x09 => Algorithm::RSA2048,
0x0a => Algorithm::RSA3072,
0x0b => Algorithm::RSA4096,
0x0c => Algorithm::EC_P256,
0x0d => Algorithm::EC_P384,
0x0e => Algorithm::EC_P521,
0x0f => Algorithm::EC_K256,
0x10 => Algorithm::EC_BP256,
0x11 => Algorithm::EC_BP384,
0x12 => Algorithm::EC_BP512,
0x13 => Algorithm::HMAC_SHA1,
0x14 => Algorithm::HMAC_SHA256,
0x15 => Algorithm::HMAC_SHA384,
0x16 => Algorithm::HMAC_SHA512,
0x17 => Algorithm::EC_ECDSA_SHA1,
0x18 => Algorithm::EC_ECDH,
0x19 => Algorithm::RSA_OAEP_SHA1,
0x1a => Algorithm::RSA_OAEP_SHA256,
0x1b => Algorithm::RSA_OAEP_SHA384,
0x1c => Algorithm::RSA_OAEP_SHA512,
0x1d => Algorithm::AES128_CCM_WRAP,
0x1e => Algorithm::OPAQUE_DATA,
0x1f => Algorithm::OPAQUE_X509_CERT,
0x20 => Algorithm::MGF1_SHA1,
0x21 => Algorithm::MGF1_SHA256,
0x22 => Algorithm::MGF1_SHA384,
0x23 => Algorithm::MGF1_SHA512,
0x24 => Algorithm::TEMPL_SSH,
0x25 => Algorithm::YUBICO_OTP_AES128,
0x26 => Algorithm::YUBICO_AES_AUTH,
0x27 => Algorithm::YUBICO_OTP_AES192,
0x28 => Algorithm::YUBICO_OTP_AES256,
0x29 => Algorithm::AES192_CCM_WRAP,
0x2a => Algorithm::AES256_CCM_WRAP,
0x2b => Algorithm::EC_ECDSA_SHA256,
0x2c => Algorithm::EC_ECDSA_SHA384,
0x2d => Algorithm::EC_ECDSA_SHA512,
0x2e => Algorithm::EC_ED25519,
0x2f => Algorithm::EC_P224,
_ => bail!("invalid algorithm: {:?}", byte),
})
}
pub fn to_u8(&self) -> u8 {
*self as u8
}
}
impl Serialize for Algorithm {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u8(self.to_u8())
}
}
impl<'de> Deserialize<'de> for Algorithm {
fn deserialize<D>(deserializer: D) -> Result<Algorithm, D::Error>
where
D: Deserializer<'de>,
{
struct AlgorithmVisitor;
impl<'de> Visitor<'de> for AlgorithmVisitor {
type Value = Algorithm;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an unsigned byte between 0x01 and 0x07")
}
fn visit_u8<E>(self, value: u8) -> Result<Algorithm, E>
where
E: de::Error,
{
Algorithm::from_u8(value).or_else(|e| Err(E::custom(format!("{}", e))))
}
}
deserializer.deserialize_u8(AlgorithmVisitor)
}
}