(general) refactor
This commit is contained in:
parent
d6edfc681b
commit
26d7e8cfd8
|
@ -10,9 +10,13 @@ use async_std::io::{Read, Write};
|
|||
use async_std::net::TcpStream;
|
||||
|
||||
use kuska_handshake::async_std::{handshake_client, BoxStream};
|
||||
use kuska_ssb::api::{
|
||||
ApiHelper, CreateHistoryStreamArgs, CreateStreamArgs, LatestUserMessage, WhoAmI,
|
||||
};
|
||||
use kuska_ssb::discovery::ssb_net_id;
|
||||
use kuska_ssb::feed::{is_privatebox, privatebox_decipher, Feed, Message};
|
||||
use kuska_ssb::patchwork::*;
|
||||
use kuska_ssb::patchwork::{ApiHelper, LatestUserMessage, WhoAmI};
|
||||
use kuska_ssb::keystore::from_patchwork_local;
|
||||
use kuska_ssb::keystore::OwnedIdentity;
|
||||
use kuska_ssb::rpc::{RecvMsg, RequestNo, RpcStream};
|
||||
|
||||
type AnyResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
@ -116,8 +120,7 @@ async fn main() -> AnyResult<()> {
|
|||
env_logger::init();
|
||||
log::set_max_level(log::LevelFilter::max());
|
||||
|
||||
let IdentitySecret { pk, sk, .. } =
|
||||
IdentitySecret::from_local_config().expect("read local secret");
|
||||
let OwnedIdentity { pk, sk, .. } = from_patchwork_local().expect("read local secret");
|
||||
|
||||
let mut socket = TcpStream::connect("127.0.0.1:8080").await?;
|
||||
let handshake = handshake_client(&mut socket, ssb_net_id(), pk, sk.clone(), pk).await?;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
mod api;
|
||||
mod config;
|
||||
mod error;
|
||||
mod helper;
|
||||
pub mod msgs;
|
||||
pub mod pubs;
|
||||
|
||||
pub use api::{
|
||||
pub use error::{Error, Result};
|
||||
pub use helper::{
|
||||
ApiHelper, ApiMethod, CreateHistoryStreamArgs, CreateStreamArgs, LatestUserMessage, WhoAmI,
|
||||
};
|
||||
pub use config::{ssb_net_id, IdentitySecret};
|
||||
pub use error::{Error, Result};
|
|
@ -2,4 +2,6 @@ mod error;
|
|||
mod sodium;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
pub use sodium::{ToSodiumObject, ToSsbId};
|
||||
pub use sodium::{
|
||||
ToSodiumObject, ToSsbId, CURVE_ED25519_SUFFIX, ED25519_SIGNATURE_SUFFIX, SHA256_SUFFIX,
|
||||
};
|
||||
|
|
|
@ -4,9 +4,9 @@ use sodiumoxide::crypto::sign::ed25519;
|
|||
|
||||
use super::error::{Error, Result};
|
||||
|
||||
const CURVE_ED25519_SUFFIX: &str = ".ed25519";
|
||||
const ED25519_SIGNATURE_SUFFIX: &str = ".sig.ed25519";
|
||||
const SHA256_SUFFIX: &str = ".sha256";
|
||||
pub const CURVE_ED25519_SUFFIX: &str = ".ed25519";
|
||||
pub const ED25519_SIGNATURE_SUFFIX: &str = ".sig.ed25519";
|
||||
pub const SHA256_SUFFIX: &str = ".sha256";
|
||||
|
||||
pub trait ToSodiumObject {
|
||||
fn to_ed25519_pk(&self) -> Result<ed25519::PublicKey>;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
ParseInt(std::num::ParseIntError),
|
||||
InvalidInviteCode,
|
||||
CryptoFormat(crate::crypto::Error),
|
||||
}
|
||||
|
||||
impl From<crate::crypto::Error> for Error {
|
||||
fn from(err: crate::crypto::Error) -> Self {
|
||||
Error::CryptoFormat(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::num::ParseIntError> for Error {
|
||||
fn from(err: std::num::ParseIntError) -> Self {
|
||||
Error::ParseInt(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
@ -0,0 +1,6 @@
|
|||
mod error;
|
||||
mod network;
|
||||
mod pubs;
|
||||
|
||||
pub use network::ssb_net_id;
|
||||
pub use pubs::Invite;
|
|
@ -0,0 +1,6 @@
|
|||
use sodiumoxide::crypto::auth;
|
||||
|
||||
pub const SSB_NET_ID: &str = "d4a1cb88a66f02f8db635ce26441cc5dac1b08420ceaac230839b755845a9ffb";
|
||||
pub fn ssb_net_id() -> auth::Key {
|
||||
auth::Key::from_slice(&hex::decode(SSB_NET_ID).unwrap()).unwrap()
|
||||
}
|
|
@ -7,7 +7,7 @@ use sodiumoxide::crypto::sign::ed25519;
|
|||
use super::error::{Error, Result};
|
||||
use super::{ssb_sha256, stringify_json};
|
||||
use crate::crypto::ToSodiumObject;
|
||||
use crate::patchwork::IdentitySecret;
|
||||
use crate::keystore::OwnedIdentity;
|
||||
use sodiumoxide::crypto::hash::sha256;
|
||||
|
||||
const MSG_PREVIOUS: &str = "previous";
|
||||
|
@ -58,7 +58,7 @@ pub struct Message {
|
|||
}
|
||||
|
||||
impl Message {
|
||||
pub fn sign(prev: Option<&Message>, identity: &IdentitySecret, content: Value) -> Result<Self> {
|
||||
pub fn sign(prev: Option<&Message>, identity: &OwnedIdentity, content: Value) -> Result<Self> {
|
||||
let mut value: serde_json::Map<String, Value> = serde_json::Map::new();
|
||||
if let Some(prev) = prev {
|
||||
value.insert(
|
||||
|
@ -206,7 +206,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_sign_verify() -> Result<()> {
|
||||
let content = Value::String("thistest".to_string());
|
||||
let id = IdentitySecret::new();
|
||||
let id = OwnedIdentity::new();
|
||||
let msg1 = Message::sign(None, &id, content.clone())?.to_string();
|
||||
let msg1 = Message::from_str(&msg1)?;
|
||||
let msg2 = Message::sign(Some(&msg1), &id, content)?.to_string();
|
||||
|
|
|
@ -125,7 +125,7 @@ fn decipher(ciphertext: &[u8], sk: &SecretKey) -> Result<Option<Vec<u8>>> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::patchwork::IdentitySecret;
|
||||
use crate::keystore::OwnedIdentity;
|
||||
|
||||
#[test]
|
||||
fn test_msg_cipher_to_one() -> Result<()> {
|
||||
|
@ -139,7 +139,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_msg_cipher_to_one_helper() -> Result<()> {
|
||||
let id = IdentitySecret::new();
|
||||
let id = OwnedIdentity::new();
|
||||
let plaintext = "holar";
|
||||
let ciphertext = privatebox_cipher(plaintext, &[&id.id])?;
|
||||
assert_eq!(is_privatebox(&ciphertext), true);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
HomeNotFound,
|
||||
InvalidConfig,
|
||||
CryptoFormat(crate::crypto::Error),
|
||||
Io(std::io::Error),
|
||||
}
|
||||
impl From<crate::crypto::Error> for Error {
|
||||
fn from(err: crate::crypto::Error) -> Self {
|
||||
Error::CryptoFormat(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
|
@ -0,0 +1,20 @@
|
|||
use crate::crypto::CURVE_ED25519_SUFFIX;
|
||||
use sodiumoxide::crypto::sign::ed25519;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OwnedIdentity {
|
||||
pub id: String,
|
||||
pub pk: ed25519::PublicKey,
|
||||
pub sk: ed25519::SecretKey,
|
||||
}
|
||||
|
||||
impl OwnedIdentity {
|
||||
pub fn new() -> OwnedIdentity {
|
||||
let (pk, sk) = ed25519::gen_keypair();
|
||||
OwnedIdentity {
|
||||
pk,
|
||||
sk,
|
||||
id: format!("@{}{}", base64::encode(&pk), CURVE_ED25519_SUFFIX),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
mod error;
|
||||
mod identity;
|
||||
pub mod patchwork;
|
||||
|
||||
pub use identity::OwnedIdentity;
|
||||
pub use patchwork::{from_patchwork_config, from_patchwork_local};
|
|
@ -0,0 +1,53 @@
|
|||
use std::io;
|
||||
use std::string::ToString;
|
||||
|
||||
use crate::crypto::ToSodiumObject;
|
||||
|
||||
use super::error::{Error, Result};
|
||||
use super::OwnedIdentity;
|
||||
|
||||
pub const CURVE_ED25519: &str = "ed25519";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct JsonSSBSecret {
|
||||
id: String,
|
||||
curve: String,
|
||||
public: String,
|
||||
private: String,
|
||||
}
|
||||
|
||||
fn to_ioerr<T: ToString>(err: T) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, err.to_string())
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
|
||||
pub fn from_patchwork_local() -> Result<OwnedIdentity> {
|
||||
let home_dir = dirs::home_dir().ok_or(Error::HomeNotFound)?;
|
||||
let local_key_file = format!("{}/.ssb/secret", home_dir.to_string_lossy());
|
||||
let content = std::fs::read_to_string(local_key_file)?;
|
||||
Ok(from_patchwork_config(content)?)
|
||||
}
|
||||
|
||||
pub fn from_patchwork_config<T: AsRef<str>>(config: T) -> Result<OwnedIdentity> {
|
||||
// strip all comments
|
||||
let json = config
|
||||
.as_ref()
|
||||
.lines()
|
||||
.filter(|line| !line.starts_with('#'))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
|
||||
// parse json
|
||||
let secret: JsonSSBSecret = serde_json::from_str(json.as_ref()).map_err(to_ioerr)?;
|
||||
|
||||
if secret.curve != CURVE_ED25519 {
|
||||
return Err(Error::InvalidConfig);
|
||||
}
|
||||
|
||||
Ok(OwnedIdentity {
|
||||
id: secret.id,
|
||||
pk: secret.public.to_ed25519_pk()?,
|
||||
sk: secret.private.to_ed25519_sk()?,
|
||||
})
|
||||
}
|
|
@ -5,7 +5,9 @@ extern crate serde;
|
|||
extern crate async_std;
|
||||
extern crate serde_json;
|
||||
|
||||
pub mod api;
|
||||
pub mod crypto;
|
||||
pub mod discovery;
|
||||
pub mod feed;
|
||||
pub mod patchwork;
|
||||
pub mod keystore;
|
||||
pub mod rpc;
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
use std::io;
|
||||
use std::string::ToString;
|
||||
|
||||
use sodiumoxide::crypto::auth;
|
||||
use sodiumoxide::crypto::sign::ed25519;
|
||||
|
||||
use crate::crypto::ToSodiumObject;
|
||||
|
||||
use super::error::{Error, Result};
|
||||
|
||||
const CURVE_ED25519: &str = "ed25519";
|
||||
pub const SSB_NET_ID: &str = "d4a1cb88a66f02f8db635ce26441cc5dac1b08420ceaac230839b755845a9ffb";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IdentitySecret {
|
||||
pub id: String,
|
||||
pub pk: ed25519::PublicKey,
|
||||
pub sk: ed25519::SecretKey,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct JsonSSBSecret {
|
||||
id: String,
|
||||
curve: String,
|
||||
public: String,
|
||||
private: String,
|
||||
}
|
||||
|
||||
pub fn ssb_net_id() -> auth::Key {
|
||||
auth::Key::from_slice(&hex::decode(SSB_NET_ID).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
fn to_ioerr<T: ToString>(err: T) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, err.to_string())
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl IdentitySecret {
|
||||
pub fn new() -> IdentitySecret {
|
||||
let (pk, sk) = ed25519::gen_keypair();
|
||||
IdentitySecret {
|
||||
pk,
|
||||
sk,
|
||||
id: format!("@{}.{}", base64::encode(&pk), CURVE_ED25519),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_local_config() -> Result<IdentitySecret> {
|
||||
let home_dir = dirs::home_dir().ok_or(Error::HomeNotFound)?;
|
||||
let local_key_file = format!("{}/.ssb/secret", home_dir.to_string_lossy());
|
||||
let content = std::fs::read_to_string(local_key_file)?;
|
||||
Ok(IdentitySecret::from_config(content)?)
|
||||
}
|
||||
|
||||
pub fn from_config<T: AsRef<str>>(config: T) -> Result<IdentitySecret> {
|
||||
// strip all comments
|
||||
let json = config
|
||||
.as_ref()
|
||||
.lines()
|
||||
.filter(|line| !line.starts_with('#'))
|
||||
.collect::<Vec<_>>()
|
||||
.join("");
|
||||
|
||||
// parse json
|
||||
let secret: JsonSSBSecret = serde_json::from_str(json.as_ref()).map_err(to_ioerr)?;
|
||||
|
||||
if secret.curve != CURVE_ED25519 {
|
||||
return Err(Error::InvalidConfig);
|
||||
}
|
||||
|
||||
Ok(IdentitySecret {
|
||||
id: secret.id,
|
||||
pk: secret.public.to_ed25519_pk()?,
|
||||
sk: secret.private.to_ed25519_sk()?,
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue