Skip to content

Commit

Permalink
ssh-encoding: PEM line width detection (#252)
Browse files Browse the repository at this point in the history
Uses the line width detection support added to `pem-rfc7468` in
RustCrypto/formats#1464 to automatically detect the input line width and
parse PEM documents accordingly, which allows support for a wider range
of SSH keys which don't use the default 70 chars of line wrapping.

Fixes #195
  • Loading branch information
tarcieri authored Jul 28, 2024
1 parent 0782a5c commit afbe00e
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 8 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ssh-encoding/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ rust-version = "1.60"
[dependencies]
base64ct = { version = "1.4", optional = true }
bytes = { version = "1", optional = true, default-features = false }
pem-rfc7468 = { version = "1.0.0-rc.0", optional = true }
pem-rfc7468 = { version = "1.0.0-rc.1", optional = true }
sha2 = { version = "=0.11.0-pre.4", optional = true, default-features = false }

[dev-dependencies]
Expand Down
7 changes: 2 additions & 5 deletions ssh-encoding/src/pem/reader.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use super::LINE_WIDTH;
use crate::{Decode, Error, Reader, Result};

/// Inner PEM decoder.
Expand All @@ -14,11 +13,9 @@ pub struct PemReader<'i> {
}

impl<'i> PemReader<'i> {
/// Create a new PEM reader.
///
/// Uses [`LINE_WIDTH`] as the default line width (i.e. 70 chars).
/// Create a new PEM reader which autodetects the line width of the input.
pub fn new(pem: &'i [u8]) -> Result<Self> {
let inner = Inner::new_wrapped(pem, LINE_WIDTH)?;
let inner = Inner::new_detect_wrap(pem)?;
let remaining_len = inner.remaining_len();

Ok(Self {
Expand Down
8 changes: 8 additions & 0 deletions ssh-key/tests/examples/id_ed25519.64cols
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtz
c2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2XxtSmk9D7RQyf1xUqrYgAA
AJgAIAxdACAMXQAAAAtzc2gtZWQyNTUxOQAAACCzPq7zfqLffKoBDe/eo04kH2Xx
tSmk9D7RQyf1xUqrYgAAAEC2BsIi0QwW2uFscKTUUXNHLsYX4FxlaSDSblbAj7WR
7bM+rvN+ot98qgEN796jTiQfZfG1KaT0PtFDJ/XFSqtiAAAAEHVzZXJAZXhhbXBs
ZS5jb20BAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
11 changes: 11 additions & 0 deletions ssh-key/tests/private_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const OPENSSH_ECDSA_P521_EXAMPLE: &str = include_str!("examples/id_ecdsa_p521");
/// Ed25519 OpenSSH-formatted private key
const OPENSSH_ED25519_EXAMPLE: &str = include_str!("examples/id_ed25519");

/// Ed25519 OpenSSH-formatted private key with 64-column line wrapping
const OPENSSH_ED25519_64COLS_EXAMPLE: &str = include_str!("examples/id_ed25519.64cols");

/// RSA (3072-bit) OpenSSH-formatted public key
#[cfg(feature = "alloc")]
const OPENSSH_RSA_3072_EXAMPLE: &str = include_str!("examples/id_rsa_3072");
Expand Down Expand Up @@ -247,6 +250,14 @@ fn decode_ed25519_openssh() {
assert_eq!(key.comment(), "[email protected]");
}

/// Test alternative PEM line wrappings (64 columns).
#[test]
fn decode_ed25519_openssh_64cols() {
let key = PrivateKey::from_openssh(OPENSSH_ED25519_64COLS_EXAMPLE).unwrap();
let other_key = PrivateKey::from_openssh(OPENSSH_ED25519_EXAMPLE).unwrap();
assert_eq!(key, other_key);
}

#[cfg(feature = "alloc")]
#[test]
fn decode_rsa_3072_openssh() {
Expand Down

0 comments on commit afbe00e

Please sign in to comment.