Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions ssh-key/src/private/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ impl<const SIZE: usize> Decode for EcdsaPrivateKey<SIZE> {

fn decode(reader: &mut impl Reader) -> Result<Self> {
reader.read_prefixed(|reader| {
if reader.remaining_len() == SIZE.checked_add(1).ok_or(encoding::Error::Length)? {
let len = reader.remaining_len();
if len == SIZE.checked_add(1).ok_or(encoding::Error::Length)? {
// Strip leading zero
// TODO(tarcieri): make sure leading zero was necessary
if u8::decode(reader)? != 0 {
Expand All @@ -48,7 +49,17 @@ impl<const SIZE: usize> Decode for EcdsaPrivateKey<SIZE> {
}

let mut bytes = [0u8; SIZE];
reader.read(&mut bytes)?;
if SIZE == 66 {
// https://stackoverflow.com/questions/50002149/why-p-521-public-key-x-y-some-time-is-65-bytes-some-time-is-66-bytes
// although lower keys than 64 are vanishingly possible, but lets stop here
if len > 63 {
reader.read(&mut bytes[..core::cmp::min(len, SIZE)])?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, upon further reflection this seems wrong: the key is supposed to be big endian, so the array should contain leading zeros, not trailing zeros, in the event the input document's key is too short.

It would also be good to add a test that the key is decoded correctly.

I'll try to take care of this in #356

} else {
return Err(encoding::Error::Length.into());
}
} else {
reader.read(&mut bytes)?;
}
Ok(Self { bytes })
})
}
Expand Down
28 changes: 28 additions & 0 deletions ssh-key/tests/private_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,3 +713,31 @@ fn encoding_integration_test(private_key: PrivateKey) {
// Ensure ssh-keygen successfully parsed our public key
assert_eq!(&public_key, private_key.public_key());
}

#[cfg(all(feature = "alloc", feature = "p521"))]
#[test]
fn paramiko_ecdsa_key() {
let key_data = r#"-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBf1mOQFzzGhb+5d4dEzPRbrHrrV+G
ODWR5lOkdlhXpljXb/aPfFGD1RcsrD+WMo510xKHUN4MblVCa//W24EAwbAApVKdO2tte1
72+L2JfNuaJWTU+7QfSWnCDqNFg+XIQSL3UN8nbgOl8Uqd+vF/Z6NqIhyVACLmsm5h3Z3c
blUsh0gAAAEQpYZBIaWGQSEAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
AAAIUEAX9ZjkBc8xoW/uXeHRMz0W6x661fhjg1keZTpHZYV6ZY12/2j3xRg9UXLKw/ljKO
ddMSh1DeDG5VQmv/1tuBAMGwAKVSnTtrbXte9vi9iXzbmiVk1Pu0H0lpwg6jRYPlyEEi91
DfJ24DpfFKnfrxf2ejaiIclQAi5rJuYd2d3G5VLIdIAAAAQQ9lo6iDFKZNqcdQtVY5teUy
2uAhY8gEm4tacIWp4k+PLPuz7l7fLe+V9JgZ6D32zoaVskogcJOXKw5fdF0D7VDUAAAAE3
phY3prb3dzQGwtemFjemtvd3M=
-----END OPENSSH PRIVATE KEY-----"#;

let key = PrivateKey::from_openssh(key_data);
assert!(key.is_ok());
let key = key.unwrap();
assert!(!key.is_encrypted());
assert_eq!(
key.algorithm(),
Algorithm::Ecdsa {
curve: ssh_key::EcdsaCurve::NistP521
}
);
}