From dbc455e69939dd6ff0e0fa1d8a4b4646ecc19d29 Mon Sep 17 00:00:00 2001 From: Cristiano Prato Date: Tue, 5 Aug 2025 15:22:49 +0200 Subject: [PATCH 1/2] add support for parsing X509 certs from DER fix: #2343 and #2344 Adds `Certificate::from_der` and `Identity::from_der` constructors to allow creation of Certificate and Identity from DER-encoded data. --- tonic/src/transport/tls.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tonic/src/transport/tls.rs b/tonic/src/transport/tls.rs index c2b7ef23f..fd4d92c64 100644 --- a/tonic/src/transport/tls.rs +++ b/tonic/src/transport/tls.rs @@ -1,3 +1,5 @@ +use base64::Engine as _; + /// Represents a X509 certificate. #[derive(Debug, Clone)] pub struct Certificate { @@ -20,6 +22,15 @@ impl Certificate { Self { pem } } + /// Parse a DER encoded X509 Certificate. + /// + /// The provided DER should include exactly one DER encoded certificate. + pub fn from_der(der: impl AsRef<[u8]>) -> Self { + let der = der.as_ref(); + let pem = der2pem(der); + Self { pem: pem.into_bytes() } + } + /// Get a immutable reference to underlying certificate pub fn get_ref(&self) -> &[u8] { self.pem.as_slice() @@ -57,4 +68,21 @@ impl Identity { let key = key.as_ref().into(); Self { cert, key } } + + /// Parse a DER encoded certificate and private key. + /// + /// The provided cert must contain exactly one DER encoded certificate. + pub fn from_der(cert: impl AsRef<[u8]>, key: impl AsRef<[u8]>) -> Self { + let cert = Certificate::from_der(cert); + let key = key.as_ref().into(); + Self { cert, key } + } } + +fn der2pem(der: &[u8]) -> String { + const RFC7468_HEADER: &str = "-----BEGIN CERTIFICATE-----"; + const RFC7468_FOOTER: &str = "-----END CERTIFICATE-----"; + let pem = crate::util::base64::STANDARD_NO_PAD.encode(der); + format!("{RFC7468_HEADER}\n{pem}\n{RFC7468_FOOTER}\n") +} + From 874327acc5459541cdff19747b2ce761530c6411 Mon Sep 17 00:00:00 2001 From: Cristiano Prato Date: Tue, 5 Aug 2025 15:54:47 +0200 Subject: [PATCH 2/2] fix formatting --- tonic/src/transport/tls.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tonic/src/transport/tls.rs b/tonic/src/transport/tls.rs index fd4d92c64..aa273a501 100644 --- a/tonic/src/transport/tls.rs +++ b/tonic/src/transport/tls.rs @@ -28,7 +28,9 @@ impl Certificate { pub fn from_der(der: impl AsRef<[u8]>) -> Self { let der = der.as_ref(); let pem = der2pem(der); - Self { pem: pem.into_bytes() } + Self { + pem: pem.into_bytes(), + } } /// Get a immutable reference to underlying certificate @@ -70,7 +72,7 @@ impl Identity { } /// Parse a DER encoded certificate and private key. - /// + /// /// The provided cert must contain exactly one DER encoded certificate. pub fn from_der(cert: impl AsRef<[u8]>, key: impl AsRef<[u8]>) -> Self { let cert = Certificate::from_der(cert); @@ -85,4 +87,3 @@ fn der2pem(der: &[u8]) -> String { let pem = crate::util::base64::STANDARD_NO_PAD.encode(der); format!("{RFC7468_HEADER}\n{pem}\n{RFC7468_FOOTER}\n") } -