Skip to content

Commit f536867

Browse files
committed
Connect to ssh-agent in a sync way
Signed-off-by: xphoniex <[email protected]>
1 parent 9cbaac5 commit f536867

File tree

5 files changed

+77
-110
lines changed

5 files changed

+77
-110
lines changed

Cargo.toml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@ edition = "2018"
77
license = "GPL-3.0-or-later"
88

99
[features]
10-
ssh-agent = ["lnk-thrussh-agent", "lnk-thrussh-encoding"]
10+
ssh-agent = ["agent", "encoding"]
1111

1212
[dependencies]
13-
async-trait = "0.1"
1413
byteorder = "1.4"
15-
futures = "0.3"
1614
generic-array = { version = "0.14", features = ["serde"] }
1715
lazy_static = "1"
18-
lnk-cryptovec = "0.6.0"
19-
lnk-thrussh-agent = { version = "0.1.0", optional = true, default-features = false }
20-
lnk-thrussh-encoding = { version = "0.1.0", optional = true }
16+
cryptovec = { version = "0.6.0", git = "https://github.com/radicle-dev/radicle-ssh" }
17+
agent = { version = "0.1.0", git = "https://github.com/radicle-dev/radicle-ssh", optional = true, default-features = false }
18+
encoding = { version = "0.1.0", git = "https://github.com/radicle-dev/radicle-ssh", optional = true }
2119
rand = "0.8.4"
2220
rpassword = "4.0"
2321
secstr = "0.5"
@@ -43,11 +41,7 @@ version = "^0.10.0"
4341
default-features = false
4442

4543
[dev-dependencies]
46-
tokio = { version = ">= 1.8.4", features = ["macros", "rt"] }
4744
ed25519-dalek = "=1.0.1"
48-
lnk-thrussh-agent = { version = "0.1.0", features = [ "smol-agent" ], default-features = false }
4945
rand = { version = "0.8.4", default-features = false }
50-
smol = { version = "1.2" }
5146
sodiumoxide = "0.2"
5247
tempfile = "3"
53-

examples/ssh-agent.rs

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,56 +16,46 @@
1616
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1717

1818
#[cfg(feature = "ssh-agent")]
19-
use smol::{io, net::unix::UnixStream};
19+
use std::{io, net::unix::UnixStream};
2020

