-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into xla/rfc-p2p-node
- Loading branch information
Showing
209 changed files
with
4,729 additions
and
1,074 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[package] | ||
name = "link-clib" | ||
version = "0.1.0" | ||
authors = ["The Radicle Team <[email protected]>"] | ||
edition = "2018" | ||
license = "GPL-3.0-or-later" | ||
|
||
[lib] | ||
doctest = true | ||
test = false | ||
|
||
[features] | ||
unsafe = [] | ||
|
||
[dependencies] | ||
serde_json = "1.0" | ||
serde = "1.0" | ||
thiserror = "1.0" | ||
|
||
[dependencies.librad] | ||
path = "../librad" | ||
|
||
[dependencies.minicbor] | ||
version = "0.9.1" | ||
features = ["std"] | ||
|
||
[dependencies.thrussh-agent] | ||
git = "https://github.com/FintanH/thrussh" | ||
branch = "generic-agent" | ||
default-features = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# CLIB | ||
|
||
When a CLI needs a LIB, one gets a CLIB. | ||
|
||
This package provides the common data types and functions that can be | ||
used across the different set of CLI packages. | ||
|
||
* `clib::keys` - common functions for setting up of and retrival from the secret key | ||
storage. | ||
* `clib::ser` - serialization formats required for CLI output. | ||
* `clib::storage` - common functions for setting up read-only and | ||
read-write storage. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Copyright © 2021 The Radicle Link Contributors | ||
// | ||
// This file is part of radicle-link, distributed under the GPLv3 with Radicle | ||
// Linking Exception. For full terms see the included LICENSE file. | ||
|
||
use std::sync::Arc; | ||
|
||
use thiserror::Error; | ||
use thrussh_agent::client::ClientStream; | ||
|
||
use librad::{ | ||
crypto::{ | ||
keystore::{ | ||
crypto::{Crypto, KdfParams, Pwhash, SecretBoxError}, | ||
file, | ||
pinentry::Prompt, | ||
sign::ssh::{self, SshAgent}, | ||
FileStorage, | ||
Keystore as _, | ||
}, | ||
BoxedSigner, | ||
IntoSecretKeyError, | ||
SomeSigner, | ||
}, | ||
git::storage::ReadOnly, | ||
profile::Profile, | ||
PublicKey, | ||
SecretKey, | ||
}; | ||
|
||
/// The filename for storing the secret key. | ||
pub const LIBRAD_KEY_FILE: &str = "librad.key"; | ||
|
||
#[derive(Debug, Error)] | ||
pub enum Error { | ||
#[error(transparent)] | ||
File(#[from] file::Error<SecretBoxError<std::io::Error>, IntoSecretKeyError>), | ||
#[error(transparent)] | ||
SshConnect(#[from] ssh::error::Connect), | ||
} | ||
|
||
/// Create a [`Prompt`] for unlocking the key storage. | ||
pub fn prompt() -> Pwhash<Prompt<'static>> { | ||
let prompt = Prompt::new("please enter your passphrase: "); | ||
Pwhash::new(prompt, KdfParams::recommended()) | ||
} | ||
|
||
/// Create a [`Prompt`] for unlocking the key storage. | ||
/// | ||
/// # Safety | ||
/// | ||
/// The encryption of the file store will be weak but fast. So this not intended | ||
/// for production use. | ||
#[cfg(feature = "unsafe")] | ||
pub fn unsafe_prompt() -> Pwhash<Prompt<'static>> { | ||
use librad::crypto::keystore::crypto::KDF_PARAMS_TEST; | ||
|
||
let prompt = Prompt::new("please enter your passphrase: "); | ||
Pwhash::new(prompt, *KDF_PARAMS_TEST) | ||
} | ||
|
||
/// Create a [`FileStorage`] for [`SecretKey`]s. | ||
pub fn file_storage<C>(profile: &Profile, crypto: C) -> FileStorage<C, PublicKey, SecretKey, ()> | ||
where | ||
C: Crypto, | ||
{ | ||
FileStorage::new(&profile.paths().keys_dir().join(LIBRAD_KEY_FILE), crypto) | ||
} | ||
|
||
/// Get the signer from the file store, decrypting the secret key by asking for | ||
/// a passphrase via a prompt. | ||
pub fn signer_prompt(profile: &Profile) -> Result<BoxedSigner, Error> { | ||
let store = file_storage(profile, prompt()); | ||
let key = store.get_key()?.secret_key; | ||
Ok(key.into()) | ||
} | ||
|
||
pub async fn signer_ssh<S>(profile: &Profile) -> Result<BoxedSigner, Error> | ||
where | ||
S: ClientStream + Unpin + 'static, | ||
{ | ||
let storage = ReadOnly::open(profile.paths()).unwrap(); | ||
let peer_id = storage.peer_id(); | ||
let agent = SshAgent::new((**peer_id).into()); | ||
let signer = agent.connect::<S>().await?; | ||
Ok(SomeSigner { | ||
signer: Arc::new(signer), | ||
} | ||
.into()) | ||
} | ||
|
||
/// Get the signer from the file store, decrypting the secret key by asking for | ||
/// a passphrase via a prompt. | ||
/// | ||
/// # Safety | ||
/// | ||
/// The encryption of the file store will be weak but fast. So this not intended | ||
/// for production use. | ||
#[cfg(feature = "unsafe")] | ||
pub fn unsafe_signer_prompt(profile: &Profile) -> Result<BoxedSigner, Error> { | ||
let store = file_storage(profile, unsafe_prompt()); | ||
let key = store.get_key()?.secret_key; | ||
Ok(key.into()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
// Copyright © 2019-2020 The Radicle Foundation <[email protected]> | ||
// Copyright © 2021 The Radicle Link Contributors | ||
// | ||
// This file is part of radicle-link, distributed under the GPLv3 with Radicle | ||
// Linking Exception. For full terms see the included LICENSE file. | ||
|
||
pub mod canonical; | ||
pub mod keys; | ||
pub mod ser; | ||
pub mod storage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright © 2021 The Radicle Link Contributors | ||
// | ||
// This file is part of radicle-link, distributed under the GPLv3 with Radicle | ||
// Linking Exception. For full terms see the included LICENSE file. | ||
|
||
use std::{fmt, str::FromStr}; | ||
|
||
use thiserror::Error; | ||
|
||
use minicbor::Encode; | ||
use serde::Serialize; | ||
|
||
#[derive(Debug, Error)] | ||
pub enum Error { | ||
#[error(transparent)] | ||
Json(#[from] serde_json::Error), | ||
#[error(transparent)] | ||
Cbor(#[from] minicbor::encode::Error<std::io::Error>), | ||
#[error(transparent)] | ||
Utf8(#[from] std::string::FromUtf8Error), | ||
} | ||
|
||
/// An enumeration of the formats the CLI can output. Note that since any of | ||
/// these formats can be used, the corresponding data type needs to implement | ||
/// the required traits. | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum Format { | ||
/// Requires the data type to implement [`Serialize`]. | ||
Json, | ||
/// Requires the data type to implement [`Encode`]. | ||
Cbor, | ||
} | ||
|
||
impl fmt::Display for Format { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
Self::Json => write!(f, "json"), | ||
Self::Cbor => write!(f, "cbor"), | ||
} | ||
} | ||
} | ||
|
||
impl FromStr for Format { | ||
type Err = &'static str; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
match s { | ||
"json" => Ok(Self::Json), | ||
"cbor" => Ok(Self::Cbor), | ||
_ => Err("unknown format type"), | ||
} | ||
} | ||
} | ||
|
||
impl Format { | ||
/// Serialize the `val` to a `String`. | ||
pub fn format<T>(&self, val: &T) -> Result<String, Error> | ||
where | ||
T: Serialize + Encode, | ||
{ | ||
match self { | ||
Self::Json => Ok(serde_json::to_string(val)?), | ||
Self::Cbor => Ok(String::from_utf8(minicbor::to_vec(val)?)?), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright © 2021 The Radicle Link Contributors | ||
// | ||
// This file is part of radicle-link, distributed under the GPLv3 with Radicle | ||
// Linking Exception. For full terms see the included LICENSE file. | ||
|
||
use thiserror::Error; | ||
|
||
use librad::{ | ||
crypto::BoxedSigner, | ||
git::storage::{error, read, ReadOnly, Storage}, | ||
profile::Profile, | ||
}; | ||
|
||
use super::keys; | ||
|
||
#[derive(Debug, Error)] | ||
pub enum Error { | ||
#[error(transparent)] | ||
ReadInit(#[from] read::error::Init), | ||
#[error(transparent)] | ||
ReadWriteInit(#[from] error::Init), | ||
#[error(transparent)] | ||
Keys(#[from] super::keys::Error), | ||
} | ||
|
||
/// Intialise a [`ReadOnly`] storage. | ||
pub fn read_only(profile: &Profile) -> Result<ReadOnly, Error> { | ||
let paths = profile.paths(); | ||
Ok(ReadOnly::open(paths)?) | ||
} | ||
|
||
pub mod prompt { | ||
use super::*; | ||
|
||
/// Initialise [`Storage`]. | ||
/// | ||
/// The decryption will happen by prompting the person for their passphrase | ||
/// at the command line. | ||
pub fn storage(profile: &Profile) -> Result<(BoxedSigner, Storage), Error> { | ||
let paths = profile.paths(); | ||
let signer = keys::signer_prompt(profile)?; | ||
Ok((signer.clone(), Storage::open(paths, signer)?)) | ||
} | ||
} | ||
|
||
pub mod ssh { | ||
use thrussh_agent::client::ClientStream; | ||
|
||
use super::*; | ||
|
||
/// Initialise [`Storage`]. | ||
/// | ||
/// The signing key will be retrieved from the ssh-agent. If the key was not | ||
/// added to the agent then this result in an error. | ||
pub async fn storage<S>(profile: &Profile) -> Result<(BoxedSigner, Storage), Error> | ||
where | ||
S: ClientStream + Unpin + 'static, | ||
{ | ||
let paths = profile.paths(); | ||
let signer = keys::signer_ssh::<S>(profile).await?; | ||
Ok((signer.clone(), Storage::open(paths, signer)?)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.