Skip to content

Commit 5a1ac38

Browse files
authored
ssh-key: Consistency in Key Read + Write (#383)
- Replace Generics with `impl` for consistency - Make File + Path functions use `Read` + `Write` implementations to unify behavior - Unified Unix + Non-Unix behavior for `PrivateKey::write_openssh_file`
1 parent ee835e3 commit 5a1ac38

2 files changed

Lines changed: 24 additions & 33 deletions

File tree

ssh-key/src/private.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ use rand_core::TryCryptoRng;
161161
use rand_core::CryptoRng;
162162

163163
#[cfg(feature = "std")]
164-
use std::{fs, path::Path};
164+
use std::{fs::File, path::Path};
165165

166166
#[cfg(feature = "std")]
167167
use std::io::{self, Read, Write};
@@ -344,50 +344,44 @@ impl PrivateKey {
344344
SshSig::sign(self, namespace, hash_alg, msg)
345345
}
346346

347-
/// Read private key from an OpenSSH-formatted PEM file.
347+
/// Read private key from an OpenSSH-formatted PEM source.
348348
#[cfg(feature = "std")]
349-
pub fn read_openssh<R: Read>(reader: &mut R) -> Result<Self> {
349+
pub fn read_openssh(reader: &mut impl Read) -> Result<Self> {
350350
let pem = Zeroizing::new(io::read_to_string(reader)?);
351351
Self::from_openssh(&*pem)
352352
}
353353

354354
/// Read private key from an OpenSSH-formatted PEM file.
355355
#[cfg(feature = "std")]
356-
pub fn read_openssh_file<P: AsRef<Path>>(path: P) -> Result<Self> {
356+
pub fn read_openssh_file(path: impl AsRef<Path>) -> Result<Self> {
357357
// TODO(tarcieri): verify file permissions match `UNIX_FILE_PERMISSIONS`
358-
let pem = Zeroizing::new(fs::read_to_string(path)?);
359-
Self::from_openssh(&*pem)
358+
let mut file = File::open(path)?;
359+
Self::read_openssh(&mut file)
360360
}
361361

362362
/// Write private key as an OpenSSH-formatted PEM file.
363363
#[cfg(feature = "std")]
364-
pub fn write_openssh<W: Write>(&self, writer: &mut W, line_ending: LineEnding) -> Result<()> {
364+
pub fn write_openssh(&self, writer: &mut impl Write, line_ending: LineEnding) -> Result<()> {
365365
let pem = self.to_openssh(line_ending)?;
366366
writer.write_all(pem.as_bytes())?;
367367
Ok(())
368368
}
369369

370370
/// Write private key as an OpenSSH-formatted PEM file.
371371
#[cfg(feature = "std")]
372-
pub fn write_openssh_file<P: AsRef<Path>>(
372+
pub fn write_openssh_file(
373373
&self,
374-
path: P,
374+
path: impl AsRef<Path>,
375375
line_ending: LineEnding,
376376
) -> Result<()> {
377-
let pem = self.to_openssh(line_ending)?;
377+
let mut options = File::options();
378378

379-
#[cfg(not(unix))]
380-
fs::write(path, pem.as_bytes())?;
381379
#[cfg(unix)]
382-
fs::OpenOptions::new()
383-
.create(true)
384-
.write(true)
385-
.truncate(true)
386-
.mode(UNIX_FILE_PERMISSIONS)
387-
.open(path)
388-
.and_then(|mut file| file.write_all(pem.as_bytes()))?;
380+
options.mode(UNIX_FILE_PERMISSIONS);
389381

390-
Ok(())
382+
let mut file = options.write(true).create(true).truncate(true).open(path)?;
383+
384+
self.write_openssh(&mut file, line_ending)
391385
}
392386

393387
/// Attempt to decrypt an encrypted private key using the provided

ssh-key/src/public.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use {
4848
use serde::{Deserialize, Serialize, de, ser};
4949

5050
#[cfg(feature = "std")]
51-
use std::{fs, path::Path};
51+
use std::{fs::File, path::Path};
5252

5353
#[cfg(feature = "std")]
5454
use std::io::{self, Read, Write};
@@ -243,23 +243,23 @@ impl PublicKey {
243243
signature.verify(msg)
244244
}
245245

246-
/// Read public key from an OpenSSH-formatted file.
246+
/// Read public key from an OpenSSH-formatted source.
247247
#[cfg(feature = "std")]
248-
pub fn read_openssh<R: Read>(reader: &mut R) -> Result<Self> {
248+
pub fn read_openssh(reader: &mut impl Read) -> Result<Self> {
249249
let input = io::read_to_string(reader)?;
250250
Self::from_openssh(&input)
251251
}
252252

253253
/// Read public key from an OpenSSH-formatted file.
254254
#[cfg(feature = "std")]
255-
pub fn read_openssh_file<P: AsRef<Path>>(path: P) -> Result<Self> {
256-
let input = fs::read_to_string(path)?;
257-
Self::from_openssh(&input)
255+
pub fn read_openssh_file(path: impl AsRef<Path>) -> Result<Self> {
256+
let mut file = File::open(path)?;
257+
Self::read_openssh(&mut file)
258258
}
259259

260260
/// Write public key as an OpenSSH-formatted file.
261261
#[cfg(feature = "std")]
262-
pub fn write_openssh<W: Write>(&self, writer: &mut W) -> Result<()> {
262+
pub fn write_openssh(&self, writer: &mut impl Write) -> Result<()> {
263263
let mut encoded = self.to_openssh()?;
264264
encoded.push('\n'); // TODO(tarcieri): OS-specific line endings?
265265

@@ -269,12 +269,9 @@ impl PublicKey {
269269

270270
/// Write public key as an OpenSSH-formatted file.
271271
#[cfg(feature = "std")]
272-
pub fn write_openssh_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
273-
let mut encoded = self.to_openssh()?;
274-
encoded.push('\n'); // TODO(tarcieri): OS-specific line endings?
275-
276-
fs::write(path, encoded.as_bytes())?;
277-
Ok(())
272+
pub fn write_openssh_file(&self, path: impl AsRef<Path>) -> Result<()> {
273+
let mut file = File::create(path)?;
274+
self.write_openssh(&mut file)
278275
}
279276

280277
/// Get the digital signature [`Algorithm`] used by this key.

0 commit comments

Comments
 (0)