User creation + login

This commit is contained in:
Sosthene00 2024-04-02 14:19:25 +02:00
parent 162cdd49af
commit 030cc0231a
5 changed files with 128 additions and 199 deletions

View File

@ -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(())
}

View File

@ -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)
}

View File

@ -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;

View 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>,
}

View File

@ -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!(