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 {
inner: Arc::new(AccountInner {
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?,
}),
})
@ -315,7 +315,7 @@ impl Account {
let id = account_url.ok_or("failed to get account URL")?;
let credentials = AccountCredentials {
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()),
// 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.
@ -377,7 +377,7 @@ impl AccountInner {
) -> Result<Self, Error> {
Ok(Self {
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) {
(Some(server_url), _) => Client::new(&server_url, http).await?,
(None, Some(urls)) => Client { http, urls },
@ -522,8 +522,8 @@ impl Key {
))
}
fn from_pkcs8_der(pkcs8_der: Vec<u8>) -> Result<Self, Error> {
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &pkcs8_der)?;
fn from_pkcs8_der(pkcs8_der: &[u8]) -> Result<Self, Error> {
let key = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, pkcs8_der)?;
let thumb = BASE64_URL_SAFE_NO_PAD.encode(Jwk::thumb_sha256(&key)?);
Ok(Self {

View File

@ -54,11 +54,51 @@ impl From<&'static str> for Error {
#[derive(Deserialize, Serialize)]
pub struct AccountCredentials {
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) 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
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]