Create new user
This commit is contained in:
parent
8dde96b93c
commit
38beda8007
@ -30,8 +30,6 @@ img-parts = "0.3.0"
|
||||
bytes = "1.5.0"
|
||||
scrypt = "0.11.0"
|
||||
shamir = "2.0.0"
|
||||
bitcoin = { version = "0.31.1", features = ["serde", "base64"] }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3"
|
||||
|
@ -1,8 +1,9 @@
|
||||
use rand::Rng;
|
||||
|
||||
use anyhow::Error as AnyhowError;
|
||||
use sp_backend::silentpayments::Error as SpError;
|
||||
use serde_json::Error as SerdeJsonError;
|
||||
use sp_backend::silentpayments::Error as SpError;
|
||||
use sp_backend::bitcoin::secp256k1::SecretKey;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_backend::silentpayments::sending::SilentPaymentAddress;
|
||||
@ -12,6 +13,9 @@ use wasm_bindgen::prelude::*;
|
||||
|
||||
use sp_backend::spclient::SpendKey;
|
||||
use sp_backend::spclient::{derive_keys_from_seed, OutputList, SpClient};
|
||||
use web_sys::js_sys::JsString;
|
||||
|
||||
use crate::user::User;
|
||||
|
||||
type ApiResult<T: FromWasmAbi> = Result<T, ApiError>;
|
||||
|
||||
@ -24,19 +28,25 @@ struct ApiError {
|
||||
|
||||
impl From<AnyhowError> for ApiError {
|
||||
fn from(value: AnyhowError) -> Self {
|
||||
ApiError {message: value.to_string()}
|
||||
ApiError {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SpError> for ApiError {
|
||||
fn from(value: SpError) -> Self {
|
||||
ApiError { message: value.to_string() }
|
||||
ApiError {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SerdeJsonError> for ApiError {
|
||||
fn from(value: SerdeJsonError) -> Self {
|
||||
ApiError { message: value.to_string() }
|
||||
ApiError {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,3 +114,44 @@ pub fn get_receiving_address(sp_client: String) -> String {
|
||||
let sp_client: SpClient = serde_json::from_str(&sp_client).unwrap();
|
||||
sp_client.get_receiving_address()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_user(
|
||||
recover_wallet: String,
|
||||
revoke_wallet: String,
|
||||
password: JsString,
|
||||
image_to_recover: &[u8],
|
||||
image_to_revoke: &[u8],
|
||||
) -> ApiResult<User> {
|
||||
let recover_sp_client: SpClient = serde_json::from_str(&recover_wallet)?;
|
||||
let revoke_sp_client: SpClient = serde_json::from_str(&revoke_wallet)?;
|
||||
let recover_spend_key: SecretKey = match recover_sp_client.get_spend_key() {
|
||||
SpendKey::Secret(sk) => sk,
|
||||
SpendKey::Public(_) => {
|
||||
return Err(ApiError {
|
||||
message: "Can't create user from a watch-only sp_client".to_owned(),
|
||||
})
|
||||
}
|
||||
};
|
||||
let revoke_spend_key: SecretKey = match revoke_sp_client.get_spend_key() {
|
||||
SpendKey::Secret(sk) => sk,
|
||||
SpendKey::Public(_) => {
|
||||
return Err(ApiError {
|
||||
message: "Can't create user from a watch-only sp_client".to_owned(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let revoke_scan_key = revoke_sp_client.get_scan_key();
|
||||
|
||||
let user = User::new(
|
||||
recover_spend_key,
|
||||
revoke_spend_key,
|
||||
revoke_scan_key,
|
||||
&password,
|
||||
image_to_recover,
|
||||
image_to_revoke,
|
||||
)?;
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
|
@ -1,21 +1,37 @@
|
||||
use anyhow::Error;
|
||||
use bitcoin::secp256k1::SecretKey;
|
||||
use aes::cipher::generic_array::GenericArray;
|
||||
use aes_gcm::aead::Aead;
|
||||
use aes_gcm::AeadCore;
|
||||
use aes_gcm::KeyInit;
|
||||
use aes_gcm::{aead::Buffer, Aes256Gcm, Key};
|
||||
use anyhow::{Error, Result};
|
||||
use bytes::Buf;
|
||||
use rand::{self, thread_rng, Rng, RngCore};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use sp_backend::bitcoin::hashes::Hash;
|
||||
use sp_backend::bitcoin::hashes::HashEngine;
|
||||
use sp_backend::bitcoin::hex::{DisplayHex, FromHex};
|
||||
use sp_backend::bitcoin::secp256k1::SecretKey;
|
||||
use tsify::Tsify;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::console;
|
||||
use web_sys::js_sys::JsString;
|
||||
|
||||
use crate::aesgcm::{Aes256GcmIv96Bit, KeyEncryption};
|
||||
use crate::secretdata::SecretData;
|
||||
// use crate::secretdata::SecretData;
|
||||
use bytes::Bytes;
|
||||
use hex;
|
||||
use sha2::{Digest, Sha256};
|
||||
use shamir::SecretData;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::api::{generate_sp_wallet, generate_sp_wallet_return};
|
||||
use sp_backend::bitcoin::secp256k1::constants::SECRET_KEY_SIZE;
|
||||
use sp_backend::silentpayments::bitcoin_hashes::sha256;
|
||||
use sp_backend::silentpayments::sending::SilentPaymentAddress;
|
||||
use sp_backend::spclient::SpendKey;
|
||||
use sp_backend::spclient::{OutputList, SpClient};
|
||||
@ -31,90 +47,100 @@ use scrypt::{
|
||||
//extern crate shamir;
|
||||
//use shamir::SecretData;
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Tsify)]
|
||||
#[tsify(into_wasm_abi, from_wasm_abi)]
|
||||
pub struct User {
|
||||
image_recover: ImageRecover,
|
||||
image_revoke: ImageRevoke,
|
||||
image_recover: BackUpImage,
|
||||
image_revoke: BackUpImage,
|
||||
sharding: Sharding,
|
||||
pre_id: String,
|
||||
recovered_spend_key: Option<String>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl User {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new(new_password: &str, image_to_recover: &[u8], image_to_revoke: &[u8]) -> Self {
|
||||
|
||||
let password = new_password.to_string();
|
||||
let random_seed1 = generate_random_key(32);
|
||||
let random_seed2 = generate_random_key(32);
|
||||
//wallet recover
|
||||
let wallet_rec: String = match generate_sp_wallet(None,50000, true) {
|
||||
Some(sp_wallet) => sp_wallet.sp_client_json,
|
||||
None => panic!("No wallet recover available"),
|
||||
};
|
||||
let sp_client_rec: SpClient = serde_json::from_str(&wallet_rec).unwrap();
|
||||
let priv_recover_scan_key_bytes = sp_client_rec.get_scan_key().secret_bytes();
|
||||
let priv_recover_scan_key = from_b64_to_hex(&base64::encode(priv_recover_scan_key_bytes));
|
||||
let priv_recover_spend_key_bytes = match sp_client_rec.get_spend_key(){
|
||||
SpendKey::Secret(key)=> key.secret_bytes(),
|
||||
SpendKey::Public(_) => panic!("No recover spend key created on Signet"),
|
||||
};
|
||||
let priv_recover_spend_key = from_b64_to_hex(&base64::encode(priv_recover_spend_key_bytes));
|
||||
console::log_2(&"priv_recover_spend_key".into(),&JsValue::from_str(&priv_recover_spend_key));
|
||||
//wallet revoke
|
||||
let wallet_rev: String = match generate_sp_wallet(None, 50000, true) {
|
||||
Some(sp_wallet) => sp_wallet.sp_client_json,
|
||||
None => panic!("No wallet revoke available"),
|
||||
};
|
||||
let sp_client_rev: SpClient = serde_json::from_str(&wallet_rec).unwrap();
|
||||
let priv_revoke_scan_key_bytes = sp_client_rev.get_scan_key().secret_bytes();
|
||||
let priv_revoke_scan_key = from_b64_to_hex(&base64::encode(priv_revoke_scan_key_bytes));
|
||||
let priv_revoke_spend_key_bytes = match sp_client_rev.get_spend_key(){
|
||||
SpendKey::Secret(key)=> key.secret_bytes(),
|
||||
SpendKey::Public(_) => panic!("No revoke spend key created on Signet"),
|
||||
};
|
||||
let priv_revoke_spend_key = from_b64_to_hex(&base64::encode(priv_revoke_spend_key_bytes));
|
||||
|
||||
//split recover spend key
|
||||
let (part1_key, part2_key) = priv_recover_spend_key.split_at(priv_recover_spend_key.len()/2);
|
||||
|
||||
//part1 enc
|
||||
let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}",password, &random_seed1)));
|
||||
|
||||
//split recover spend key
|
||||
let (part1_key, part2_key) =
|
||||
priv_recover_spend_key.split_at(priv_recover_spend_key.len() / 2);
|
||||
|
||||
//part1 enc
|
||||
let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}", password, &random_seed1)));
|
||||
let key_enc_part1 = KeyEncryption::new(None, Some(pwd_hash_part1.clone()), None);
|
||||
let part1_key_enc = key_enc_part1.enc_string(part1_key.to_string());
|
||||
//part2 enc
|
||||
let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2)));
|
||||
let key_enc_part2 = KeyEncryption::new(None, Some(pwd_hash_part2.clone()), None);
|
||||
let part2_key_enc = key_enc_part2.enc_string(part2_key.to_string());
|
||||
//image recover
|
||||
let image_recover = ImageRecover::new(
|
||||
image_to_recover,
|
||||
&random_seed1,
|
||||
&random_seed2,
|
||||
&part1_key_enc,
|
||||
);
|
||||
pub fn new(
|
||||
recover_spend_key: SecretKey,
|
||||
revoke_spend_key: SecretKey,
|
||||
revoke_scan_key: SecretKey,
|
||||
user_password: &JsString,
|
||||
recover_image: &[u8],
|
||||
revoke_image: &[u8],
|
||||
) -> Result<Self> {
|
||||
// image revoke
|
||||
//let priv_revoke_spend_key = wallet.priv_revoke_spend_key.to_owned();
|
||||
//let priv_revoke_scan_key = wallet.priv_revoke_scan_key.to_owned();
|
||||
let image_revoke = ImageRevoke::new(
|
||||
image_to_revoke,
|
||||
&priv_revoke_spend_key,
|
||||
&priv_revoke_scan_key,
|
||||
);
|
||||
// We just take the 2 revoke keys and put it in the revoke_img file
|
||||
let mut revoke_data = [0u8; SECRET_KEY_SIZE * 2];
|
||||
revoke_data[..SECRET_KEY_SIZE].copy_from_slice(revoke_scan_key.as_ref());
|
||||
revoke_data[SECRET_KEY_SIZE..].copy_from_slice(revoke_spend_key.as_ref());
|
||||
|
||||
let revoke_img_with_data = BackUpImage::new_revoke(revoke_image, &revoke_data)?;
|
||||
|
||||
// split recover spend key
|
||||
let (part1_key, part2_key) = recover_spend_key.as_ref().split_at(SECRET_KEY_SIZE / 2);
|
||||
let mut recover_data = Vec::<u8>::with_capacity(88);
|
||||
|
||||
// generate 2 tokens of 32B entropy
|
||||
let mut entropy_1 = [0u8; 32];
|
||||
entropy_1.copy_from_slice(&generate_random_key(32));
|
||||
let mut entropy_2 = [0u8; 32];
|
||||
entropy_2.copy_from_slice(&generate_random_key(32));
|
||||
|
||||
recover_data.extend_from_slice(&entropy_1);
|
||||
recover_data.extend_from_slice(&entropy_2);
|
||||
|
||||
// convert the password in a Vec<u8>
|
||||
// Be careful of javascript strings: https://rustwasm.github.io/wasm-bindgen/reference/types/str.html#utf-16-vs-utf-8
|
||||
assert!(user_password.is_valid_utf16());
|
||||
let password: String = user_password.into();
|
||||
|
||||
// hash the concatenation
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
engine.write_all(&password.as_bytes());
|
||||
engine.write_all(&entropy_1);
|
||||
let hash1 = sha256::Hash::from_engine(engine);
|
||||
|
||||
// take it as a AES key
|
||||
let key1: &Key<Aes256Gcm> = hash1.as_byte_array().try_into()?;
|
||||
let cipher = Aes256Gcm::new(&key1);
|
||||
|
||||
// encrypt the part1 of the key
|
||||
let nonce1 = Aes256Gcm::generate_nonce(&mut thread_rng());
|
||||
let nonce2 = Aes256Gcm::generate_nonce(&mut thread_rng());
|
||||
let cipher_recover_part1 = cipher
|
||||
.encrypt(&nonce1, part1_key)
|
||||
.map_err(|e| anyhow::Error::msg(format!("{}", e)))?;
|
||||
|
||||
log::debug!("cipher_part1 length: {}", cipher_recover_part1.len());
|
||||
|
||||
recover_data.extend_from_slice(&nonce1);
|
||||
recover_data.extend_from_slice(&nonce2);
|
||||
recover_data.extend_from_slice(&cipher_recover_part1);
|
||||
|
||||
//image recover
|
||||
let recover_img_with_data = BackUpImage::new_recover(recover_image, &recover_data)?;
|
||||
|
||||
// encrypt the part 2 of the key
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
engine.write_all(&password.as_bytes());
|
||||
engine.write_all(&entropy_2);
|
||||
let hash2 = sha256::Hash::from_engine(engine);
|
||||
|
||||
// take it as a AES key
|
||||
let key2: &Key<Aes256Gcm> = hash2.as_byte_array().try_into()?;
|
||||
let cipher = Aes256Gcm::new(&key2);
|
||||
|
||||
// encrypt the part2 of the key
|
||||
let cipher_recover_part2 = cipher
|
||||
.encrypt(&nonce2, part2_key)
|
||||
.map_err(|e| anyhow::Error::msg(format!("{}", e)))?;
|
||||
|
||||
//create shardings
|
||||
let sharding = Sharding::new(&part2_key_enc, 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere
|
||||
let sharding = Sharding::new(&cipher_recover_part2.to_lower_hex_string(), 10u8); //nMembers = 10 for testing, need to recover nmember elsewhere
|
||||
|
||||
//Pre ID
|
||||
let pre_id = sha_256(&format!("{}{}", password, part2_key_enc));
|
||||
let mut engine = sha256::HashEngine::default();
|
||||
engine.write_all(&password.as_bytes());
|
||||
engine.write_all(&cipher_recover_part1);
|
||||
let pre_id = sha256::Hash::from_engine(engine);
|
||||
|
||||
//Create PRDList
|
||||
//@todo
|
||||
@ -122,86 +148,118 @@ impl User {
|
||||
//@todo
|
||||
//Receive List Items (PCD)
|
||||
|
||||
console::log_1(&"authentication: ok".into());
|
||||
User {
|
||||
image_recover,
|
||||
image_revoke,
|
||||
Ok(User {
|
||||
image_recover: recover_img_with_data,
|
||||
image_revoke: revoke_img_with_data,
|
||||
sharding,
|
||||
pre_id,
|
||||
pre_id: pre_id.to_string(),
|
||||
recovered_spend_key: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn login(&self, password: &str, image_recover: &[u8]) -> Option<String> {
|
||||
let exif_image_bytes = read_exif(image_recover).unwrap_or_else(|error| {
|
||||
panic!("Unable to read the image exif: {}", error);
|
||||
});
|
||||
pub fn login(&self, user_password: JsString, image_recover: &[u8]) -> Result<SecretKey> {
|
||||
let mut retrieved_key = [0u8; 32];
|
||||
let mut entropy1 = [0u8; 32];
|
||||
let mut entropy2 = [0u8; 32];
|
||||
let mut nonce1 = [0u8; 12];
|
||||
let mut nonce2 = [0u8; 12];
|
||||
let mut part1_ciphertext = Vec::with_capacity(32); // just a guess
|
||||
|
||||
let exif_image_string = String::from_utf8(exif_image_bytes.to_vec()).unwrap();
|
||||
let exif_image_json: Value = serde_json::from_str(&exif_image_string).unwrap();
|
||||
let random_seed1 = exif_image_json["random_seed1"].as_str().unwrap_or("N/A");
|
||||
let random_seed2 = exif_image_json["random_seed2"].as_str().unwrap_or("N/A");
|
||||
let part1_key_enc = exif_image_json["part1_key_enc"].as_str().unwrap_or("N/A");
|
||||
let part1_recovered = Self::recover_part1(password, random_seed1, part1_key_enc);
|
||||
let part1_trimmed = part1_recovered.trim_matches('"');
|
||||
assert!(user_password.is_valid_utf16());
|
||||
let password: String = user_password.into();
|
||||
|
||||
//@todo: get shardings from member managers!!
|
||||
let exif_image_bytes =
|
||||
Bytes::from(read_exif(image_recover).map_err(|e| Error::msg(format!("{}", e)))?);
|
||||
let mut reader = exif_image_bytes.reader();
|
||||
reader.read_exact(&mut entropy1)?;
|
||||
reader.read_exact(&mut entropy2)?;
|
||||
reader.read_exact(&mut nonce1)?;
|
||||
reader.read_exact(&mut nonce2)?;
|
||||
reader.read_to_end(&mut part1_ciphertext)?;
|
||||
|
||||
retrieved_key[..16].copy_from_slice(&Self::recover_part1(
|
||||
&password,
|
||||
&entropy1,
|
||||
&nonce1,
|
||||
&part1_ciphertext,
|
||||
)?);
|
||||
|
||||
//@todo: get shardings from member managers!
|
||||
let shardings = self.sharding.shares_vec.clone(); // temporary
|
||||
|
||||
let part2_recovered = Self::recover_part2(&password, &random_seed2, shardings);
|
||||
let part2_trimmed = part2_recovered.trim_matches('"');
|
||||
let recover_key_hex: String = format!("{}{}", part1_trimmed, part2_trimmed);
|
||||
retrieved_key[16..].copy_from_slice(&Self::recover_part2(
|
||||
&password, &entropy2, &nonce2, shardings,
|
||||
)?);
|
||||
|
||||
Some(recover_key_hex)
|
||||
let key = SecretKey::from_slice(&retrieved_key)?;
|
||||
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
fn recover_part1(password: &str, random_seed1: &str, part1_key_enc: &str) -> String {
|
||||
let pwd_hash_part1 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed1)));
|
||||
let key_dec_part1 = KeyEncryption::new(None, Some(pwd_hash_part1), None);
|
||||
let part1_key_recovered = key_dec_part1
|
||||
.decode(part1_key_enc.to_string())
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
part1_key_recovered
|
||||
fn recover_part1(
|
||||
password: &str,
|
||||
entropy: &[u8],
|
||||
nonce: &[u8],
|
||||
part1_ciphertext: &[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 key: &Key<Aes256Gcm> = hash.as_byte_array().try_into()?;
|
||||
let cipher = Aes256Gcm::new(&key);
|
||||
|
||||
cipher
|
||||
.decrypt(nonce.into(), part1_ciphertext)
|
||||
.map_err(|e| anyhow::Error::msg(format!("{}", e)))
|
||||
}
|
||||
|
||||
fn recover_part2(password: &str, random_seed2: &str, shares_vec: Vec<Vec<u8>>) -> String {
|
||||
let quorum_sharding =
|
||||
(Sharding::QUORUM_SHARD * f32::from(shares_vec.len() as u8)).round() as u8;
|
||||
let part2_key_enc = SecretData::recover_secret(quorum_sharding, shares_vec).unwrap();
|
||||
let pwd_hash_part2 = from_hex_to_b64(&sha_256(&format!("{}{}", password, random_seed2)));
|
||||
let key_dec_part2 = KeyEncryption::new(None, Some(pwd_hash_part2), None);
|
||||
let part2_key_recovered = key_dec_part2
|
||||
.decode(part2_key_enc)
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
part2_key_recovered
|
||||
fn recover_part2(
|
||||
password: &str,
|
||||
entropy: &[u8],
|
||||
nonce: &[u8],
|
||||
shares_vec: Vec<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 part2_key_enc = Vec::from_hex(
|
||||
&SecretData::recover_secret(quorum_sharding, shares_vec)
|
||||
.ok_or_else(|| anyhow::Error::msg("Failed to retrieve the sharded secret"))?,
|
||||
)?;
|
||||
|
||||
let key: &Key<Aes256Gcm> = hash.as_byte_array().try_into()?;
|
||||
let cipher = Aes256Gcm::new(&key);
|
||||
|
||||
cipher
|
||||
.decrypt(nonce.into(), &*part2_key_enc)
|
||||
.map_err(|e| anyhow::Error::msg(format!("{}", e)))
|
||||
}
|
||||
|
||||
//not used
|
||||
pub fn pbkdf2(password: &str, data: &str) -> String {
|
||||
let data_salt = data.trim_end_matches('=');
|
||||
let salt = SaltString::from_b64(data_salt)
|
||||
.map(|s| s)
|
||||
.unwrap_or_else(|_| panic!("Failed to parse salt value from base64 string"));
|
||||
// pub fn pbkdf2(password: &str, data: &str) -> String {
|
||||
// let data_salt = data.trim_end_matches('=');
|
||||
// let salt = SaltString::from_b64(data_salt)
|
||||
// .map(|s| s)
|
||||
// .unwrap_or_else(|_| panic!("Failed to parse salt value from base64 string"));
|
||||
|
||||
let mut password_hash = String::new();
|
||||
if let Ok(pwd) = Scrypt.hash_password(password.as_bytes(), &salt) {
|
||||
password_hash.push_str(&pwd.to_string());
|
||||
}
|
||||
sha_256(&password_hash)
|
||||
}
|
||||
|
||||
pub fn get_image_recover(&self) -> Vec<u8> {
|
||||
return self.image_recover.image_recover_bytes.clone();
|
||||
}
|
||||
// let mut password_hash = String::new();
|
||||
// if let Ok(pwd) = Scrypt.hash_password(password.as_bytes(), &salt) {
|
||||
// password_hash.push_str(&pwd.to_string());
|
||||
// }
|
||||
// sha_256(&password_hash)
|
||||
// }
|
||||
|
||||
pub fn get_exif_image(&self, image: &[u8]) -> Vec<u8> {
|
||||
return read_exif(image).expect("Error reading the exif");
|
||||
}
|
||||
|
||||
pub fn get_image_revoke(&self) -> Vec<u8> {
|
||||
return self.image_revoke.image_revoke_bytes.clone();
|
||||
}
|
||||
|
||||
// Test sharing JS side
|
||||
pub fn get_shares(&self) -> Vec<String> {
|
||||
self.sharding.shares_format_str.clone()
|
||||
@ -223,52 +281,21 @@ impl User {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct ImageRecover {
|
||||
image_recover_bytes: Vec<u8>,
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum BackUpImage {
|
||||
Recover(Vec<u8>),
|
||||
Revoke(Vec<u8>),
|
||||
}
|
||||
|
||||
impl ImageRecover {
|
||||
pub fn new(
|
||||
image_to_recover: &[u8],
|
||||
random_seed1: &str,
|
||||
random_seed2: &str,
|
||||
part1_key_enc: &str,
|
||||
) -> Self {
|
||||
let data_exif_json = json!({
|
||||
"random_seed1": random_seed1,
|
||||
"random_seed2": random_seed2,
|
||||
"part1_key_enc": part1_key_enc
|
||||
});
|
||||
|
||||
let data = serde_json::to_string(&data_exif_json).unwrap();
|
||||
let image_recover = write_exif(image_to_recover, &data);
|
||||
ImageRecover {
|
||||
image_recover_bytes: image_recover.expect("Image recover not generated!"),
|
||||
}
|
||||
}
|
||||
impl BackUpImage {
|
||||
pub fn new_recover(image: &[u8], data: &[u8]) -> Result<Self> {
|
||||
let img = write_exif(image, data)?;
|
||||
Ok(Self::Recover(img))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct ImageRevoke {
|
||||
image_revoke_bytes: Vec<u8>,
|
||||
}
|
||||
impl ImageRevoke {
|
||||
pub fn new(
|
||||
image_to_revoke: &[u8],
|
||||
priv_revoke_spend_key: &str,
|
||||
priv_revoke_scan_key: &str,
|
||||
) -> Self {
|
||||
let data_exif_json = json!({
|
||||
"priv_revoke_spend_key":priv_revoke_spend_key,
|
||||
"priv_revoke_scan_key":priv_revoke_scan_key
|
||||
});
|
||||
|
||||
let data = serde_json::to_string(&data_exif_json).unwrap();
|
||||
let image_revoke = write_exif(image_to_revoke, &data);
|
||||
ImageRevoke {
|
||||
image_revoke_bytes: image_revoke.expect("Image revoke not generated!"),
|
||||
}
|
||||
pub fn new_revoke(image: &[u8], data: &[u8]) -> Result<Self> {
|
||||
let img = write_exif(image, data)?;
|
||||
Ok(Self::Recover(img))
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,27 +342,20 @@ impl Sharding {
|
||||
}
|
||||
|
||||
//associated functions
|
||||
pub fn generate_random_key(length: usize) -> String {
|
||||
pub fn generate_random_key(length: usize) -> Vec<u8> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let random_bytes: Vec<u8> = (0..length).map(|_| rng.gen_range(0x00..=0xFF)).collect();
|
||||
base64::encode(random_bytes)
|
||||
let mut entropy = Vec::<u8>::with_capacity(length);
|
||||
rng.fill_bytes(&mut entropy);
|
||||
entropy
|
||||
}
|
||||
|
||||
pub fn sha_256(data: &str) -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(data);
|
||||
let result = hasher.finalize();
|
||||
hex::encode(result)
|
||||
}
|
||||
|
||||
pub fn write_exif(image_to_recover: &[u8], data: &str) -> Result<Vec<u8>, String> {
|
||||
let image_to_recover_bytes = Bytes::from(image_to_recover.to_vec());
|
||||
let mut jpeg = Jpeg::from_bytes(image_to_recover_bytes).unwrap();
|
||||
let data_bytes = Bytes::from(data.as_bytes().to_vec());
|
||||
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.as_ref();
|
||||
Ok(output_image.to_vec())
|
||||
let output_image = output_image_bytes.to_vec();
|
||||
Ok(output_image)
|
||||
}
|
||||
|
||||
pub fn read_exif(image: &[u8]) -> Result<Vec<u8>, String> {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { GenerateSpWalletReturn } from '../dist/pkg/sdk_client';
|
||||
import { generate_sp_wallet_return, User } from '../dist/pkg/sdk_client';
|
||||
import IndexedDB from './database'
|
||||
import Processstore from './store/processstore';
|
||||
import Userstore from './store/userstore';
|
||||
@ -26,7 +26,7 @@ class Services {
|
||||
this.sdkClient.setup();
|
||||
}
|
||||
|
||||
public new_sp_client(label: string, current_tip: number, is_testnet: boolean): GenerateSpWalletReturn {
|
||||
public new_sp_client(label: string, current_tip: number, is_testnet: boolean): generate_sp_wallet_return {
|
||||
return this.sdkClient.generate_sp_wallet(label, current_tip, is_testnet);
|
||||
}
|
||||
|
||||
@ -91,12 +91,12 @@ class Services {
|
||||
if (!Services.instance.isPasswordValid(password)) return;
|
||||
|
||||
// TODO get secretpart1 from User object
|
||||
// const user = new this.sdkClient.User(password);
|
||||
let secretpart1 = "LKHGKJJJ3H";
|
||||
// const user: User = new this.sdkClient.create_user(password);
|
||||
const user: User = this.sdkClient.create_user(password);
|
||||
// let secretpart1 = "LKHGKJJJ3H";
|
||||
|
||||
try {
|
||||
let userstore = new Userstore;
|
||||
userstore.secretpart1 = secretpart1;
|
||||
userstore.process = process;
|
||||
const indexedDb = await IndexedDB.getInstance();
|
||||
const db = indexedDb.getDb();
|
||||
|
Loading…
x
Reference in New Issue
Block a user