Skip to content

Commit 9764c7a

Browse files
authored
ssh-key: support for reading PPK format private keys (#324)
1 parent 028e40f commit 9764c7a

18 files changed

+1015
-19
lines changed

.github/workflows/ssh-key.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
toolchain: ${{ matrix.rust }}
7373
target: ${{ matrix.target }}
7474
- uses: RustCrypto/actions/cargo-hack-install@master
75-
- run: cargo hack build --target ${{ matrix.target }} --feature-powerset --exclude-features default,dsa,ed25519,getrandom,p256,p384,p521,rsa,tdes,std --release
75+
- run: cargo hack build --target ${{ matrix.target }} --feature-powerset --exclude-features default,dsa,ed25519,getrandom,p256,p384,p521,rsa,tdes,std,ppk --release
7676
- run: cargo build --target ${{ matrix.target }} --no-default-features --features alloc,crypto,dsa,encryption,tdes --release
7777

7878
test:
@@ -88,7 +88,7 @@ jobs:
8888
with:
8989
toolchain: ${{ matrix.rust }}
9090
- uses: RustCrypto/actions/cargo-hack-install@master
91-
- run: cargo hack test --feature-powerset --exclude-features default,dsa,ed25519,getrandom,p256,p384,p521,rsa,tdes,std --release
91+
- run: cargo hack test --feature-powerset --exclude-features default,dsa,ed25519,getrandom,p256,p384,p521,rsa,tdes,std,ppk --release
9292
- run: cargo test --release
9393
- run: cargo test --release --features getrandom
9494
- run: cargo test --release --features std

Cargo.lock

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ssh-key/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ subtle = { version = "2", default-features = false }
2626
zeroize = { version = "1", default-features = false }
2727

2828
# optional dependencies
29+
argon2 = { version = "=0.6.0-pre.1", optional = true, default-features = false, features = ["alloc"] }
2930
bcrypt-pbkdf = { version = "=0.11.0-pre.1", optional = true, default-features = false, features = ["alloc"] }
3031
bigint = { package = "num-bigint-dig", version = "0.8", optional = true, default-features = false }
3132
dsa = { version = "=0.7.0-pre.1", optional = true, default-features = false }
3233
ed25519-dalek = { version = "=2.2.0-pre", optional = true, default-features = false }
34+
hex = { version = "0.4", optional = true, default-features = false, features = ["alloc"] }
35+
hmac = { version = "=0.13.0-pre.4", optional = true }
3336
home = { version = "0.5", optional = true }
3437
p256 = { version = "=0.14.0-pre.1", optional = true, default-features = false, features = ["ecdsa"] }
3538
p384 = { version = "=0.14.0-pre.1", optional = true, default-features = false, features = ["ecdsa"] }
@@ -79,6 +82,7 @@ getrandom = ["rand_core/getrandom"]
7982
p256 = ["dep:p256", "ecdsa"]
8083
p384 = ["dep:p384", "ecdsa"]
8184
p521 = ["dep:p521", "ecdsa"]
85+
ppk = ["dep:hex", "alloc", "cipher/aes-cbc", "dep:hmac", "dep:argon2", "dep:sha1"]
8286
rsa = ["dep:bigint", "dep:rsa", "alloc", "rand_core"]
8387
tdes = ["cipher/tdes", "encryption"]
8488

ssh-key/src/error.rs

+9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ use core::fmt;
66
#[cfg(feature = "alloc")]
77
use crate::certificate;
88

9+
#[cfg(feature = "ppk")]
10+
use crate::ppk::PpkParseError;
11+
912
/// Result type with `ssh-key`'s [`Error`] as the error type.
1013
pub type Result<T> = core::result::Result<T, Error>;
1114

@@ -66,6 +69,10 @@ pub enum Error {
6669
/// Public key is incorrect.
6770
PublicKey,
6871

72+
/// PuTTY format parsing errors.
73+
#[cfg(feature = "ppk")]
74+
Ppk(PpkParseError),
75+
6976
/// Invalid timestamp (e.g. in a certificate)
7077
Time,
7178

@@ -104,6 +111,8 @@ impl fmt::Display for Error {
104111
#[cfg(feature = "std")]
105112
Error::Io(err) => write!(f, "I/O error: {}", std::io::Error::from(*err)),
106113
Error::Namespace => write!(f, "namespace invalid"),
114+
#[cfg(feature = "ppk")]
115+
Error::Ppk(err) => write!(f, "PPK parsing error: {err}"),
107116
Error::PublicKey => write!(f, "public key is incorrect"),
108117
Error::Time => write!(f, "invalid time"),
109118
Error::TrailingData { remaining } => write!(

ssh-key/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ mod kdf;
160160
mod dot_ssh;
161161
#[cfg(feature = "alloc")]
162162
mod mpint;
163+
#[cfg(feature = "ppk")]
164+
mod ppk;
163165
#[cfg(feature = "alloc")]
164166
mod signature;
165167
#[cfg(feature = "alloc")]

0 commit comments

Comments
 (0)