Skip to content

Commit 43edc32

Browse files
committed
fixed #172 - update ed25519-dalek
1 parent d5cc506 commit 43edc32

File tree

8 files changed

+70
-78
lines changed

8 files changed

+70
-78
lines changed

russh-keys/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ block-padding = { version = "0.3", features = ["std"] }
3838
byteorder = "1.4"
3939
data-encoding = "2.3"
4040
dirs = "5.0"
41-
ed25519-dalek = "1.0"
41+
ed25519-dalek = { version= "2.0", features = ["rand_core"] }
4242
futures = "0.3"
4343
hmac = "0.12"
4444
inout = { version = "0.1", features = ["std"] }
@@ -49,7 +49,7 @@ num-integer = "0.1"
4949
openssl = { version = "0.10", optional = true }
5050
pbkdf2 = "0.11"
5151
rand = "0.7"
52-
rand_core = { version = "0.5", features = ["std"] }
52+
rand_core = { version = "0.6.4", features = ["std"] }
5353
russh-cryptovec = { version = "0.7.0", path = "../cryptovec" }
5454
serde = { version = "1.0", features = ["derive"] }
5555
sha2 = "0.10"

russh-keys/src/agent/client.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use std::convert::TryFrom;
2+
13
use byteorder::{BigEndian, ByteOrder};
4+
use log::{debug, info};
25
use russh_cryptovec::CryptoVec;
36
use tokio;
47
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
5-
use log::{debug, info};
68

79
use super::{msg, Constraint};
810
use crate::encoding::{Encoding, Reader};
@@ -102,10 +104,10 @@ impl<S: AsyncRead + AsyncWrite + Unpin> AgentClient<S> {
102104
match *key {
103105
key::KeyPair::Ed25519(ref pair) => {
104106
self.buf.extend_ssh_string(b"ssh-ed25519");
105-
self.buf.extend_ssh_string(pair.public.as_bytes());
107+
self.buf.extend_ssh_string(pair.verifying_key().as_bytes());
106108
self.buf.push_u32_be(64);
107-
self.buf.extend(pair.secret.as_bytes());
108-
self.buf.extend(pair.public.as_bytes());
109+
self.buf.extend(pair.to_bytes().as_slice());
110+
self.buf.extend(pair.verifying_key().as_bytes());
109111
self.buf.extend_ssh_string(b"");
110112
}
111113
#[cfg(feature = "openssl")]
@@ -263,7 +265,7 @@ impl<S: AsyncRead + AsyncWrite + Unpin> AgentClient<S> {
263265
})
264266
}
265267
b"ssh-ed25519" => keys.push(PublicKey::Ed25519(
266-
ed25519_dalek::PublicKey::from_bytes(r.read_string()?)?,
268+
ed25519_dalek::VerifyingKey::try_from(r.read_string()?)?,
267269
)),
268270
t => {
269271
info!("Unsupported key type: {:?}", std::str::from_utf8(t))

russh-keys/src/agent/server.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::collections::HashMap;
2-
use std::sync::{Arc, RwLock};
2+
use std::convert::TryFrom;
33
use std::marker::Sync;
4+
use std::sync::{Arc, RwLock};
45
use std::time::{Duration, SystemTime};
56

67
use async_trait::async_trait;
@@ -211,7 +212,7 @@ impl<S: AsyncRead + AsyncWrite + Send + Unpin + 'static, A: Agent + Send + Sync
211212
}
212213
}
213214
let len = writebuf.len() - 4;
214-
BigEndian::write_u32(&mut writebuf[..], len as u32);
215+
BigEndian::write_u32(&mut writebuf[..], len as u32);
215216
Ok(())
216217
}
217218