2121
#[cfg(feature = "ssh-agent")]
2222
fn main() -> io::Result<()> {
2323
use radicle_keystore::sign::{ssh, Signer, SshAgent};
2424
use rand::rngs::OsRng;
2525

26-
smol::block_on(async {
27-
let sk = ed25519_zebra::SigningKey::new(OsRng {});
28-
let pk = ed25519_zebra::VerificationKey::from(&sk);
29-
let public = ssh::ed25519::PublicKey(pk.into());
30-
let agent = SshAgent::new(public);
26+
let sk = ed25519_zebra::SigningKey::new(OsRng {});
27+
let pk = ed25519_zebra::VerificationKey::from(&sk);
28+
let public = ssh::ed25519::PublicKey(pk.into());
29+
let agent = SshAgent::new(public);
3130

32-
// This could be a `rad-ssh-add` executable which reads the local key from
33-
// the filestore (prompting for the password).
34-
ssh::add_key::<UnixStream>(&agent, sk, &[]).await.unwrap();
31+
// This could be a `rad-ssh-add` executable which reads the local key from
32+
// the filestore (prompting for the password).
33+
ssh::add_key::<UnixStream>(&agent, sk, &[]).unwrap();
3534

36-
println!("connecting to ssh-agent");
37-
let signer = agent
38-
.connect::<UnixStream>()
39-
.await
40-
.expect("could not connect to ssh-agent");
41-
println!("asking agent to sign some data");
42-
let sig = signer
43-
.sign(b"cooper")
44-
.await
45-
.expect("signing via ssh-agent failed");
46-
println!("verifying signature");
47-
pk.verify(&ed25519_zebra::Signature::from(sig.0), b"cooper")
48-
.expect("ssh-agent didn't return a valid signature");
49-
println!("it worksed");
35+
println!("connecting to ssh-agent");
36+
let signer = agent
37+
.connect::<UnixStream>()
38+
.expect("could not connect to ssh-agent");
39+
println!("asking agent to sign some data");
40+
let sig = signer
41+
.sign(b"cooper")
42+
.expect("signing via ssh-agent failed");
43+
println!("verifying signature");
44+
pk.verify(&ed25519_zebra::Signature::from(sig.0), b"cooper")
45+
.expect("ssh-agent didn't return a valid signature");
46+
println!("it worksed");
5047

51-
let keys = ssh::list_keys::<UnixStream>(&agent)
52-
.await
53-
.expect("could not list keys");
54-
if keys.contains(&public) {
55-
println!("added key succesfully")
56-
}
57-
ssh::remove_key::<UnixStream>(&agent, &public)
58-
.await
59-
.expect("could not remove key from ssh-agent");
60-
let keys = ssh::list_keys::<UnixStream>(&agent)
61-
.await
62-
.expect("could not list keys");
63-
if !keys.contains(&public) {
64-
println!("removed key successfully")
65-
}
48+
let keys = ssh::list_keys::<UnixStream>(&agent).expect("could not list keys");
49+
if keys.contains(&public) {
50+
println!("added key succesfully")
51+
}
52+
ssh::remove_key::<UnixStream>(&agent, &public).expect("could not remove key from ssh-agent");
53+
let keys = ssh::list_keys::<UnixStream>(&agent).expect("could not list keys");
54+
if !keys.contains(&public) {
55+
println!("removed key successfully")
56+
}
6657

67-
Ok(())
68-
})
58+
Ok(())
6959
}
7060

7161
#[cfg(not(feature = "ssh-agent"))]

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
//! encryption entirely to an external system (such as GPG, or a password
3434
//! manager).
3535
36-
#[macro_use]
37-
extern crate async_trait;
3836
#[macro_use]
3937
extern crate lazy_static;
4038

src/sign/ed25519.rs

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ impl Debug for Signature {
105105
}
106106
}
107107

108-
#[async_trait]
109108
pub trait Signer {
110109
type Error: std::error::Error + Send + Sync + 'static;
111110

@@ -114,10 +113,9 @@ pub trait Signer {
114113

115114
/// Sign the supplied data with the secret key corresponding to
116115
/// [`Signer::public_key`]
117-
async fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error>;
116+
fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error>;
118117
}
119118

120-
#[async_trait]
121119
impl<S> Signer for Arc<S>
122120
where
123121
S: Signer + Send + Sync,
@@ -128,12 +126,11 @@ where
128126
self.as_ref().public_key()
129127
}
130128

131-
async fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
132-
self.as_ref().sign(data).await
129+
fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
130+
self.as_ref().sign(data)
133131
}
134132
}
135133

