From ed324eb4391491c3b1897a8ee0671533ccb41c13 Mon Sep 17 00:00:00 2001 From: C0ffeeCode Date: Thu, 26 Sep 2024 23:18:45 +0200 Subject: [PATCH] WIP: Replace outdated `rust-crypto` --- Cargo.lock | 345 ++++++++++++++++++++++++++++++++- Cargo.toml | 13 +- src/key_exchange/curve25519.rs | 44 +++-- src/lib.rs | 2 +- src/mac/hmac_new.rs | 38 ++++ src/mac/mod.rs | 7 +- src/public_key/ed25519.rs | 64 +++--- 7 files changed, 470 insertions(+), 43 deletions(-) create mode 100644 src/mac/hmac_new.rs diff --git a/Cargo.lock b/Cargo.lock index 70d5f4e..c15192c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,18 +2,68 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -26,6 +76,130 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core 0.6.4", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -38,6 +212,16 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -49,6 +233,34 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "libc" version = "0.2.159" @@ -89,6 +301,34 @@ dependencies = [ "autocfg", ] +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -197,14 +437,18 @@ dependencies = [ name = "redox-ssh" version = "0.1.0" dependencies = [ + "aes-gcm", "byteorder", + "curve25519-dalek", + "ed25519-dalek", + "hmac", "libc", "log", "num-bigint", "rand 0.8.5", "redox_syscall", "rust-crypto", - "rustc-serialize", + "sha2", ] [[package]] @@ -235,6 +479,77 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.77" @@ -257,12 +572,34 @@ dependencies = [ "winapi", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" @@ -317,3 +654,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 9e51ec5..714e36a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,20 @@ byteorder = "^1.5.0" log = "^0.4.22" num-bigint = "0.4.6" rand = "^0.8.5" +# This crate is deprecated in favor of serde: +# rustc-serialize = "^0.3.25" +# Not updated for 8 years, depends and blocks build on Redox rust-crypto = "^0.2.36" -rustc-serialize = "^0.3.25" + +curve25519-dalek = "^4.1.3" +ed25519-dalek = { version = "^2.1.1", features = ["rand_core"]} +sha2 = { version = "^0.10.8" } +hmac = { version = "^0.12.1", features = ["std", "reset"]} +aes-gcm = "0.10.3" [target.'cfg(not(target_os = "redox"))'.dependencies] -libc = "^0.2.26" +libc = "^0.2.159" + [target.'cfg(target_os = "redox")'.dependencies] redox_syscall = "0.2" diff --git a/src/key_exchange/curve25519.rs b/src/key_exchange/curve25519.rs index 7dc7bac..8b0588d 100644 --- a/src/key_exchange/curve25519.rs +++ b/src/key_exchange/curve25519.rs @@ -1,8 +1,10 @@ -use crypto::curve25519; -use crypto::digest::Digest; -use crypto::sha2::Sha256; +use curve25519_dalek::{MontgomeryPoint, Scalar}; +// use crypto::curve25519; +// use crypto::digest::Digest; +// use crypto::sha2::Sha256; use num_bigint::{BigInt, Sign}; use rand::RngCore; +use sha2::{Digest, Sha256}; use crate::connection::{Connection, ConnectionType}; use crate::key_exchange::{KexResult, KeyExchange}; @@ -36,14 +38,14 @@ impl KeyExchange for Curve25519 { } fn hash(&self, data: &[&[u8]]) -> Vec { - let mut hash = [0; 32]; + // let mut hash = [0; 32]; let mut hasher = Sha256::new(); for item in data { - hasher.input(item); + hasher.update(item); } - hasher.result(&mut hash); + let hash = hasher.finalize(); hash.to_vec() } @@ -81,16 +83,32 @@ impl KeyExchange for Curve25519 { secret }; - let server_public = curve25519::curve25519_base(&server_secret); + // let server_public = crypto::curve25519::curve25519_base(&server_secret); + // let shared_secret = { + // let mut buf = Vec::new(); + // buf.write_mpint(BigInt::from_bytes_be( + // Sign::Plus, + // &crypto::curve25519::curve25519(&server_secret, &client_public), + // )).ok(); + // buf + // }; + + // ------------------------------------- + + let server_secret_scalar = Scalar::from_bytes_mod_order(server_secret); + let server_public = MontgomeryPoint::mul_base(&server_secret_scalar); let shared_secret = { let mut buf = Vec::new(); - buf.write_mpint(BigInt::from_bytes_be( - Sign::Plus, - &curve25519::curve25519(&server_secret, &client_public), - )).ok(); + let client_public_array: [u8; 32] = client_public.clone().try_into().unwrap(); // TODO + let client_public_point = MontgomeryPoint(client_public_array); + let server_secret_scalar = Scalar::from_bytes_mod_order(server_secret); + let shared_secret_point = client_public_point * server_secret_scalar; + buf.write_mpint(BigInt::from_bytes_be(Sign::Plus, &shared_secret_point.to_bytes())).ok(); buf }; + //------------------------------- + let hash_data = { let mut buf = Vec::new(); let data = &conn.hash_data; @@ -103,7 +121,7 @@ impl KeyExchange for Curve25519 { data.server_kexinit.as_ref().unwrap().as_slice(), public_key.as_slice(), client_public.as_slice(), - &server_public, + &server_public.to_bytes(), ]; for item in items.iter() { @@ -120,7 +138,7 @@ impl KeyExchange for Curve25519 { let signature = config.as_ref().key.sign(&hash).unwrap(); packet.write_bytes(public_key.as_slice()).unwrap(); - packet.write_bytes(&server_public).unwrap(); + packet.write_bytes(&server_public.to_bytes()).unwrap(); packet.write_bytes(signature.as_slice()).unwrap(); // Signature self.exchange_hash = Some(hash); diff --git a/src/lib.rs b/src/lib.rs index cc4eed8..8a2b1fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ extern crate byteorder; extern crate rand; -extern crate crypto; +// extern crate crypto; extern crate num_bigint; #[macro_use] extern crate log; diff --git a/src/mac/hmac_new.rs b/src/mac/hmac_new.rs new file mode 100644 index 0000000..dd7198e --- /dev/null +++ b/src/mac/hmac_new.rs @@ -0,0 +1,38 @@ +use hmac::{Hmac, Mac}; +use sha2::Sha256; + +use super::MacAlgorithm; + +type HmacSha256 = Hmac; + +pub struct ExtHmac { + hmac: HmacSha256, +} + +impl ExtHmac { + pub fn new(key: &[u8]) -> Self { + Self { + hmac: HmacSha256::new_from_slice(key).unwrap(), + } + } +} + +impl MacAlgorithm for ExtHmac { + fn size(&self) -> usize { + 32 + } + + fn sign(&mut self, data: &[u8], seq: u32, buf: &mut [u8]) { + let sequence = &[ + ((seq & 0xff000000) >> 24) as u8, + ((seq & 0x00ff0000) >> 16) as u8, + ((seq & 0x0000ff00) >> 8) as u8, + (seq & 0x000000ff) as u8, + ]; + self.hmac.update(sequence); + self.hmac.update(data); + let result = self.hmac.clone().finalize(); + buf.copy_from_slice(&result.into_bytes()); + self.hmac.reset(); + } +} diff --git a/src/mac/mod.rs b/src/mac/mod.rs index e2d492a..f499f6f 100644 --- a/src/mac/mod.rs +++ b/src/mac/mod.rs @@ -1,6 +1,9 @@ -mod hmac; -pub use self::hmac::Hmac; +// mod hmac; +mod hmac_new; + +// pub use self::hmac::Hmac; +pub use self::hmac_new::ExtHmac as Hmac; pub trait MacAlgorithm { fn size(&self) -> usize; diff --git a/src/public_key/ed25519.rs b/src/public_key/ed25519.rs index 7cbf208..0ec96cd 100644 --- a/src/public_key/ed25519.rs +++ b/src/public_key/ed25519.rs @@ -1,11 +1,13 @@ -use std::io::{self, Read, Write}; use std::io::ErrorKind::InvalidData; +use std::io::{self, Read, Write}; -use crypto::ed25519; -use rand::RngCore; +use ed25519_dalek::ed25519::signature::SignerMut; +use ed25519_dalek::{Signature, SigningKey, VerifyingKey}; +use rand::rngs::OsRng; +// use crypto::ed25519; use crate::public_key::{ - CryptoSystem, KeyPair, KeyPairIdValidationError, SigningError + CryptoSystem, KeyPair, KeyPairIdValidationError, SigningError, }; pub static ED25519: CryptoSystem = CryptoSystem { @@ -16,17 +18,16 @@ pub static ED25519: CryptoSystem = CryptoSystem { }; struct Ed25519KeyPair { - private: Option<[u8; 64]>, - public: [u8; 32], + private: Option, //[u8; 64]>, + public: VerifyingKey, // [u8; 32], } impl Ed25519KeyPair { fn generate(_: Option) -> Box { - let mut seed = [0u8; 32]; - let mut rng = rand::thread_rng(); - rng.fill_bytes(&mut seed); + let mut csprng = OsRng; + let private: SigningKey = SigningKey::generate(&mut csprng); + let public: VerifyingKey = private.verifying_key(); - let (private, public) = ed25519::keypair(&seed); Box::new(Ed25519KeyPair { private: Some(private), public, @@ -46,6 +47,7 @@ impl Ed25519KeyPair { let mut public = [0u8; 32]; r.read_exact(&mut public)?; + let public = VerifyingKey::from_bytes(&public).unwrap(); // TODO if r.read_uint32()? != 64 { return Err(io::Error::new(InvalidData, "invalid ED25519 key")); @@ -53,6 +55,7 @@ impl Ed25519KeyPair { let mut private = [0u8; 64]; r.read_exact(&mut private)?; + let private = SigningKey::from_keypair_bytes(&private).unwrap(); // TODO, also wtf Ok(Box::new(Ed25519KeyPair { public, @@ -69,6 +72,8 @@ impl Ed25519KeyPair { let mut public = [0u8; 32]; r.read_exact(&mut public)?; + let public = VerifyingKey::from_bytes(&public) + .unwrap(); // TODO Ok(Box::new(Ed25519KeyPair { private: None, @@ -86,9 +91,13 @@ impl KeyPair for Ed25519KeyPair { self.private.is_some() } - fn verify(&self, data: &[u8], signature: &[u8]) -> Result { - use std::io::Cursor; + fn verify( + &self, + data: &[u8], + signature: &[u8], + ) -> Result { use crate::packet::ReadPacketExt; + use std::io::Cursor; const EXPECTED_ID: &[u8] = b"ssh-ed25519"; @@ -96,23 +105,30 @@ impl KeyPair for Ed25519KeyPair { let received_id = reader.read_string().unwrap_or_default(); if received_id == EXPECTED_ID { - if let Ok(sig) = reader.read_string() { - return Ok(ed25519::verify(data, &self.public, sig.as_slice())); + if let Ok(sig) = reader.read_string() { // TODO: .read_string() { + let sig_array: &[u8; 64] = sig.as_slice().try_into().expect("slice with incorrect length"); // TODO + let sig = Signature::from_bytes(sig_array); // TODO + let res = self.public.verify_strict(data, &sig); + return Ok(res.is_ok()); + // return Ok(ed25519::verify(data, &self.public, sig.as_slice())); } } - Err(KeyPairIdValidationError {received_id, expected_id: EXPECTED_ID }) + Err(KeyPairIdValidationError { + received_id, + expected_id: EXPECTED_ID, + }) } fn sign(&self, data: &[u8]) -> Result, SigningError> { use crate::packet::WritePacketExt; - if let Some(private_key) = self.private { + if let Some(mut private_key) = self.private.clone() { let mut result = Vec::new(); - let sig = ed25519::signature(data, &private_key); + let sig = private_key.sign(data); + // let sig = ed25519::signature(data, &private_key); result.write_string("ssh-ed25519")?; - result.write_bytes(&sig)?; + result.write_bytes(&sig.to_bytes())?; Ok(result) - } - else { + } else { Err(SigningError::NoPrivateKey) } } @@ -120,15 +136,15 @@ impl KeyPair for Ed25519KeyPair { fn write_public(&self, w: &mut dyn Write) -> io::Result<()> { use crate::packet::WritePacketExt; w.write_string("ssh-ed25519")?; - w.write_bytes(&self.public) + w.write_bytes(self.public.as_bytes()) } fn export(&self, w: &mut dyn Write) -> io::Result<()> { use crate::packet::WritePacketExt; w.write_string("ssh-ed25519")?; - w.write_bytes(&self.public)?; - if let Some(private_key) = self.private { - w.write_bytes(&private_key)?; + w.write_bytes(self.public.as_bytes())?; + if let Some(private_key) = &self.private { + w.write_bytes(private_key.as_bytes())?; } Ok(()) }