@@ -255,25 +256,18 @@ impl<S: AsyncRead + AsyncWrite + Send + Unpin + 'static, A: Agent + Send + Sync
255256
let t = r.read_string()?;
256257
let (blob, key) = match t {
257258
b"ssh-ed25519" => {
258-
let public_ = r.read_string()?;
259259
let pos1 = r.position;
260260
let concat = r.read_string()?;
261261
let _comment = r.read_string()?;
262262
#[allow(clippy::indexing_slicing)] // length checked before
263-
let public = ed25519_dalek::PublicKey::from_bytes(
264-
public_.get(..32).ok_or(Error::KeyIsCorrupt)?,
265-
)?;
266-
let secret = ed25519_dalek::SecretKey::from_bytes(
263+
let secret = ed25519_dalek::SigningKey::try_from(
267264
concat.get(..32).ok_or(Error::KeyIsCorrupt)?,
268-
)?;
265+
).map_err(|_| Error::KeyIsCorrupt)?;
269266

270267
writebuf.push(msg::SUCCESS);
271268

272269
#[allow(clippy::indexing_slicing)] // positions checked before
273-
(
274-
self.buf[pos0..pos1].to_vec(),
275-
key::KeyPair::Ed25519(ed25519_dalek::Keypair { public, secret }),
276-
)
270+
(self.buf[pos0..pos1].to_vec(), key::KeyPair::Ed25519(secret))
277271
}
278272
#[cfg(feature = "openssl")]
279273
b"ssh-rsa" => {

russh-keys/src/format/openssh.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::TryFrom;
2+
13
use aes::cipher::block_padding::NoPadding;
24
use aes::cipher::{BlockDecryptMut, KeyIvInit, StreamCipher};
35
use bcrypt_pbkdf;
@@ -42,14 +44,10 @@ pub fn decode_openssh(secret: &[u8], password: Option<&str>) -> Result<key::KeyP
4244
if Some(pubkey) != seckey.get(32..) {
4345
return Err(Error::KeyIsCorrupt);
4446
}
45-
let secret = ed25519_dalek::SecretKey::from_bytes(
47+
let secret = ed25519_dalek::SigningKey::try_from(
4648
seckey.get(..32).ok_or(Error::KeyIsCorrupt)?,
4749
)?;
48-
let public = (&secret).into();
49-
return Ok(key::KeyPair::Ed25519(ed25519_dalek::Keypair {
50-
secret,
51-
public,
52-
}));
50+
return Ok(key::KeyPair::Ed25519(secret));
5351
} else if key_type == KEYTYPE_RSA && cfg!(feature = "openssl") {
5452
#[cfg(feature = "openssl")]
5553
{

russh-keys/src/format/pkcs8.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use openssl::pkey::Private;
99
use openssl::rsa::Rsa;
1010
#[cfg(test)]
1111
use rand_core::OsRng;
12+
use std::convert::TryFrom;
1213
use yasna::BERReaderSeq;
1314
use {std, yasna};
1415

@@ -116,8 +117,8 @@ fn asn1_read_aes256cbc(
116117
Ok(Ok(Encryption::Aes256Cbc(i)))
117118
}
118119

119-
fn write_key_v1(writer: &mut yasna::DERWriterSeq, secret: &ed25519_dalek::SecretKey) {
120-
let public = ed25519_dalek::PublicKey::from(secret);
120+
fn write_key_v1(writer: &mut yasna::DERWriterSeq, secret: &ed25519_dalek::SigningKey) {
121+
let public = ed25519_dalek::VerifyingKey::from(secret);
121122
writer.next().write_u32(1);
122123
// write OID
123124
writer.next().write_sequence(|writer| {
@@ -127,7 +128,7 @@ fn write_key_v1(writer: &mut yasna::DERWriterSeq, secret: &ed25519_dalek::Secret
127128
});
128129
let seed = yasna::construct_der(|writer| {
129130
writer.write_bytes(
130-
[secret.as_bytes().as_slice(), public.as_bytes().as_slice()]
131+
[secret.to_bytes().as_slice(), public.as_bytes().as_slice()]
131132
.concat()
132133
.as_slice(),
133134
)
@@ -145,22 +146,15 @@ fn read_key_v1(reader: &mut BERReaderSeq) -> Result<key::KeyPair, Error> {
145146
.next()
146147
.read_sequence(|reader| reader.next().read_oid())?;
147148
if oid.components().as_slice() == ED25519 {
148-
use ed25519_dalek::{Keypair, PublicKey, SecretKey};
149+
use ed25519_dalek::SigningKey;
149150
let secret = {
150151
let s = yasna::parse_der(&reader.next().read_bytes()?, |reader| reader.read_bytes())?;
151152

152153
s.get(..ed25519_dalek::SECRET_KEY_LENGTH)
153154
.ok_or(Error::KeyIsCorrupt)
154-
.and_then(|s| SecretKey::from_bytes(s).map_err(|_| Error::CouldNotReadKey))?
155+
.and_then(|s| SigningKey::try_from(s).map_err(|_| Error::CouldNotReadKey))?
155156
};
156-
let public = {
157-
let public = reader
158-
.next()
159-
.read_tagged(yasna::Tag::context(1), |reader| reader.read_bitvec())?
160-
.to_bytes();
161-
PublicKey::from_bytes(&public).map_err(|_| Error::CouldNotReadKey)?
162-
};
163-
Ok(key::KeyPair::Ed25519(Keypair { public, secret }))
157+
Ok(key::KeyPair::Ed25519(secret))
164158
} else {
165159
Err(Error::CouldNotReadKey)
166160
}
@@ -255,12 +249,12 @@ fn read_key_v0(_: &mut BERReaderSeq) -> Result<key::KeyPair, Error> {
255249

256250
#[test]
257251
fn test_read_write_pkcs8() {
258-
let ed25519_dalek::Keypair { public, secret } = ed25519_dalek::Keypair::generate(&mut OsRng {});
252+
let secret = ed25519_dalek::SigningKey::generate(&mut OsRng {});
259253
assert_eq!(
260-
public.as_bytes(),
261-
ed25519_dalek::PublicKey::from(&secret).as_bytes()
254+
secret.verifying_key().as_bytes(),
255+
ed25519_dalek::VerifyingKey::from(&secret).as_bytes()
262256
);
263-
let key = key::KeyPair::Ed25519(ed25519_dalek::Keypair { public, secret });
257+
let key = key::KeyPair::Ed25519(secret);
264258
let password = b"blabla";
265259
let ciphertext = encode_pkcs8_encrypted(password, 100, &key).unwrap();
266260
let key = decode_pkcs8(&ciphertext, Some(password)).unwrap();
@@ -317,7 +311,7 @@ pub fn encode_pkcs8_encrypted(
317311
pub fn encode_pkcs8(key: &key::KeyPair) -> Vec<u8> {
318312
yasna::construct_der(|writer| {
319313
writer.write_sequence(|writer| match *key {
320-
key::KeyPair::Ed25519(ref pair) => write_key_v1(writer, &pair.secret),
314+
key::KeyPair::Ed25519(ref pair) => write_key_v1(writer, pair),
321315
#[cfg(feature = "openssl")]
322316
key::KeyPair::RSA { ref key, .. } => write_key_v0(writer, key),
323317
})

russh-keys/src/key.rs

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414
//
15-
use serde::{Serialize, Deserialize};
16-
use ed25519_dalek::ed25519::signature::Signature as EdSignature;
1715
use ed25519_dalek::{Signer, Verifier};
1816
#[cfg(feature = "openssl")]
1917
use openssl::pkey::{Private, Public};
20-
use rand::rngs::OsRng;
18+
use rand_core::OsRng;
2119
use russh_cryptovec::CryptoVec;
20+
use serde::{Deserialize, Serialize};
21+
use std::convert::TryFrom;
2222

2323
use crate::encoding::{Encoding, Reader};
2424
pub use crate::signature::*;
@@ -109,7 +109,7 @@ impl SignatureHash {
109109
#[derive(Eq, Debug, Clone)]
110110
pub enum PublicKey {
111111
#[doc(hidden)]
112-
Ed25519(ed25519_dalek::PublicKey),
112+
Ed25519(ed25519_dalek::VerifyingKey),
113113
#[doc(hidden)]
114114
#[cfg(feature = "openssl")]
115115
RSA {
@@ -137,7 +137,7 @@ pub struct OpenSSLPKey(pub openssl::pkey::PKey<Public>);
137137

138138
#[cfg(feature = "openssl")]
139139
use std::cmp::{Eq, PartialEq};
140-
use std::convert::TryInto;
140+
141141
#[cfg(feature = "openssl")]
142142
impl PartialEq for OpenSSLPKey {
143143
fn eq(&self, b: &OpenSSLPKey) -> bool {
@@ -161,11 +161,13 @@ impl PublicKey {
161161
let mut p = pubkey.reader(0);
162162
let key_algo = p.read_string()?;
163163
let key_bytes = p.read_string()?;
164-
if key_algo != b"ssh-ed25519" || key_bytes.len() != ed25519_dalek::PUBLIC_KEY_LENGTH
165-
{
164+
if key_algo != b"ssh-ed25519" {
166165
return Err(Error::CouldNotReadKey);
167166
}
168-
ed25519_dalek::PublicKey::from_bytes(key_bytes)
167+
let Ok(key_bytes) = <&[u8; ed25519_dalek::PUBLIC_KEY_LENGTH]>::try_from(key_bytes) else {
168+
return Err(Error::CouldNotReadKey);
169+
};
170+
ed25519_dalek::VerifyingKey::from_bytes(key_bytes)
169171
.map(PublicKey::Ed25519)
170172
.map_err(Error::from)
171173
}
@@ -217,9 +219,13 @@ impl PublicKey {
217219
/// Verify a signature.
218220
pub fn verify_detached(&self, buffer: &[u8], sig: &[u8]) -> bool {
219221
match self {
220-
PublicKey::Ed25519(ref public) => ed25519_dalek::Signature::from_bytes(sig)
221-
.and_then(|sig| public.verify(buffer, &sig))
222-
.is_ok(),
222+
PublicKey::Ed25519(ref public) => {
223+
let Ok(sig) = ed25519_dalek::ed25519::SignatureBytes::try_from(sig) else {
224+
return false;
225+
};
226+
let sig = ed25519_dalek::Signature::from_bytes(&sig);
227+
public.verify(buffer, &sig).is_ok()
228+
}
223229

224230
#[cfg(feature = "openssl")]
225231
PublicKey::RSA { ref key, ref hash } => {
@@ -273,7 +279,7 @@ impl Verify for PublicKey {
273279
/// Public key exchange algorithms.
274280
#[allow(clippy::large_enum_variant)]
275281
pub enum KeyPair {
276-
Ed25519(ed25519_dalek::Keypair),
282+
Ed25519(ed25519_dalek::SigningKey),
277283
#[cfg(feature = "openssl")]
278284
RSA {
279285
key: openssl::rsa::Rsa<Private>,
@@ -285,10 +291,9 @@ impl Clone for KeyPair {
285291
fn clone(&self) -> Self {
286292
match self {
287293
#[allow(clippy::expect_used)]
288-
Self::Ed25519(kp) => Self::Ed25519(
289-
ed25519_dalek::Keypair::from_bytes(&kp.to_bytes())
290-
.expect("expected to clone keypair"),
291-
),
294+
Self::Ed25519(kp) => {
295+
Self::Ed25519(ed25519_dalek::SigningKey::from_bytes(&kp.to_bytes()))
296+
}
292297
#[cfg(feature = "openssl")]
293298
Self::RSA { key, hash } => Self::RSA {
294299
key: key.clone(),
@@ -304,7 +309,7 @@ impl std::fmt::Debug for KeyPair {
304309
KeyPair::Ed25519(ref key) => write!(
305310
f,
306311
"Ed25519 {{ public: {:?}, secret: (hidden) }}",
307-
key.public.as_bytes()
312+
key.verifying_key().as_bytes()
308313
),
309314
#[cfg(feature = "openssl")]
310315
KeyPair::RSA { .. } => write!(f, "RSA {{ (hidden) }}"),
@@ -322,7 +327,7 @@ impl KeyPair {
322327
/// Copy the public key of this algorithm.
323328
pub fn clone_public_key(&self) -> Result<PublicKey, Error> {
324329
Ok(match self {
325-
KeyPair::Ed25519(ref key) => PublicKey::Ed25519(key.public),
330+
KeyPair::Ed25519(ref key) => PublicKey::Ed25519(key.verifying_key()),
326331
#[cfg(feature = "openssl")]
327332
KeyPair::RSA { ref key, ref hash } => {
328333
use openssl::pkey::PKey;
@@ -347,10 +352,10 @@ impl KeyPair {
347352

348353
/// Generate a key pair.
349354
pub fn generate_ed25519() -> Option<Self> {
350-
let keypair = ed25519_dalek::Keypair::generate(&mut OsRng {});
355+
let keypair = ed25519_dalek::SigningKey::generate(&mut OsRng {});
351356
assert_eq!(
352-
keypair.public.as_bytes(),
353-
ed25519_dalek::PublicKey::from(&keypair.secret).as_bytes()
357+
keypair.verifying_key().as_bytes(),
358+
ed25519_dalek::VerifyingKey::from(&keypair).as_bytes()
354359
);
355360
Some(KeyPair::Ed25519(keypair))
356361
}
@@ -366,9 +371,7 @@ impl KeyPair {
366371
match self {
367372
#[allow(clippy::unwrap_used)]
368373
KeyPair::Ed25519(ref secret) => Ok(Signature::Ed25519(SignatureBytes(
369-
ed25519_dalek::ed25519::signature::Signature::as_bytes(&secret.sign(to_sign))
370-
.try_into()
371-
.unwrap(),
374+
secret.sign(to_sign).to_bytes(),
372375
))),
373376
#[cfg(feature = "openssl")]
374377
KeyPair::RSA { ref key, ref hash } => Ok(Signature::RSA {
@@ -391,11 +394,9 @@ impl KeyPair {
391394
KeyPair::Ed25519(ref secret) => {
392395
let signature = secret.sign(to_sign.as_ref());
393396

394-
buffer.push_u32_be(
395-
(ED25519.0.len() + EdSignature::as_bytes(&signature).len() + 8) as u32,
396-
);
397+
buffer.push_u32_be((ED25519.0.len() + signature.to_bytes().len() + 8) as u32);
397398
buffer.extend_ssh_string(ED25519.0.as_bytes());
398-
buffer.extend_ssh_string(signature.as_bytes());
399+
buffer.extend_ssh_string(signature.to_bytes().as_slice());
399400
}
400401
#[cfg(feature = "openssl")]
401402
KeyPair::RSA { ref key, ref hash } => {
@@ -418,9 +419,9 @@ impl KeyPair {
418419
match self {
419420
KeyPair::Ed25519(ref secret) => {
420421
let signature = secret.sign(buffer);
421-
buffer.push_u32_be((ED25519.0.len() + signature.as_bytes().len() + 8) as u32);
422+
buffer.push_u32_be((ED25519.0.len() + signature.to_bytes().len() + 8) as u32);
422423
buffer.extend_ssh_string(ED25519.0.as_bytes());
423-
buffer.extend_ssh_string(signature.as_bytes());
424+
buffer.extend_ssh_string(signature.to_bytes().as_slice());
424425
}
425426
#[cfg(feature = "openssl")]
426427
KeyPair::RSA { ref key, ref hash } => {
@@ -482,7 +483,10 @@ pub fn parse_public_key(
482483
let t = pos.read_string()?;
483484
if t == b"ssh-ed25519" {
484485
if let Ok(pubkey) = pos.read_string() {
485-
let p = ed25519_dalek::PublicKey::from_bytes(pubkey).map_err(Error::from)?;
486+
let Ok(pubkey) = <&[u8; ed25519_dalek::PUBLIC_KEY_LENGTH]>::try_from(pubkey) else {
487+
return Err(Error::CouldNotReadKey);
488+
};
489+
let p = ed25519_dalek::VerifyingKey::from_bytes(pubkey).map_err(Error::from)?;
486490
return Ok(PublicKey::Ed25519(p));
487491
}
488492
}

russh-keys/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,10 +245,10 @@ impl PublicKeyBase64 for key::KeyPair {
245245
s.extend_from_slice(name);
246246
match *self {
247247
key::KeyPair::Ed25519(ref key) => {
248-
let public = key.public.as_bytes();
248+
let public = key.verifying_key().to_bytes();
249249
#[allow(clippy::unwrap_used)] // Vec<>.write can't fail
250250
s.write_u32::<BigEndian>(public.len() as u32).unwrap();
251-
s.extend_from_slice(public);
251+
s.extend_from_slice(public.as_slice());
252252
}
253253
#[cfg(feature = "openssl")]
254254
key::KeyPair::RSA { ref key, .. } => {

0 commit comments

Comments
 (0)