Only encode/decode key bytes for (de)serialization

This commit is contained in:
Dirkjan Ochtman 2023-08-01 10:59:35 +02:00
parent 3d87755f30
commit 7aa0d46294
2 changed files with 46 additions and 6 deletions

View File

@ -236,7 +236,7 @@ impl Account {
Ok(Self { Ok(Self {
inner: Arc::new(AccountInner { inner: Arc::new(AccountInner {
id, id,
key: Key::from_pkcs8_der(BASE64_URL_SAFE_NO_PAD.decode(key_pkcs8_der)?)?, key: Key::from_pkcs8_der(key_pkcs8_der)?,
client: Client::new(directory_url, http).await?, client: Client::new(directory_url, http).await?,
}), }),
}) })
@ -315,7 +315,7 @@ impl Account {
let id = account_url.ok_or("failed to get account URL")?; let id = account_url.ok_or("failed to get account URL")?;
let credentials = AccountCredentials { let credentials = AccountCredentials {
id: id.clone(), id: id.clone(),
key_pkcs8: BASE64_URL_SAFE_NO_PAD.encode(key_pkcs8.as_ref()), key_pkcs8: key_pkcs8.as_ref().to_vec(),
directory: Some(server_url.to_owned()), directory: Some(server_url.to_owned()),
// We support deserializing URLs for compatibility with versions pre 0.4, // We support deserializing URLs for compatibility with versions pre 0.4,
// but we prefer to get fresh URLs from the `server_url` for newer credentials. // but we prefer to get fresh URLs from the `server_url` for newer credentials.
@ -377,7 +377,7 @@ impl AccountInner {
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(Self { Ok(Self {
id: credentials.id, id: credentials.id,
key: Key::from_pkcs8_der(BASE64_URL_SAFE_NO_PAD.decode(&credentials.key_pkcs8)?)?, key: Key::from_pkcs8_der(credentials.key_pkcs8.as_ref())?,
client: match (credentials.directory, credentials.urls) { client: match (credentials.directory, credentials.urls) {
(Some(server_url), _) => Client::new(&server_url, http).await?, (Some(server_url), _) => Client::new(&server_url, http).await?,
(None, Some(urls)) => Client { http, urls }, (None, Some(urls)) => Client { http, urls },
@ -522,8 +522,8 @@ impl Key {
)) ))
} }
fn from_pkcs8_der(pkcs8_der: Vec<u8>) -> Result<Self, Error> { fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self, Error> {
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &pkcs8_der)?; let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8_der)?;
let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?); let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?);
Ok(Self { Ok(Self {

View File

@ -54,11 +54,51 @@ impl From<&'static str> for Error {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct AccountCredentials { pub struct AccountCredentials {
pub(crate) id: String, pub(crate) id: String,
pub(crate) key_pkcs8: String, /// Stored in DER, serialized as base64
#[serde(with = "pkcs8_serde")]
pub(crate) key_pkcs8: Vec<u8>,
pub(crate) directory: Option<String>, pub(crate) directory: Option<String>,
pub(crate) urls: Option<DirectoryUrls>, pub(crate) urls: Option<DirectoryUrls>,
} }
mod pkcs8_serde {
use std::fmt;
use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
use serde::{de, Deserializer, Serializer};
pub(crate) fn serialize<S>(key_pkcs8: &[u8], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let encoded = BASE64_URL_SAFE_NO_PAD.encode(key_pkcs8.as_ref());
serializer.serialize_str(&encoded)
}
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Vec<u8>, D::Error> {
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Vec<u8>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a base64-encoded PKCS#8 private key")
}
fn visit_str<E>(self, v: &str) -> Result<Vec<u8>, E>
where
E: de::Error,
{
BASE64_URL_SAFE_NO_PAD.decode(v).map_err(de::Error::custom)
}
}
deserializer.deserialize_str(Visitor)
}
}
/// An RFC 7807 problem document as returned by the ACME server /// An RFC 7807 problem document as returned by the ACME server
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]