Skip to content

Commit 85f0c56

Browse files
authored
ssh-encoding: remove length prefix from [u8; N] encoding (#342)
The type `[u8; N]` maps naturally to SSH's `byte[n]` type, which has no length prefix because `n` is known a priori. In cases where `[u8; N]` is being used to store an SSH `string`, such as Ed25519 public keys, it first needs to be converted to `[u8]` (which maps to `string`) using `as_slice()`
1 parent 4962f11 commit 85f0c56

File tree

5 files changed

+33
-11
lines changed

5 files changed

+33
-11
lines changed

ssh-encoding/src/decode.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,17 @@ impl Decode for usize {
116116
/// > data is sometimes represented as an array of bytes, written
117117
/// > `byte[n]`, where n is the number of bytes in the array.
118118
///
119+
/// Note that unlike `string`, this type is encoded without a length prefix,
120+
/// but instead implicitly obtains its length as `N`.
121+
///
119122
/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
120123
impl<const N: usize> Decode for [u8; N] {
121124
type Error = Error;
122125

123126
fn decode(reader: &mut impl Reader) -> Result<Self> {
124-
reader.read_prefixed(|reader| {
125-
let mut result = [(); N].map(|_| 0);
126-
reader.read(&mut result)?;
127-
Ok(result)
128-
})
127+
let mut result = [0u8; N];
128+
reader.read(&mut result)?;
129+
Ok(result)
129130
}
130131
}
131132

ssh-encoding/src/encode.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,17 @@ impl Encode for [u8] {
158158
/// > data is sometimes represented as an array of bytes, written
159159
/// > `byte[n]`, where n is the number of bytes in the array.
160160
///
161+
/// Note that unlike `string`, this type is encoded without a length prefix,
162+
/// but instead implicitly obtains its length as `N`.
163+
///
161164
/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
162165
impl<const N: usize> Encode for [u8; N] {
163166
fn encoded_len(&self) -> Result<usize, Error> {
164167
self.as_slice().encoded_len()
165168
}
166169

167170
fn encode(&self, writer: &mut impl Writer) -> Result<(), Error> {
168-
self.as_slice().encode(writer)
171+
writer.write(self)
169172
}
170173
}
171174

ssh-encoding/tests/decode.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ fn reject_oversize_usize() {
5252
}
5353

5454
#[test]
55-
fn decode_byte_slice() {
56-
let mut bytes = hex!("000000076578616d706c65").as_slice();
55+
fn decode_byte_array() {
56+
let mut bytes = hex!("6578616d706c65").as_slice();
5757
let ret = <[u8; 7]>::decode(&mut bytes).unwrap();
5858
assert_eq!(&ret, b"example");
5959
}

ssh-encoding/tests/encode.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,16 @@ fn encode_usize() {
4141
}
4242

4343
#[test]
44-
fn encode_byte_slice() {
44+
fn encode_byte_array() {
4545
let mut out = Vec::new();
4646
b"example".encode(&mut out).unwrap();
47+
assert_eq!(out, hex!("6578616d706c65"));
48+
}
49+
50+
#[test]
51+
fn encode_byte_slice() {
52+
let mut out = Vec::new();
53+
b"example".as_slice().encode(&mut out).unwrap();
4754
assert_eq!(out, hex!("000000076578616d706c65"));
4855
}
4956

ssh-key/src/public/ed25519.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,18 @@ use core::fmt;
77
use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
88

99
/// Ed25519 public key.
10-
// TODO(tarcieri): use `ed25519::PublicKey`? (doesn't exist yet)
10+
///
11+
/// Encodings for Ed25519 public keys are described in [RFC8709 § 4]:
12+
///
13+
/// > The "ssh-ed25519" key format has the following encoding:
14+
/// >
15+
/// > **string** "ssh-ed25519"
16+
/// >
17+
/// > **string** key
18+
/// >
19+
/// > Here, 'key' is the 32-octet public key described in RFC8032
20+
///
21+
/// [RFC8709 § 4]: https://datatracker.ietf.org/doc/html/rfc8709#section-4
1122
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
1223
pub struct Ed25519PublicKey(pub [u8; Self::BYTE_SIZE]);
1324

@@ -38,7 +49,7 @@ impl Encode for Ed25519PublicKey {
3849
}
3950

4051
fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
41-
self.0.encode(writer)?;
52+
self.0.as_slice().encode(writer)?;
4253
Ok(())
4354
}
4455
}

0 commit comments

Comments
 (0)