Initial Commit
This commit is contained in:
commit
0bdaa94dd5
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
*.profile
|
||||||
|
*.sqlite
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,2 @@
|
||||||
|
[workspace]
|
||||||
|
members=["./niwl", "niwl-client","niwl-server"]
|
|
@ -0,0 +1,35 @@
|
||||||
|
# niwl - a prototype system for metadata resistant notifications
|
||||||
|
|
||||||
|
**niwl** (_/nɪu̯l/_) - fog, mist or haze (Welsh).
|
||||||
|
|
||||||
|
Privacy preserving applications often require a mechanism for providing notifications to parties that an
|
||||||
|
event has happened e.g. a new group message, a payment etc.
|
||||||
|
|
||||||
|
**niwl** provides a set of libraries, clients and servers to provide this in a metadata resistant, bandwidth
|
||||||
|
efficient way based on [fuzzytags](https://crates.io/crates/fuzzytags).
|
||||||
|
|
||||||
|
# Overview
|
||||||
|
|
||||||
|
**niwl-server** provides a web server with a json API for posting new tags and querying the tags database.
|
||||||
|
|
||||||
|
**niwl-client** provides a command-line application for managing secrets, tagging keys of parties and posting / querying
|
||||||
|
for new tags.
|
||||||
|
|
||||||
|
For a more detailed overview please check out each individual crate.
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
|
||||||
|
niwl-client alice.profile generate "alice"
|
||||||
|
Tagging Key: auaaaaaaaaaaaylmnfrwkgaaaaaaaaaaadlbii3y7r6vmc7upbxa4myohaqmr5xl22bdxeed4abkotnovlmakzdo5stq2ibtjewm4rnkgzqwglrt72zfeyomvdpxqnu4ci4hwebyiseyn7pqfxypnvef7a3flu2hby7gdluh6wocxa5mvmimi2xorydcqaca2p2aevmue4cwyxnw2h7fkps7e6grgls66zgohbnwjibt6nlsdqjbrdjrzlsc3at3f43jyniz2i67ng6xdty5pr3elzedhjlvefhd6pjfc7g4owrz3dkq5xt2hhh3vvctkywqkcwriguayyx3pourepfs7s76bekrjgcjgj6zyid3ixmeh5ewqhkhxhzevf3uogvscxtpbksaclhccht7pj2fungnztfghshd6lsmegmysiiuyav6schtmyxmne2vfi4j4cxllm2crj3cqofsxjlxov3ms2zgtjzyxtubwtnwspc4jhijz4kufm6r3qkhpcyibx7ulceckx2a4g23tkhtgshtxq3fga7ptbhq5gcebwiq6cfolt4zbn72gbmtc43nw63vd4soxf4bnbhrykaoudfs3mh6laap6iwbngo4ylocs4w5hgd4t22yrtrmhkewsc2eytsosxyhaiuaww24mszscsojm2bcoldpokwuxbnfx7lgnzdcuae3y55zoen47noltjqgcpuqzl6upjcvutgvvro6nu2uyl36rcqmw2by2e45uqtsdnolbispxv2e5aeeuz5gytuf5f5e44nldmywtmxkfqfljml5gye6tj3qswmz6d36f2k4v7fbiuv7jzplzmghsgxvmq7fo3qp655obysbggkd3iqpk76p5umbpc2tk64oiklrponulkqf3v337aaxyn6nvzz2rpj3o374tftscsr7oilzkah63xpe2jc45dd4fuwxvlg3c33zgkminemqqfz7jdjtnawy77vpxxgnosbw4fwadhhggofmipboiqo55xygojdnfdkuzgfe4455sdqv5ytzdl55yuzlbdgsnwtgnfakmoyjhblzbuwohq7esayfxe72yqgci5dappiad7bc3ikfsydv5b7stifajkxuosu345upxg2hwzajj4uu7lxaykxgo22pslkxnidaoyevn3gamx63ec4fkhzguhbu6jt7pukr4rpafx24vd622f5wzux4corlxthjuhi2ewiu6laxx3aqfkzv2d2hhqzsac25vycmmxy
|
||||||
|
niwl-client bob.profile generate "bob"
|
||||||
|
Tagging Key: auaaaaaaaaaaaylmnfrwkgaaaaaaaaaaadlbii3y7r6vmc7upbxa4myohaqmr5xl22bdxeed4abkotnovlmakzdo5stq2ibtjewm4rnkgzqwglrt72zfeyomvdpxqnu4ci4hwebyiseyn7pqfxypnvef7a3flu2hby7gdluh6wocxa5mvmimi2xorydcqaca2p2aevmue4cwyxnw2h7fkps7e6grgls66zgohbnwjibt6nlsdqjbrdjrzlsc3at3f43jyniz2i67ng6xdty5pr3elzedhjlvefhd6pjfc7g4owrz3dkq5xt2hhh3vvctkywqkcwriguayyx3pourepfs7s76bekrjgcjgj6zyid3ixmeh5ewqhkhxhzevf3uogvscxtpbksaclhccht7pj2fungnztfghshd6lsmegmysiiuyav6schtmyxmne2vfi4j4cxllm2crj3cqofsxjlxov3ms2zgtjzyxtubwtnwspc4jhijz4kufm6r3qkhpcyibx7ulceckx2a4g23tkhtgshtxq3fga7ptbhq5gcebwiq6cfolt4zbn72gbmtc43nw63vd4soxf4bnbhrykaoudfs3mh6laap6iwbngo4ylocs4w5hgd4t22yrtrmhkewsc2eytsosxyhaiuaww24mszscsojm2bcoldpokwuxbnfx7lgnzdcuae3y55zoen47noltjqgcpuqzl6upjcvutgvvro6nu2uyl36rcqmw2by2e45uqtsdnolbispxv2e5aeeuz5gytuf5f5e44nldmywtmxkfqfljml5gye6tj3qswmz6d36f2k4v7fbiuv7jzplzmghsgxvmq7fo3qp655obysbggkd3iqpk76p5umbpc2tk64oiklrponulkqf3v337aaxyn6nvzz2rpj3o374tftscsr7oilzkah63xpe2jc45dd4fuwxvlg3c33zgkminemqqfz7jdjtnawy77vpxxgnosbw4fwadhhggofmipboiqo55xygojdnfdkuzgfe4455sdqv5ytzdl55yuzlbdgsnwtgnfakmoyjhblzbuwohq7esayfxe72yqgci5dappiad7bc3ikfsydv5b7stifajkxuosu345upxg2hwzajj4uu7lxaykxgo22pslkxnidaoyevn3gamx63ec4fkhzguhbu6jt7pukr4rpafx24vd622f5wzux4corlxthjuhi2ewiu6laxx3aqfkzv2d2hhqzsac25vycmmxy
|
||||||
|
|
||||||
|
niwl-client alice.profile import-tagging-key amaaaaaaaaaaaytpmimaaaaaaaaaaafaukgy7543bcnjyq4jbthaovnfxtdnya3jajmbwa4t5gmihqgudbta4nzigrhzirkekers23ng2lr4zbjspthybajjj7vbwn6wnied27e2jvuipqbinru2q7eumgbt62spztz3rpslymv4iwsujozb7ylcfr7ugroilpgxzrjniussojm4q3kun247o4kqjzcrec4ohcuiyaiinourb7h7j4qjv4ne46xhnptwsfjr5s7yz2igqsbpvrqeiy5u6khmxwpi2jzxrnk5qlixewjcbe3zzy4qpxnl7ybdds6tld522amonc2dxncff2ihribsdnd5fc5dozqu2eqqxqmyvnd5pdngozhqikdc6ovj4uzf2ttabckbr4sim6z3fkl7kd5wqjjdaosahqsi67gy47q3vd3ubtu5btx2lmgkmyzm2wuupvwxxvc65lcxghm43bu4yah76jb3u36kg4nzdemuxewxcswofymuvdxh24uqyyhn7ymlr6mnuuk6g6acy4bcu7gsiacu3am6qwfve7s5wckgbaqc6veafbzynjmv6wubkleas2ghkirnl3pdznf37pyz62hkjssiqzqlduhkcyghdkdzccrtnesdkob447zlxaj2qz24chuxpy7hkffx64fi7aqzkpujifagrkcxvroq43wl2hme7udqcwpdjdtqm7yhnnanazuahtqlvf3ux7kvmidevorrgaiephptm7qgk7ezw6aa7o3fjyra7m3xknbmpniqa4dnwg44cfgbj2ln6kcecgat4d5cokabzk64jjhfq4m6upoptya4bjy2chdhged4jsqvp646u4klk5zk2fmhgf7l365k2g4z4i2u2dveajldebgnwc4esdrmequawk5sk6oskurfsuj6i4v7jzeqcd5hbujllka4dq3cn3hidx67jspqefnwj6yr7fvwjvvtjo3ri5wcqqd3m5kjrmhjuxbho7sl5xnhzntdtha7ldwml6xkwg3x7scsmhikvkrzfenggxccunpyp6cmsslblfbdrwvl4qurnrdg7wqtlgy6pfhjrqwqej26e7ddxwax34fagkgqksupdutbaq2juvicn7rq3xrxs6bi6a2ozdfdyfbtun5ckz6ln2jxyu254appisier35e3d6nmicywn5p7m32cvcct3ilub4ovk4jpuizegyudyrcgoud2rmuyei6fdgrbvtdqv7gqy6a
|
||||||
|
Got: bob: 4211f14667b425649390eee099c4e84bf758a1a4e6375e23b50c6de347c25654
|
||||||
|
|
||||||
|
niwl-client alice.profile tag-and-send bob
|
||||||
|
Tag for bob 7e441275a5c3f88606c34c3451a44eaeaa025680cfcb3d9db53992501cc22134 4f7a7f961bc19297fee98da5f8601aa8373429b80b10c55dbe8116aa8c497a0e 71d8da
|
||||||
|
|
||||||
|
niwl-client bob.profile detect 10
|
||||||
|
7e441275a5c3f88606c34c3451a44eaeaa025680cfcb3d9db53992501cc22134 4f7a7f961bc19297fee98da5f8601aa8373429b80b10c55dbe8116aa8c497a0e 71d8da
|
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "niwl-client"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
niwl = {path="../niwl"}
|
||||||
|
fuzzytags = {path="../../fuzzymetatag"}
|
||||||
|
clap = "3.0.0-beta.2"
|
||||||
|
serde = {version="1.0.123", features=["derive"]}
|
||||||
|
serde_json = "1.0.61"
|
||||||
|
bincode = "1.3.1"
|
||||||
|
hex = "0.4.2"
|
||||||
|
base32 = "0.4.0"
|
||||||
|
reqwest = {version="0.11.0", features=["json"]}
|
||||||
|
tokio = "1.2.0"
|
|
@ -0,0 +1,114 @@
|
||||||
|
use clap::Clap;
|
||||||
|
use std::fs;
|
||||||
|
use niwl::{Profile};
|
||||||
|
|
||||||
|
#[derive(Clap)]
|
||||||
|
#[clap(version = "1.0", author = "Sarah Jamie Lewis <sarah@openprivacy.ca>")]
|
||||||
|
struct Opts {
|
||||||
|
|
||||||
|
#[clap(default_value = "niwl.profile")]
|
||||||
|
profile_filename: String,
|
||||||
|
|
||||||
|
#[clap(default_value = "http://localhost:8000")]
|
||||||
|
niwl_server: String,
|
||||||
|
|
||||||
|
#[clap(subcommand)]
|
||||||
|
subcmd: SubCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clap)]
|
||||||
|
enum SubCommand {
|
||||||
|
Generate(Generate),
|
||||||
|
ImportTaggingKey(ImportTaggingKey),
|
||||||
|
TagAndSend(TagAndSend),
|
||||||
|
Detect(Detect)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a new niwl.profile file
|
||||||
|
#[derive(Clap)]
|
||||||
|
struct Generate {
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Import a friends tagging key into this profile so you can send messages to them
|
||||||
|
#[derive(Clap)]
|
||||||
|
struct ImportTaggingKey {
|
||||||
|
key: String
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect to a server and check for new notifications
|
||||||
|
#[derive(Clap)]
|
||||||
|
struct Detect {
|
||||||
|
#[clap(default_value = "2")]
|
||||||
|
length: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a message to a friend tagged with their niwl key
|
||||||
|
#[derive(Clap)]
|
||||||
|
struct TagAndSend {
|
||||||
|
/// the id of the friend e.g. "alice"
|
||||||
|
id: String,
|
||||||
|
/// the message you want to send.
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_profile(profile_filename: &String) -> Profile {
|
||||||
|
match fs::read_to_string(profile_filename) {
|
||||||
|
Ok(json) => serde_json::from_str(json.as_str()).unwrap(),
|
||||||
|
Err(why) => {
|
||||||
|
panic!("couldn't read orb.profile : {}", why);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let opts: Opts = Opts::parse();
|
||||||
|
match opts.subcmd {
|
||||||
|
SubCommand::Generate(g) => {
|
||||||
|
let profile = Profile::new(g.name.clone());
|
||||||
|
let hotk = profile.human_readable_tagging_key();
|
||||||
|
println!("Tagging Key: {}", base32::encode(base32::Alphabet::RFC4648{padding:false} ,bincode::serialize(&hotk).unwrap().as_slice()).to_ascii_lowercase());
|
||||||
|
profile.save(&opts.profile_filename);
|
||||||
|
}
|
||||||
|
SubCommand::ImportTaggingKey(cmd) => {
|
||||||
|
let mut profile = get_profile(&opts.profile_filename);
|
||||||
|
profile.import_tagging_key(&cmd.key);
|
||||||
|
profile.save(&opts.profile_filename);
|
||||||
|
},
|
||||||
|
SubCommand::TagAndSend(cmd) => {
|
||||||
|
let mut profile = get_profile(&opts.profile_filename);
|
||||||
|
let server = opts.niwl_server.clone();
|
||||||
|
let contact = cmd.id.clone();
|
||||||
|
tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(async {
|
||||||
|
let result = profile.tag_and_send(server, contact).await;
|
||||||
|
println!("{}", result.unwrap().text().await.unwrap());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SubCommand::Detect(cmd) => {
|
||||||
|
let mut profile = get_profile(&opts.profile_filename);
|
||||||
|
let server = opts.niwl_server.clone();
|
||||||
|
tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.block_on(async {
|
||||||
|
match profile.detect_tags(server).await {
|
||||||
|
Ok(detected_tags) => {
|
||||||
|
for tag in detected_tags.detected_tags {
|
||||||
|
println!("{}", tag);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "niwl-server"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
fuzzytags = {path="../../fuzzymetatag"}
|
||||||
|
rocket = "0.4.6"
|
||||||
|
rocket_contrib = {version="0.4.6", features=["sqlite_pool"]}
|
||||||
|
chrono = "0.4.19"
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Requires `libsqlite3`
|
||||||
|
|
||||||
|
sudo apt install libsqlite3-dev
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
First setup the database:
|
||||||
|
|
||||||
|
cat sql/create.sql | sqlite3 tags.sqlite
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[global.databases]
|
||||||
|
tags = { url = "./tags.sqlite", pool_size = 20 }
|
|
@ -0,0 +1,4 @@
|
||||||
|
create table if not exists tags (
|
||||||
|
id text primary key,
|
||||||
|
tag blob not null unique
|
||||||
|
)
|
|
@ -0,0 +1,55 @@
|
||||||
|
#![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
|
||||||
|
#[macro_use] extern crate rocket;
|
||||||
|
#[macro_use] extern crate rocket_contrib;
|
||||||
|
|
||||||
|
use rocket_contrib::json;
|
||||||
|
use fuzzytags::{DetectionKey, Tag};
|
||||||
|
use rocket_contrib::json::{Json, JsonValue};
|
||||||
|
use rocket_contrib::databases::rusqlite;
|
||||||
|
use rocket_contrib::databases::rusqlite::types::ToSql;
|
||||||
|
use chrono::{Utc, Duration};
|
||||||
|
use std::ops::Sub;
|
||||||
|
|
||||||
|
#[database("tags")]
|
||||||
|
struct TagsDbConn(rusqlite::Connection);
|
||||||
|
|
||||||
|
#[post("/new", format = "application/json", data = "<tag>")]
|
||||||
|
fn new(conn:TagsDbConn, tag: Json<Tag<24>>) -> JsonValue {
|
||||||
|
conn.0.execute(
|
||||||
|
"INSERT INTO tags (id, tag) VALUES (strftime('%Y-%m-%d %H:%M:%S:%f', 'now'), ?1)",
|
||||||
|
&[&tag.0.compress() as &dyn ToSql],
|
||||||
|
).unwrap();
|
||||||
|
json!({"tag" : tag.to_string()})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/tags", format = "application/json", data = "<detection_key>")]
|
||||||
|
fn tags(conn:TagsDbConn, detection_key: Json<DetectionKey<24>>) -> JsonValue {
|
||||||
|
|
||||||
|
let mut stmt = conn.0.prepare(
|
||||||
|
"SELECT tag FROM tags WHERE id > (?1) AND id < (?2)",
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
let now = Utc::now();
|
||||||
|
let after = now.sub(Duration::days(1)).format("%Y-%m-%d %H:%M:%S:%f").to_string();
|
||||||
|
let before = now.format("%Y-%m-%d %H:%M:%S:%f").to_string();
|
||||||
|
let selected_tags = stmt.query_map(&[&after, &before], |row| {
|
||||||
|
let tag_bytes : Vec<u8> = row.get(0);
|
||||||
|
let tag = Tag::<24>::decompress(tag_bytes.as_slice()).unwrap();
|
||||||
|
tag
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let mut detected_tags : Vec<Tag<24>> = vec![];
|
||||||
|
for tag in selected_tags {
|
||||||
|
let tag : Tag<24> = tag.unwrap();
|
||||||
|
if detection_key.0.test_tag(&tag) {
|
||||||
|
detected_tags.push(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json!({"detected_tags" : detected_tags})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
rocket::ignite().attach(TagsDbConn::fairing()).mount("/", routes![tags, new]).launch();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "niwl"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
fuzzytags = {path="../../fuzzymetatag"}
|
||||||
|
serde = {version="1.0.123", features=["derive"]}
|
||||||
|
serde_json = "1.0.61"
|
||||||
|
bincode = "1.3.1"
|
||||||
|
hex = "0.4.2"
|
||||||
|
base32 = "0.4.0"
|
||||||
|
reqwest = {version="0.11.0", features=["json"]}
|
|
@ -0,0 +1,121 @@
|
||||||
|
#![feature(into_future)]
|
||||||
|
use fuzzytags::{RootSecret, TaggingKey, Tag};
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use reqwest::{Response, Error};
|
||||||
|
use std::future::{Future, IntoFuture};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum NiwlError {
|
||||||
|
NoKnownContactError(String),
|
||||||
|
RemoteServerError(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize,Deserialize)]
|
||||||
|
pub struct Profile {
|
||||||
|
profile_name: String,
|
||||||
|
root_secret: RootSecret<24>,
|
||||||
|
tagging_keys: HashMap<String, TaggingKey<24>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize,Deserialize)]
|
||||||
|
pub struct HumanOrientedTaggingKey {
|
||||||
|
profile_name: String,
|
||||||
|
tagging_key: TaggingKey<24>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct DetectedTags {
|
||||||
|
pub detected_tags: Vec<Tag<24>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Profile {
|
||||||
|
pub fn new(profile_name: String) -> Profile {
|
||||||
|
let root_secret = RootSecret::<24>::generate();
|
||||||
|
Profile {
|
||||||
|
profile_name,
|
||||||
|
root_secret,
|
||||||
|
tagging_keys: Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn human_readable_tagging_key(&self) -> HumanOrientedTaggingKey {
|
||||||
|
let tagging_key = self.root_secret.tagging_key();
|
||||||
|
HumanOrientedTaggingKey {
|
||||||
|
profile_name: self.profile_name.clone(),
|
||||||
|
tagging_key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self, profile_filename: &String) -> std::io::Result<()> {
|
||||||
|
let j = serde_json::to_string(&self);
|
||||||
|
let mut file = match File::create(profile_filename) {
|
||||||
|
Err(why) => panic!("couldn't create : {}", why),
|
||||||
|
Ok(file) => file,
|
||||||
|
};
|
||||||
|
file.write_all(j.unwrap().as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_tag(&self, id: &String) -> Result<Tag<24>, NiwlError> {
|
||||||
|
if self.tagging_keys.contains_key(id) {
|
||||||
|
let tag = self.tagging_keys[id].generate_tag();
|
||||||
|
println!("Tag for {} {}", id, tag.to_string());
|
||||||
|
return Ok(tag)
|
||||||
|
}
|
||||||
|
Err(NiwlError::NoKnownContactError(format!("No known friend {}. Perhaps you need to import-tagging-key first?", id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn import_tagging_key(&mut self, key: &String) {
|
||||||
|
match base32::decode(base32::Alphabet::RFC4648 { padding: false }, key.as_str()) {
|
||||||
|
Some(data) => {
|
||||||
|
let tagging_key_result: Result<HumanOrientedTaggingKey, bincode::Error> = bincode::deserialize(&data);
|
||||||
|
match tagging_key_result {
|
||||||
|
Ok(hotk) => {
|
||||||
|
println!("Got: {}: {}", hotk.profile_name, hotk.tagging_key.id());
|
||||||
|
if self.tagging_keys.contains_key(&hotk.profile_name) == false {
|
||||||
|
self.tagging_keys.insert(hotk.profile_name, hotk.tagging_key);
|
||||||
|
} else {
|
||||||
|
println!("There is already an entry for {}", hotk.profile_name)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error: {}", err.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
println!("Error Reporting Tagging Key")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn tag_and_send(&self, server: String, contact: String) -> Result<Response, NiwlError> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
match self.generate_tag(&contact) {
|
||||||
|
Ok(tag) => {
|
||||||
|
let result = client.
|
||||||
|
post(&String::from(server + "/new"))
|
||||||
|
.json(&tag)
|
||||||
|
.send().await;
|
||||||
|
match result {
|
||||||
|
Ok(response) => Ok(response),
|
||||||
|
Err(err) => Err(NiwlError::RemoteServerError(err.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn detect_tags(&mut self, server: String) -> Result<DetectedTags, Error> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let detection_key = self.root_secret.extract_detection_key(1);
|
||||||
|
let result = client.post(&String::from(server + "/tags"))
|
||||||
|
.json(&detection_key)
|
||||||
|
.send().await;
|
||||||
|
result.unwrap().json().await
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue