diff --git a/Cargo.toml b/Cargo.toml
index e8fb74e..76fc773 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,17 +7,15 @@ edition = "2018"
license = "GPL-3.0-or-later"
[features]
-ssh-agent = ["lnk-thrussh-agent", "lnk-thrussh-encoding"]
+ssh-agent = ["agent", "encoding"]
[dependencies]
-async-trait = "0.1"
byteorder = "1.4"
-futures = "0.3"
generic-array = { version = "0.14", features = ["serde"] }
lazy_static = "1"
-lnk-cryptovec = "0.6.0"
-lnk-thrussh-agent = { version = "0.1.0", optional = true, default-features = false }
-lnk-thrussh-encoding = { version = "0.1.0", optional = true }
+cryptovec = { version = "0.6.0", git = "https://github.com/radicle-dev/radicle-ssh" }
+agent = { version = "0.1.0", git = "https://github.com/radicle-dev/radicle-ssh", optional = true, default-features = false }
+encoding = { version = "0.1.0", git = "https://github.com/radicle-dev/radicle-ssh", optional = true }
rand = "0.8.4"
rpassword = "4.0"
secstr = "0.5"
@@ -43,11 +41,7 @@ version = "^0.10.0"
default-features = false
[dev-dependencies]
-tokio = { version = ">= 1.8.4", features = ["macros", "rt"] }
ed25519-dalek = "=1.0.1"
-lnk-thrussh-agent = { version = "0.1.0", features = [ "smol-agent" ], default-features = false }
rand = { version = "0.8.4", default-features = false }
-smol = { version = "1.2" }
sodiumoxide = "0.2"
tempfile = "3"
-
diff --git a/deny.toml b/deny.toml
index e4dc7db..e0d618f 100644
--- a/deny.toml
+++ b/deny.toml
@@ -192,4 +192,4 @@ unknown-git = "deny"
# if not specified. If it is specified but empty, no registries are allowed.
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
-allow-git = []
+allow-git = ["https://github.com/radicle-dev/radicle-ssh"]
diff --git a/examples/ssh-agent.rs b/examples/ssh-agent.rs
index f1779b4..6252e96 100644
--- a/examples/ssh-agent.rs
+++ b/examples/ssh-agent.rs
@@ -16,56 +16,46 @@
// along with this program. If not, see .
#[cfg(feature = "ssh-agent")]
-use smol::{io, net::unix::UnixStream};
+use std::{io, os::unix::net::UnixStream};
#[cfg(feature = "ssh-agent")]
fn main() -> io::Result<()> {
use radicle_keystore::sign::{ssh, Signer, SshAgent};
use rand::rngs::OsRng;
- smol::block_on(async {
- let sk = ed25519_zebra::SigningKey::new(OsRng {});
- let pk = ed25519_zebra::VerificationKey::from(&sk);
- let public = ssh::ed25519::PublicKey(pk.into());
- let agent = SshAgent::new(public);
+ let sk = ed25519_zebra::SigningKey::new(OsRng {});
+ let pk = ed25519_zebra::VerificationKey::from(&sk);
+ let public = ssh::ed25519::PublicKey(pk.into());
+ let agent = SshAgent::new(public);
- // This could be a `rad-ssh-add` executable which reads the local key from
- // the filestore (prompting for the password).
- ssh::add_key::(&agent, sk, &[]).await.unwrap();
+ // This could be a `rad-ssh-add` executable which reads the local key from
+ // the filestore (prompting for the password).
+ ssh::add_key::(&agent, sk, &[]).unwrap();
- println!("connecting to ssh-agent");
- let signer = agent
- .connect::()
- .await
- .expect("could not connect to ssh-agent");
- println!("asking agent to sign some data");
- let sig = signer
- .sign(b"cooper")
- .await
- .expect("signing via ssh-agent failed");
- println!("verifying signature");
- pk.verify(&ed25519_zebra::Signature::from(sig.0), b"cooper")
- .expect("ssh-agent didn't return a valid signature");
- println!("it worksed");
+ println!("connecting to ssh-agent");
+ let signer = agent
+ .connect::()
+ .expect("could not connect to ssh-agent");
+ println!("asking agent to sign some data");
+ let sig = signer
+ .sign(b"cooper")
+ .expect("signing via ssh-agent failed");
+ println!("verifying signature");
+ pk.verify(&ed25519_zebra::Signature::from(sig.0), b"cooper")
+ .expect("ssh-agent didn't return a valid signature");
+ println!("it worksed");
- let keys = ssh::list_keys::(&agent)
- .await
- .expect("could not list keys");
- if keys.contains(&public) {
- println!("added key succesfully")
- }
- ssh::remove_key::(&agent, &public)
- .await
- .expect("could not remove key from ssh-agent");
- let keys = ssh::list_keys::(&agent)
- .await
- .expect("could not list keys");
- if !keys.contains(&public) {
- println!("removed key successfully")
- }
+ let keys = ssh::list_keys::(&agent).expect("could not list keys");
+ if keys.contains(&public) {
+ println!("added key succesfully")
+ }
+ ssh::remove_key::(&agent, &public).expect("could not remove key from ssh-agent");
+ let keys = ssh::list_keys::(&agent).expect("could not list keys");
+ if !keys.contains(&public) {
+ println!("removed key successfully")
+ }
- Ok(())
- })
+ Ok(())
}
#[cfg(not(feature = "ssh-agent"))]
diff --git a/src/lib.rs b/src/lib.rs
index 2b3dad4..ddf2c04 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -33,8 +33,6 @@
//! encryption entirely to an external system (such as GPG, or a password
//! manager).
-#[macro_use]
-extern crate async_trait;
#[macro_use]
extern crate lazy_static;
diff --git a/src/sign/ed25519.rs b/src/sign/ed25519.rs
index 5ddba6c..b072dcc 100644
--- a/src/sign/ed25519.rs
+++ b/src/sign/ed25519.rs
@@ -105,7 +105,6 @@ impl Debug for Signature {
}
}
-#[async_trait]
pub trait Signer {
type Error: std::error::Error + Send + Sync + 'static;
@@ -114,10 +113,9 @@ pub trait Signer {
/// Sign the supplied data with the secret key corresponding to
/// [`Signer::public_key`]
- async fn sign(&self, data: &[u8]) -> Result;
+ fn sign(&self, data: &[u8]) -> Result;
}
-#[async_trait]
impl Signer for Arc
where
S: Signer + Send + Sync,
@@ -128,12 +126,11 @@ where
self.as_ref().public_key()
}
- async fn sign(&self, data: &[u8]) -> Result {
- self.as_ref().sign(data).await
+ fn sign(&self, data: &[u8]) -> Result {
+ self.as_ref().sign(data)
}
}
-#[async_trait]
impl Signer for ed25519_zebra::SigningKey {
type Error = Infallible;
@@ -142,7 +139,7 @@ impl Signer for ed25519_zebra::SigningKey {
PublicKey(vk.into())
}
- async fn sign(&self, data: &[u8]) -> Result {
+ fn sign(&self, data: &[u8]) -> Result {
let signature = self.sign(data);
Ok(Signature(signature.into()))
}
@@ -152,10 +149,10 @@ impl Signer for ed25519_zebra::SigningKey {
pub mod thrussh {
use std::convert::{TryFrom as _, TryInto as _};
+ use agent;
use byteorder::{BigEndian, ByteOrder as _};
- use lnk_cryptovec::CryptoVec;
- use lnk_thrussh_agent as agent;
- use lnk_thrussh_encoding::{Encoding as _, Position, Reader as _};
+ use cryptovec::CryptoVec;
+ use encoding::{Encoding as _, Position, Reader as _};
use thiserror::Error;
use super::*;
@@ -165,7 +162,7 @@ pub mod thrussh {
#[error("invalid signature was computed")]
Invalid,
#[error(transparent)]
- Encoding(#[from] lnk_thrussh_encoding::Error),
+ Encoding(#[from] encoding::Error),
}
impl agent::key::Signature for Signature {
@@ -190,7 +187,7 @@ pub mod thrussh {
#[error("the public key parsed was not 32 bits in length")]
Invalid,
#[error(transparent)]
- Encoding(#[from] lnk_thrussh_encoding::Error),
+ Encoding(#[from] encoding::Error),
}
impl agent::key::Public for PublicKey {
@@ -227,7 +224,7 @@ pub mod thrussh {
#[derive(Debug, Error)]
pub enum SigningKeyError {
#[error(transparent)]
- Encoding(#[from] lnk_thrussh_encoding::Error),
+ Encoding(#[from] encoding::Error),
#[error(transparent)]
Ed25519(#[from] ed25519_zebra::Error),
}
@@ -299,7 +296,7 @@ mod tests {
/// implementations must be byte-for-byte equal.
///
/// All combinatorial pairs of `Signer` implementations must pass this.
- async fn compat(signer1: S1, signer2: S2)
+ fn compat(signer1: S1, signer2: S2)
where
S1: Signer,
S2: Signer,
@@ -309,12 +306,11 @@ mod tests {
{
assert_eq!(signer1.public_key(), signer2.public_key());
assert_eq!(
- signer1.sign(MESSAGE).await.unwrap(),
- signer2.sign(MESSAGE).await.unwrap()
+ signer1.sign(MESSAGE).unwrap(),
+ signer2.sign(MESSAGE).unwrap()
);
}
- #[async_trait]
impl Signer for sodiumoxide::crypto::sign::ed25519::SecretKey {
type Error = Infallible;
@@ -322,14 +318,13 @@ mod tests {
PublicKey(self.public_key().0)
}
- async fn sign(&self, data: &[u8]) -> Result {
+ fn sign(&self, data: &[u8]) -> Result {
Ok(Signature(
sodiumoxide::crypto::sign::ed25519::sign_detached(data, self).to_bytes(),
))
}
}
- #[async_trait]
impl Signer for ed25519_dalek::Keypair {
type Error = Infallible;
@@ -337,13 +332,13 @@ mod tests {
PublicKey(self.public.to_bytes())
}
- async fn sign(&self, data: &[u8]) -> Result {
+ fn sign(&self, data: &[u8]) -> Result {
Ok(Signature(DalekSigner::sign(self, data).to_bytes()))
}
}
- #[tokio::test]
- async fn compat_sodium_dalek() {
+ #[test]
+ fn compat_sodium_dalek() {
sodiumoxide::init().unwrap();
let (_, sodium) = sodium::gen_keypair();
@@ -353,11 +348,11 @@ mod tests {
ed25519_dalek::Keypair { secret, public }
};
- compat(sodium, dalek).await
+ compat(sodium, dalek)
}
- #[tokio::test]
- async fn compat_zebra_dalek() {
+ #[test]
+ fn compat_zebra_dalek() {
use rand::rngs::OsRng;
let csprng = OsRng {};
@@ -369,6 +364,6 @@ mod tests {
ed25519_dalek::Keypair { secret, public }
};
- compat(zebra, dalek).await
+ compat(zebra, dalek)
}
}
diff --git a/src/sign/ssh.rs b/src/sign/ssh.rs
index 4018462..88a13e3 100644
--- a/src/sign/ssh.rs
+++ b/src/sign/ssh.rs
@@ -16,12 +16,11 @@
// along with this program. If not, see .
use std::path::PathBuf;
+use std::sync::Mutex;
-use futures::lock::Mutex;
-use lnk_thrussh_agent::{
- client::{self, AgentClient, ClientStream},
- Constraint,
-};
+use agent::client::Error::PoisonError;
+use agent::client::{self, AgentClient, ClientStream};
+use agent::Constraint;
pub use super::ed25519;
@@ -100,16 +99,11 @@ impl SshAgent {
/// This is to leave the async runtime agnostic. The different
/// implementations for streams can be found at [`ClientStream`]'s
/// documentation.
- pub async fn connect(
- &self,
- ) -> Result, error::Connect>
+ pub fn connect(&self) -> Result, error::Connect>
where
S: ClientStream + Unpin,
{
- let client = self
- .client::()
- .await
- .map(|client| Mutex::new(Some(client)))?;
+ let client = self.client::().map(|client| Mutex::new(Some(client)))?;
Ok(Signer {
rfc: self.key,
@@ -117,13 +111,13 @@ impl SshAgent {
})
}
- async fn client(&self) -> Result, client::Error>
+ fn client(&self) -> Result, client::Error>
where
S: ClientStream + Unpin,
{
match &self.path {
- None => Ok(S::connect_env().await?),
- Some(path) => Ok(S::connect_uds(path).await?),
+ None => Ok(S::connect_env()?),
+ Some(path) => Ok(S::connect_uds(path)?),
}
}
}
@@ -148,7 +142,7 @@ struct Signer {
/// The stream parameter `S` needs to be chosen when calling this function. This
/// is to leave the async runtime agnostic. The different implementations for
/// streams can be found at [`ClientStream`]'s documentation.
-pub async fn add_key(
+pub fn add_key(
agent: &SshAgent,
secret: ed25519_zebra::SigningKey,
constraints: &[Constraint],
@@ -156,35 +150,31 @@ pub async fn add_key(
where
S: ClientStream + Unpin,
{
- let mut client = agent.client::().await?;
+ let mut client = agent.client::()?;
let secret = ed25519::SigningKey::from(secret);
- client.add_identity(&secret, constraints).await?;
+ client.add_identity(&secret, constraints)?;
Ok(())
}
-pub async fn remove_key(
- agent: &SshAgent,
- key: &ed25519::PublicKey,
-) -> Result<(), error::RemoveKey>
+pub fn remove_key(agent: &SshAgent, key: &ed25519::PublicKey) -> Result<(), error::RemoveKey>
where
S: ClientStream + Unpin,
{
- let mut client = agent.client::().await?;
- client.remove_identity(key).await?;
+ let mut client = agent.client::()?;
+ client.remove_identity(key)?;
Ok(())
}
-pub async fn list_keys(agent: &SshAgent) -> Result, error::ListKeys>
+pub fn list_keys(agent: &SshAgent) -> Result, error::ListKeys>
where
S: ClientStream + Unpin,
{
- let mut client = agent.client::().await?;
- let keys = client.request_identities().await?;
+ let mut client = agent.client::()?;
+ let keys = client.request_identities()?;
Ok(keys)
}
-#[async_trait]
impl ed25519::Signer for Signer
where
S: ClientStream + Unpin,
@@ -195,14 +185,14 @@ where
self.rfc
}
- async fn sign(&self, data: &[u8]) -> Result {
- let mut guard = self.client.lock().await;
+ fn sign(&self, data: &[u8]) -> Result {
+ let mut guard = self.client.lock().map_err(|_| PoisonError)?;
let client = match guard.take() {
- None => ClientStream::connect_env().await?,
+ None => ClientStream::connect_env()?,
Some(client) => client,
};
- let (client, sig) = client.sign_request_signature(&self.rfc, data).await;
+ let (client, sig) = client.sign_request_signature(&self.rfc, data);
*guard = Some(client);
Ok(sig?)
}