From 4d6a94d67f4482f401bf00d55fed365aaff8fb18 Mon Sep 17 00:00:00 2001 From: "Aode (lion)" Date: Thu, 18 Nov 2021 16:08:30 -0600 Subject: [PATCH] openssl: impl serde --- apub-openssl/Cargo.toml | 4 +++ apub-openssl/src/lib.rs | 60 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/apub-openssl/Cargo.toml b/apub-openssl/Cargo.toml index 75061ab..d6be5e2 100644 --- a/apub-openssl/Cargo.toml +++ b/apub-openssl/Cargo.toml @@ -8,3 +8,7 @@ edition = "2021" [dependencies] apub-core = { version = "0.1.0", path = "../apub-core/" } openssl = "0.10.36" +serde = { version = "1", features = ["derive"] } + +[dev-dependencies] +serde_json = "1" diff --git a/apub-openssl/src/lib.rs b/apub-openssl/src/lib.rs index bf9af02..51d8364 100644 --- a/apub-openssl/src/lib.rs +++ b/apub-openssl/src/lib.rs @@ -16,8 +16,10 @@ pub struct OpenSslSigner { private_key: PKey, } +#[derive(Clone, serde::Deserialize, serde::Serialize)] pub struct OpenSsl { key_id: String, + #[serde(with = "openssl_private_key")] private_key: PKey, } @@ -101,3 +103,61 @@ impl Debug for OpenSsl { .finish() } } + +mod openssl_private_key { + use openssl::pkey::{PKey, Private}; + use serde::{ + de::{Deserialize, Deserializer}, + ser::{Serialize, Serializer}, + }; + + pub(super) fn serialize( + private_key: &PKey, + serializer: S, + ) -> Result { + use serde::ser::Error; + + let der = private_key.private_key_to_der().map_err(S::Error::custom)?; + let der_string = openssl::base64::encode_block(&der); + + String::serialize(&der_string, serializer) + } + + pub(super) fn deserialize<'de, D: Deserializer<'de>>( + deserializer: D, + ) -> Result, D::Error> { + use serde::de::Error; + + let der_string = String::deserialize(deserializer)?; + let der = openssl::base64::decode_block(&der_string).map_err(D::Error::custom)?; + + PKey::::private_key_from_der(&der).map_err(D::Error::custom) + } +} + +#[cfg(test)] +pub mod tests { + use super::OpenSsl; + use apub_core::signature::{Sign, SignFactory}; + use openssl::{pkey::PKey, rsa::Rsa}; + + #[test] + fn round_trip() { + let private_key = PKey::from_rsa(Rsa::generate(1024).unwrap()).unwrap(); + let crypto = OpenSsl::new("key-id".into(), private_key); + let signer = crypto.signer(); + + let first_sign = signer.sign("hello").unwrap(); + + let s = serde_json::to_string(&crypto).unwrap(); + let crypto2: OpenSsl = serde_json::from_str(&s).unwrap(); + let signer2 = crypto2.signer(); + + let second_sign = signer2.sign("hello").unwrap(); + + let s2 = serde_json::to_string(&crypto2).unwrap(); + + assert_eq!(s, s2); + assert_eq!(first_sign, second_sign); + } +}