User creation + login
This commit is contained in:
parent
162cdd49af
commit
030cc0231a
@ -1,14 +1,12 @@
|
||||
use sp_backend::bitcoin::PublicKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use sp_backend::bitcoin::PublicKey;
|
||||
//use sp_backend::silentpayments::sending::SilentPaymentAddress;
|
||||
use std::marker::Copy;
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use std::marker::Copy;
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq, Copy)]
|
||||
pub enum Role {
|
||||
Manager,
|
||||
@ -18,16 +16,15 @@ pub enum Role {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct SilentPaymentAddress {
|
||||
version : u8,
|
||||
scan_pubkey : PublicKey,
|
||||
m_pubkey : PublicKey,
|
||||
is_testnet : bool,
|
||||
version: u8,
|
||||
scan_pubkey: PublicKey,
|
||||
m_pubkey: PublicKey,
|
||||
is_testnet: bool,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ItemMember {
|
||||
pub role : Role,
|
||||
pub role: Role,
|
||||
pub sp_address: SilentPaymentAddress,
|
||||
//pre_id: hash(password, part1)
|
||||
//shard,
|
||||
@ -38,7 +35,7 @@ pub struct ItemMember {
|
||||
|
||||
impl ItemMember {
|
||||
pub fn new(role: Role, sp_address: SilentPaymentAddress) -> Self {
|
||||
ItemMember {role, sp_address}
|
||||
ItemMember { role, sp_address }
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,37 +44,30 @@ pub struct Prdlist {
|
||||
//pub id: String,
|
||||
//pub version: String,
|
||||
pub gestionnaires: Vec<ItemMember>,
|
||||
// pub gestionnaires: Box<Vec<ItemMember>>,
|
||||
// pub gestionnaires: Box<Vec<ItemMember>>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[wasm_bindgen]
|
||||
struct RequestBody {
|
||||
message: String,
|
||||
}
|
||||
|
||||
pub fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> {
|
||||
let managers: Vec<&ItemMember> = prdlist.gestionnaires.iter().filter(|m| m.role == Role::Manager).collect();
|
||||
pub fn send_PrdRequest(prdlist: &Prdlist) -> Result<(), JsValue> {
|
||||
let managers: Vec<&ItemMember> = prdlist
|
||||
.gestionnaires
|
||||
.iter()
|
||||
.filter(|m| m.role == Role::Manager)
|
||||
.collect();
|
||||
for manager in managers {
|
||||
let request_body = RequestBody {
|
||||
message: "Asking for the Prd list".to_string(),
|
||||
};
|
||||
|
||||
let json_body = serde_json::to_string(&request_body).map_err(|e| JsValue::from_str(&format!("Failed to serialize request body: {:?}", e)))?;
|
||||
let json_body = serde_json::to_string(&request_body).map_err(|e| {
|
||||
JsValue::from_str(&format!("Failed to serialize request body: {:?}", e))
|
||||
})?;
|
||||
println!("Sending request to manager {:?}", manager.sp_address);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -128,20 +128,21 @@ pub fn get_receiving_address(sp_client: String) -> String {
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_user(
|
||||
password: String,
|
||||
password: String, // Attention à la conversion depuis le js
|
||||
label: Option<String>,
|
||||
birthday: u32,
|
||||
birthday_main: u32,
|
||||
birthday_signet: u32,
|
||||
process: String,
|
||||
) -> ApiResult<createUserReturn> {
|
||||
let mut output_list: Vec<OutputList> = Vec::new();
|
||||
//recover
|
||||
let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday, true)?;
|
||||
let sp_wallet_recover = generate_sp_wallet(label.clone(), birthday_signet, true)?;
|
||||
output_list.push(sp_wallet_recover.sp_outputs);
|
||||
//revoke
|
||||
let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday, true)?;
|
||||
let sp_wallet_revoke = generate_sp_wallet(label.clone(), birthday_signet, true)?;
|
||||
output_list.push(sp_wallet_revoke.sp_outputs);
|
||||
//mainet
|
||||
let sp_wallet_main = generate_sp_wallet(label, birthday, false)?;
|
||||
let sp_wallet_main = generate_sp_wallet(label, birthday_main, false)?;
|
||||
output_list.push(sp_wallet_main.sp_outputs);
|
||||
|
||||
let user_keys = UserKeys::new(
|
||||
@ -195,3 +196,37 @@ pub fn get_processes() -> ApiResult<get_process_return> {
|
||||
data_process.push(process3);
|
||||
Ok(get_process_return(data_process))
|
||||
}
|
||||
|
||||
#[derive(Debug, Tsify, Serialize, Deserialize)]
|
||||
#[tsify(from_wasm_abi)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct recover_data(Vec<u8>);
|
||||
|
||||
impl recover_data {
|
||||
fn as_inner(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Tsify, Serialize, Deserialize)]
|
||||
#[tsify(from_wasm_abi)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct shamir_shares(Vec<Vec<u8>>);
|
||||
|
||||
impl shamir_shares {
|
||||
fn as_inner(&self) -> &[Vec<u8>] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn login_user(
|
||||
user_password: String,
|
||||
pre_id: String,
|
||||
recover: recover_data,
|
||||
shares: shamir_shares,
|
||||
) -> ApiResult<()> {
|
||||
let res = User::login(pre_id, user_password, recover.as_inner(), shares.as_inner())?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![allow(warnings)]
|
||||
mod Prd_list;
|
||||
mod aesgcm;
|
||||
pub mod api;
|
||||
mod injecteurhtml;
|
||||
mod user;
|
||||
mod aesgcm;
|
||||
mod Prd_list;
|
||||
mod peers;
|
||||
mod process;
|
||||
|
||||
mod user;
|
||||
|
9
crates/sp_client/src/peers.rs
Normal file
9
crates/sp_client/src/peers.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Peer {
|
||||
pub addr: SocketAddr,
|
||||
pub processes: Vec<String>,
|
||||
}
|
@ -16,7 +16,6 @@ use sp_backend::bitcoin::secp256k1::ThirtyTwoByteHash;
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use bytes::Bytes;
|
||||
use shamir::SecretData;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
@ -37,10 +36,14 @@ use img_parts::{ImageEXIF, ImageICC};
|
||||
use crate::aesgcm::Aes256Decryption;
|
||||
use crate::aesgcm::HalfKey;
|
||||
use crate::aesgcm::{Aes256Encryption, Purpose};
|
||||
use crate::peers::Peer;
|
||||
use crate::user;
|
||||
|
||||
type PreId = String;
|
||||
|
||||
const MANAGERS_NUMBER: u8 = 10;
|
||||
const QUORUM_SHARD: f32 = 0.8;
|
||||
|
||||
pub static CONNECTED_USERS: OnceLock<Mutex<HashMap<PreId, UserKeys>>> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -67,11 +70,12 @@ impl UserKeys {
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct User {
|
||||
pub pre_id: String,
|
||||
pub process: String,
|
||||
pub pre_id: PreId,
|
||||
pub processes: Vec<String>,
|
||||
pub peers: Vec<Peer>,
|
||||
recover_data: Vec<u8>,
|
||||
revoke_data: Option<Vec<u8>>,
|
||||
sharding: Sharding,
|
||||
shares: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl User {
|
||||
@ -143,7 +147,18 @@ impl User {
|
||||
let cipher_recover_part2 = part2_encryption.encrypt_with_aes_key()?;
|
||||
|
||||
//create shardings
|
||||
let sharding = Sharding::new(&cipher_recover_part2.to_lower_hex_string(), 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere
|
||||
let threshold = (MANAGERS_NUMBER as f32 * QUORUM_SHARD).floor();
|
||||
debug_assert!(threshold > 0.0 && threshold <= u8::MAX as f32);
|
||||
let sharding = shamir::SecretData::with_secret(
|
||||
&cipher_recover_part2.to_lower_hex_string(),
|
||||
threshold as u8,
|
||||
);
|
||||
|
||||
let shares: Vec<Vec<u8>> = (1..MANAGERS_NUMBER)
|
||||
.map(|x| {
|
||||
sharding.get_share(x).unwrap() // Let's trust it for now
|
||||
})
|
||||
.collect();
|
||||
|
||||
//scan key:
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
@ -171,10 +186,11 @@ impl User {
|
||||
|
||||
Ok(User {
|
||||
pre_id: pre_id.to_string(),
|
||||
process,
|
||||
processes: vec![process],
|
||||
peers: vec![],
|
||||
recover_data,
|
||||
revoke_data: Some(revoke_data),
|
||||
sharding,
|
||||
shares,
|
||||
})
|
||||
}
|
||||
|
||||
@ -182,7 +198,7 @@ impl User {
|
||||
pre_id: PreId,
|
||||
user_password: String,
|
||||
recover_data: &[u8],
|
||||
sharding: Sharding,
|
||||
shares: &[Vec<u8>],
|
||||
) -> Result<()> {
|
||||
let mut retrieved_spend_key = [0u8; 32];
|
||||
let mut retrieved_scan_key = [0u8; 32];
|
||||
@ -228,13 +244,10 @@ impl User {
|
||||
part1_ciphertext.to_vec(),
|
||||
)?);
|
||||
|
||||
//@todo: get shardings from member managers!
|
||||
let shardings = sharding.shares_vec.clone(); // temporary
|
||||
|
||||
retrieved_spend_key[16..].copy_from_slice(&Self::recover_part2(
|
||||
&user_password,
|
||||
&entropy2,
|
||||
shardings,
|
||||
shares,
|
||||
)?);
|
||||
|
||||
retrieved_scan_key.copy_from_slice(&Self::recover_key_slice(
|
||||
@ -309,17 +322,17 @@ impl User {
|
||||
aes_dec.decrypt_with_key()
|
||||
}
|
||||
|
||||
fn recover_part2(password: &str, entropy: &[u8], shares_vec: Vec<Vec<u8>>) -> Result<Vec<u8>> {
|
||||
fn recover_part2(password: &str, entropy: &[u8], shares: &[Vec<u8>]) -> Result<Vec<u8>> {
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
engine.write_all(&password.as_bytes());
|
||||
engine.write_all(&entropy);
|
||||
let hash = sha256::Hash::from_engine(engine);
|
||||
|
||||
let shares_total: f32 = u8::try_from(shares_vec.len())?.try_into()?;
|
||||
let quorum_sharding: u8 = (Sharding::QUORUM_SHARD * shares_total).round() as u8;
|
||||
let threshold = (MANAGERS_NUMBER as f32 * QUORUM_SHARD).floor();
|
||||
debug_assert!(threshold > 0.0 && threshold <= u8::MAX as f32);
|
||||
|
||||
let part2_key_enc = Vec::from_hex(
|
||||
&SecretData::recover_secret(quorum_sharding, shares_vec)
|
||||
&SecretData::recover_secret(threshold as u8, shares.to_vec())
|
||||
.ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?,
|
||||
)?;
|
||||
|
||||
@ -356,141 +369,27 @@ impl User {
|
||||
// sha_256(&password_hash)
|
||||
// }
|
||||
|
||||
// Test sharing JS side
|
||||
pub fn get_shares(&self) -> Vec<String> {
|
||||
self.sharding.shares_format_str.clone()
|
||||
}
|
||||
// // Test sharing JS side
|
||||
// pub fn get_shares(&self) -> Vec<String> {
|
||||
// self.sharding.shares_format_str.clone()
|
||||
// }
|
||||
|
||||
//Test sharing Js side
|
||||
pub fn get_secret(&self, shardings: Vec<String>) -> String {
|
||||
let mut shares_vec = Vec::new();
|
||||
// //Test sharing Js side
|
||||
// pub fn get_secret(&self, shardings: Vec<String>) -> String {
|
||||
// let mut shares_vec = Vec::new();
|
||||
|
||||
for s in shardings.iter() {
|
||||
let bytes_vec: Vec<u8> = s
|
||||
.trim_matches(|c| c == '[' || c == ']')
|
||||
.split(',')
|
||||
.filter_map(|s| s.trim().parse().ok())
|
||||
.collect();
|
||||
shares_vec.push(bytes_vec);
|
||||
}
|
||||
self.sharding.recover_secrete(shares_vec.clone())
|
||||
}
|
||||
// for s in shardings.iter() {
|
||||
// let bytes_vec: Vec<u8> = s
|
||||
// .trim_matches(|c| c == '[' || c == ']')
|
||||
// .split(',')
|
||||
// .filter_map(|s| s.trim().parse().ok())
|
||||
// .collect();
|
||||
// shares_vec.push(bytes_vec);
|
||||
// }
|
||||
// self.sharding.recover_secrete(shares_vec.clone())
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum BackUpImage {
|
||||
Recover(Vec<u8>),
|
||||
Revoke(Vec<u8>),
|
||||
}
|
||||
|
||||
impl BackUpImage {
|
||||
pub fn new_recover(image: &[u8], data: &[u8]) -> Result<Self> {
|
||||
let img = write_exif(image, data)?;
|
||||
Ok(Self::Recover(img))
|
||||
}
|
||||
|
||||
pub fn new_revoke(image: &[u8], data: &[u8]) -> Result<Self> {
|
||||
let img = write_exif(image, data)?;
|
||||
Ok(Self::Revoke(img))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Sharding {
|
||||
shares_vec: Vec<Vec<u8>>,
|
||||
shares_format_str: Vec<String>,
|
||||
}
|
||||
|
||||
impl Sharding {
|
||||
const QUORUM_SHARD: f32 = 0.80_f32;
|
||||
pub fn new(part2_key_enc: &str, number_members: u8) -> Self {
|
||||
let secret_data = SecretData::with_secret(part2_key_enc, number_members);
|
||||
let mut shares_format_str: Vec<String> = Vec::new();
|
||||
let shares_vec = (1..=number_members)
|
||||
.map(|i| match secret_data.get_share(i) {
|
||||
Ok(share) => {
|
||||
let string = format!(
|
||||
"[{}]",
|
||||
share
|
||||
.clone()
|
||||
.iter()
|
||||
.map(|b| format!("{}", b))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
);
|
||||
shares_format_str.push(string.clone());
|
||||
share
|
||||
}
|
||||
Err(_) => panic!("Not able to recover the shares!"),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Sharding {
|
||||
shares_vec,
|
||||
shares_format_str,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recover_secrete(&self, shares: Vec<Vec<u8>>) -> String {
|
||||
let quorum_sharding = (Self::QUORUM_SHARD * f32::from(shares.len() as u8)).round() as u8;
|
||||
SecretData::recover_secret(quorum_sharding, shares).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_exif(image_to_recover: &[u8], data: &[u8]) -> Result<Vec<u8>> {
|
||||
let mut jpeg = Jpeg::from_bytes(Bytes::from(image_to_recover.to_vec()))?;
|
||||
let data_bytes = Bytes::from(data.to_owned());
|
||||
jpeg.set_exif(Some(data_bytes));
|
||||
let output_image_bytes = jpeg.encoder().bytes();
|
||||
let output_image = output_image_bytes.to_vec();
|
||||
Ok(output_image)
|
||||
}
|
||||
|
||||
pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> {
|
||||
let image_bytes = Bytes::from(image.to_vec());
|
||||
let jpeg = Jpeg::from_bytes(image_bytes).unwrap();
|
||||
|
||||
//exif out
|
||||
let mut exif_image = Bytes::new();
|
||||
if let Some(ref meta) = jpeg.exif() {
|
||||
exif_image = meta.clone();
|
||||
} else {
|
||||
return Err("No exif data".to_string());
|
||||
}
|
||||
let exif_bytes = exif_image.as_ref();
|
||||
Ok(exif_bytes.to_vec())
|
||||
}
|
||||
|
||||
// //change for return Result?
|
||||
// pub fn from_hex_to_b58(hex_string: &str) -> String {
|
||||
// let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string");
|
||||
// let base58_string = bs58::encode(decoded_data).into_string();
|
||||
// base58_string
|
||||
// }
|
||||
// //change for return Result?
|
||||
// pub fn from_b58_to_hex(base58_string: &str) -> String {
|
||||
// let decoded_data = bs58::decode(base58_string.to_owned()).into_vec().unwrap();
|
||||
// let hex_string = decoded_data
|
||||
// .iter()
|
||||
// .map(|b| format!("{:02x}", b))
|
||||
// .collect::<String>();
|
||||
// hex_string
|
||||
// }
|
||||
|
||||
// fn from_b64_to_hex(base64_string: &str) -> String {
|
||||
// let decoded_data = base64::decode(base64_string).unwrap();
|
||||
// let hex_string = decoded_data
|
||||
// .iter()
|
||||
// .map(|b| format!("{:02x}", b))
|
||||
// .collect::<String>();
|
||||
// hex_string
|
||||
// }
|
||||
// fn from_hex_to_b64(hex_string: &str) -> String {
|
||||
// let decoded_data = hex::decode(hex_string).expect("Failed to decode hex string");
|
||||
// let base64_string = base64::encode(decoded_data);
|
||||
// base64_string
|
||||
// }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*; // Import everything from the outer module
|
||||
@ -550,22 +449,18 @@ mod tests {
|
||||
let user_keys = helper_create_user_keys();
|
||||
let user = User::new(user_keys, USER_PASSWORD.to_owned(), PROCESS.to_owned()).unwrap();
|
||||
|
||||
let pre_id = user.pre_id;
|
||||
let recover_data = user.recover_data;
|
||||
let sharding = user.sharding;
|
||||
|
||||
let retrieved_recover_spend = User::login(
|
||||
pre_id.clone(),
|
||||
let res = User::login(
|
||||
user.pre_id.clone(),
|
||||
USER_PASSWORD.to_owned(),
|
||||
&recover_data,
|
||||
sharding,
|
||||
&user.recover_data,
|
||||
&user.shares,
|
||||
);
|
||||
|
||||
assert!(retrieved_recover_spend.is_ok());
|
||||
assert!(res.is_ok());
|
||||
|
||||
let connected = CONNECTED_USERS.get().unwrap().lock().unwrap();
|
||||
|
||||
let recover = &connected.get(&pre_id).unwrap().recover;
|
||||
let recover = &connected.get(&user.pre_id).unwrap().recover;
|
||||
|
||||
assert!(
|
||||
format!(
|
||||
|
Loading…
x
Reference in New Issue
Block a user