-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ssh-encoding: internal
PemReader
/PemWriter
newtypes
Ala #220, but for PEM, creates newtypes implementing the `Reader` and `Writer` traits for greater future flexibility around these types. Also factors them into internal submodules.
- Loading branch information
Showing
13 changed files
with
177 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
//! PEM encoding support. | ||
|
||
mod decode; | ||
mod encode; | ||
mod reader; | ||
mod writer; | ||
|
||
pub use self::{decode::DecodePem, encode::EncodePem}; | ||
pub use pem_rfc7468::{Error, LineEnding, PemLabel}; | ||
|
||
/// Line width used by the PEM encoding of OpenSSH documents. | ||
const LINE_WIDTH: usize = 70; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
use super::{reader::PemReader, PemLabel}; | ||
use crate::{Decode, Reader}; | ||
|
||
/// Decoding trait for PEM documents. | ||
/// | ||
/// This is an extension trait which is auto-impl'd for types which impl the | ||
/// [`Decode`], [`PemLabel`], and [`Sized`] traits. | ||
pub trait DecodePem: Decode + PemLabel + Sized { | ||
/// Decode the provided PEM-encoded string, interpreting the Base64-encoded | ||
/// body of the document using the [`Decode`] trait. | ||
fn decode_pem(pem: impl AsRef<[u8]>) -> Result<Self, Self::Error>; | ||
} | ||
|
||
impl<T: Decode + PemLabel + Sized> DecodePem for T { | ||
fn decode_pem(pem: impl AsRef<[u8]>) -> Result<Self, Self::Error> { | ||
let mut reader = PemReader::new(pem.as_ref()).map_err(crate::Error::from)?; | ||
Self::validate_pem_label(reader.type_label()).map_err(crate::Error::from)?; | ||
|
||
let ret = Self::decode(&mut reader)?; | ||
Ok(reader.finish(ret)?) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use super::{writer::PemWriter, LineEnding, PemLabel}; | ||
use crate::{Encode, Error}; | ||
use core::str; | ||
|
||
#[cfg(feature = "alloc")] | ||
use {super::LINE_WIDTH, alloc::string::String}; | ||
|
||
/// Encoding trait for PEM documents. | ||
/// | ||
/// This is an extension trait which is auto-impl'd for types which impl the | ||
/// [`Encode`] and [`PemLabel`] traits. | ||
pub trait EncodePem: Encode + PemLabel { | ||
/// Encode this type using the [`Encode`] trait, writing the resulting PEM | ||
/// document into the provided `out` buffer. | ||
fn encode_pem<'o>(&self, line_ending: LineEnding, out: &'o mut [u8]) -> Result<&'o str, Error>; | ||
|
||
/// Encode this type using the [`Encode`] trait, writing the resulting PEM | ||
/// document to a returned [`String`]. | ||
#[cfg(feature = "alloc")] | ||
fn encode_pem_string(&self, line_ending: LineEnding) -> Result<String, Error>; | ||
} | ||
|
||
impl<T: Encode + PemLabel> EncodePem for T { | ||
fn encode_pem<'o>(&self, line_ending: LineEnding, out: &'o mut [u8]) -> Result<&'o str, Error> { | ||
let mut writer = PemWriter::new(Self::PEM_LABEL, line_ending, out).map_err(Error::from)?; | ||
self.encode(&mut writer)?; | ||
|
||
let encoded_len = writer.finish().map_err(Error::from)?; | ||
str::from_utf8(&out[..encoded_len]).map_err(Error::from) | ||
} | ||
|
||
#[cfg(feature = "alloc")] | ||
fn encode_pem_string(&self, line_ending: LineEnding) -> Result<String, Error> { | ||
let encoded_len = pem_rfc7468::encapsulated_len_wrapped( | ||
Self::PEM_LABEL, | ||
LINE_WIDTH, | ||
line_ending, | ||
self.encoded_len()?, | ||
) | ||
.map_err(Error::from)?; | ||
|
||
let mut buf = vec![0u8; encoded_len]; | ||
let actual_len = self.encode_pem(line_ending, &mut buf)?.len(); | ||
buf.truncate(actual_len); | ||
String::from_utf8(buf).map_err(Error::from) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use super::LINE_WIDTH; | ||
use crate::{Reader, Result}; | ||
|
||
/// Inner PEM decoder. | ||
type Inner<'i> = pem_rfc7468::Decoder<'i>; | ||
|
||
/// Constant-time PEM reader. | ||
pub struct PemReader<'i> { | ||
inner: Inner<'i>, | ||
} | ||
|
||
impl<'i> PemReader<'i> { | ||
/// TODO | ||
pub fn new(pem: &'i [u8]) -> Result<Self> { | ||
Ok(Self { | ||
inner: Inner::new_wrapped(pem, LINE_WIDTH)?, | ||
}) | ||
} | ||
|
||
/// Get the PEM type label for the input document. | ||
pub fn type_label(&self) -> &'i str { | ||
self.inner.type_label() | ||
} | ||
} | ||
|
||
impl Reader for PemReader<'_> { | ||
fn read<'o>(&mut self, out: &'o mut [u8]) -> Result<&'o [u8]> { | ||
Ok(self.inner.decode(out)?) | ||
} | ||
|
||
fn remaining_len(&self) -> usize { | ||
self.inner.remaining_len() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use super::{LineEnding, LINE_WIDTH}; | ||
use crate::{Result, Writer}; | ||
|
||
/// Inner PEM encoder. | ||
type Inner<'o> = pem_rfc7468::Encoder<'static, 'o>; | ||
|
||
/// Constant-time PEM writer. | ||
pub struct PemWriter<'o> { | ||
inner: Inner<'o>, | ||
} | ||
|
||
impl<'o> PemWriter<'o> { | ||
/// Create a new PEM writer with the default options which writes output into the provided | ||
/// buffer. | ||
/// | ||
/// Uses 70-character line wrapping to be equivalent to OpenSSH. | ||
pub fn new( | ||
type_label: &'static str, | ||
line_ending: LineEnding, | ||
out: &'o mut [u8], | ||
) -> Result<Self> { | ||
Ok(Self { | ||
inner: Inner::new_wrapped(type_label, LINE_WIDTH, line_ending, out)?, | ||
}) | ||
} | ||
|
||
/// Finish encoding PEM, writing the post-encapsulation boundary. | ||
/// | ||
/// On success, returns the total number of bytes written to the output | ||
/// buffer. | ||
pub fn finish(self) -> Result<usize> { | ||
Ok(self.inner.finish()?) | ||
} | ||
} | ||
|
||
impl<'o> Writer for PemWriter<'o> { | ||
fn write(&mut self, bytes: &[u8]) -> Result<()> { | ||
Ok(self.inner.encode(bytes)?) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.