136-
#[async_trait]
137134
impl Signer for ed25519_zebra::SigningKey {
138135
type Error = Infallible;
139136

@@ -142,7 +139,7 @@ impl Signer for ed25519_zebra::SigningKey {
142139
PublicKey(vk.into())
143140
}
144141

145-
async fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
142+
fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
146143
let signature = self.sign(data);
147144
Ok(Signature(signature.into()))
148145
}
@@ -152,10 +149,10 @@ impl Signer for ed25519_zebra::SigningKey {
152149
pub mod thrussh {
153150
use std::convert::{TryFrom as _, TryInto as _};
154151

152+
use agent;
155153
use byteorder::{BigEndian, ByteOrder as _};
156-
use lnk_cryptovec::CryptoVec;
157-
use lnk_thrussh_agent as agent;
158-
use lnk_thrussh_encoding::{Encoding as _, Position, Reader as _};
154+
use cryptovec::CryptoVec;
155+
use encoding::{Encoding as _, Position, Reader as _};
159156
use thiserror::Error;
160157

161158
use super::*;
@@ -165,7 +162,7 @@ pub mod thrussh {
165162
#[error("invalid signature was computed")]
166163
Invalid,
167164
#[error(transparent)]
168-
Encoding(#[from] lnk_thrussh_encoding::Error),
165+
Encoding(#[from] encoding::Error),
169166
}
170167

171168
impl agent::key::Signature for Signature {
@@ -190,7 +187,7 @@ pub mod thrussh {
190187
#[error("the public key parsed was not 32 bits in length")]
191188
Invalid,
192189
#[error(transparent)]
193-
Encoding(#[from] lnk_thrussh_encoding::Error),
190+
Encoding(#[from] encoding::Error),
194191
}
195192

196193
impl agent::key::Public for PublicKey {
@@ -227,7 +224,7 @@ pub mod thrussh {
227224
#[derive(Debug, Error)]
228225
pub enum SigningKeyError {
229226
#[error(transparent)]
230-
Encoding(#[from] lnk_thrussh_encoding::Error),
227+
Encoding(#[from] encoding::Error),
231228
#[error(transparent)]
232229
Ed25519(#[from] ed25519_zebra::Error),
233230
}
@@ -299,7 +296,7 @@ mod tests {
299296
/// implementations must be byte-for-byte equal.
300297
///
301298
/// All combinatorial pairs of `Signer` implementations must pass this.
302-
async fn compat<S1, S2>(signer1: S1, signer2: S2)
299+
fn compat<S1, S2>(signer1: S1, signer2: S2)
303300
where
304301
S1: Signer,
305302
S2: Signer,
@@ -309,41 +306,39 @@ mod tests {
309306
{
310307
assert_eq!(signer1.public_key(), signer2.public_key());
311308
assert_eq!(
312-
signer1.sign(MESSAGE).await.unwrap(),
313-
signer2.sign(MESSAGE).await.unwrap()
309+
signer1.sign(MESSAGE).unwrap(),
310+
signer2.sign(MESSAGE).unwrap()
314311
);
315312
}
316313

317-
#[async_trait]
318314
impl Signer for sodiumoxide::crypto::sign::ed25519::SecretKey {
319315
type Error = Infallible;
320316

321317
fn public_key(&self) -> PublicKey {
322318
PublicKey(self.public_key().0)
323319
}
324320

325-
async fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
321+
fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
326322
Ok(Signature(
327323
sodiumoxide::crypto::sign::ed25519::sign_detached(data, self).to_bytes(),
328324
))
329325
}
330326
}
331327

332-
#[async_trait]
333328
impl Signer for ed25519_dalek::Keypair {
334329
type Error = Infallible;
335330

336331
fn public_key(&self) -> PublicKey {
337332
PublicKey(self.public.to_bytes())
338333
}
339334

340-
async fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
335+
fn sign(&self, data: &[u8]) -> Result<Signature, Self::Error> {
341336
Ok(Signature(DalekSigner::sign(self, data).to_bytes()))
342337
}
343338
}
344339

345-
#[tokio::test]
346-
async fn compat_sodium_dalek() {
340+
#[test]
341+
fn compat_sodium_dalek() {
347342
sodiumoxide::init().unwrap();
348343

349344
let (_, sodium) = sodium::gen_keypair();
@@ -353,11 +348,11 @@ mod tests {
353348
ed25519_dalek::Keypair { secret, public }
354349
};
355350

356-
compat(sodium, dalek).await
351+
compat(sodium, dalek)
357352
}
358353

359-
#[tokio::test]
360-
async fn compat_zebra_dalek() {
354+
#[test]
355+
fn compat_zebra_dalek() {
361356
use rand::rngs::OsRng;
362357

363358
let csprng = OsRng {};
@@ -369,6 +364,6 @@ mod tests {
369364
ed25519_dalek::Keypair { secret, public }
370365
};
371366

372-
compat(zebra, dalek).await
367+
compat(zebra, dalek)
373368
}
374369
}

0 commit comments

Comments
 (0)