mv crypto and network to common
This commit is contained in:
parent
9f0bde4710
commit
7d22c033bb
@ -18,8 +18,7 @@ wasm-logger = "0.2.0"
|
|||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
log = "0.4.6"
|
log = "0.4.6"
|
||||||
tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" }
|
tsify = { git = "https://github.com/Sosthene00/tsify", branch = "next" }
|
||||||
aes-gcm = "0.10.3"
|
sdk_common = { git = "https://git.4nkweb.com/4nk/sdk_common.git", branch = "demo" }
|
||||||
aes = "0.8.3"
|
|
||||||
shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" }
|
shamir = { git = "https://github.com/Sosthene00/shamir", branch = "master" }
|
||||||
img-parts = "0.3.0"
|
img-parts = "0.3.0"
|
||||||
|
|
||||||
|
@ -1,447 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use anyhow::{Error, Result};
|
|
||||||
use sp_backend::{
|
|
||||||
bitcoin::{
|
|
||||||
consensus::serde::hex,
|
|
||||||
hex::DisplayHex,
|
|
||||||
key::constants::SECRET_KEY_SIZE,
|
|
||||||
secp256k1::{ecdh::SharedSecret, SecretKey},
|
|
||||||
Txid,
|
|
||||||
},
|
|
||||||
silentpayments::sending::SilentPaymentAddress,
|
|
||||||
};
|
|
||||||
use wasm_bindgen::JsValue;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::{json, Value};
|
|
||||||
|
|
||||||
use aes::cipher::generic_array::GenericArray;
|
|
||||||
use aes::{
|
|
||||||
cipher::consts::{U32, U8},
|
|
||||||
Aes256,
|
|
||||||
};
|
|
||||||
use aes_gcm::{
|
|
||||||
aead::{Aead, AeadInPlace, KeyInit, Nonce},
|
|
||||||
AeadCore, Aes256Gcm, AesGcm, Key, TagSize,
|
|
||||||
};
|
|
||||||
use rand::{thread_rng, RngCore};
|
|
||||||
|
|
||||||
const HALFKEYSIZE: usize = SECRET_KEY_SIZE / 2;
|
|
||||||
|
|
||||||
const THIRTYTWO: usize = 32;
|
|
||||||
|
|
||||||
pub struct HalfKey([u8; HALFKEYSIZE]);
|
|
||||||
|
|
||||||
impl TryFrom<Vec<u8>> for HalfKey {
|
|
||||||
type Error = anyhow::Error;
|
|
||||||
fn try_from(value: Vec<u8>) -> std::prelude::v1::Result<Self, Error> {
|
|
||||||
if value.len() == HALFKEYSIZE {
|
|
||||||
let mut buf = [0u8; HALFKEYSIZE];
|
|
||||||
buf.copy_from_slice(&value);
|
|
||||||
Ok(HalfKey(buf))
|
|
||||||
} else {
|
|
||||||
Err(Error::msg("Invalid length for HalfKey"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HalfKey {
|
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_inner(&self) -> Vec<u8> {
|
|
||||||
self.0.to_vec()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Purpose {
|
|
||||||
Login,
|
|
||||||
ThirtyTwoBytes,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type CipherText = Vec<u8>;
|
|
||||||
|
|
||||||
pub type EncryptedKey = Vec<u8>;
|
|
||||||
|
|
||||||
pub struct Aes256Decryption {
|
|
||||||
pub purpose: Purpose,
|
|
||||||
cipher_text: CipherText,
|
|
||||||
aes_key: [u8; 32],
|
|
||||||
nonce: [u8; 12],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Aes256Decryption {
|
|
||||||
pub fn new(
|
|
||||||
purpose: Purpose,
|
|
||||||
cipher_text: CipherText,
|
|
||||||
encrypted_aes_key: Vec<u8>, // If shared_secret is none this is actually the aes_key
|
|
||||||
shared_secret: Option<SharedSecret>, // We don't need that for certain purpose, like Login
|
|
||||||
) -> Result<Self> {
|
|
||||||
let mut aes_key = [0u8; 32];
|
|
||||||
if let Some(shared_secret) = shared_secret {
|
|
||||||
if encrypted_aes_key.len() <= 12 {
|
|
||||||
return Err(Error::msg("encrypted_aes_key is shorter than nonce length"));
|
|
||||||
} // Actually we could probably test that if the remnant is not a multiple of 32, something's wrong
|
|
||||||
// take the first 12 bytes form encrypted_aes_key as nonce
|
|
||||||
let (decrypt_key_nonce, encrypted_key) = encrypted_aes_key.split_at(12);
|
|
||||||
// decrypt key with shared_secret obtained from transaction
|
|
||||||
let decrypt_key_cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref())
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
let aes_key_plain = decrypt_key_cipher
|
|
||||||
.decrypt(decrypt_key_nonce.into(), encrypted_key)
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
if aes_key_plain.len() != 32 {
|
|
||||||
return Err(Error::msg("Invalid length for decrypted key"));
|
|
||||||
}
|
|
||||||
aes_key.copy_from_slice(&aes_key_plain);
|
|
||||||
} else {
|
|
||||||
if encrypted_aes_key.len() != 32 {
|
|
||||||
return Err(Error::msg("Invalid length for decrypted key"));
|
|
||||||
}
|
|
||||||
aes_key.copy_from_slice(&encrypted_aes_key);
|
|
||||||
}
|
|
||||||
if cipher_text.len() <= 12 {
|
|
||||||
return Err(Error::msg("cipher_text is shorter than nonce length"));
|
|
||||||
}
|
|
||||||
let (message_nonce, message_cipher) = cipher_text.split_at(12);
|
|
||||||
let mut nonce = [0u8; 12];
|
|
||||||
nonce.copy_from_slice(message_nonce);
|
|
||||||
Ok(Self {
|
|
||||||
purpose,
|
|
||||||
cipher_text: message_cipher.to_vec(),
|
|
||||||
aes_key,
|
|
||||||
nonce,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrypt_with_key(&self) -> Result<Vec<u8>> {
|
|
||||||
match self.purpose {
|
|
||||||
Purpose::Login => {
|
|
||||||
let half_key = self.decrypt_login()?;
|
|
||||||
Ok(half_key.to_inner())
|
|
||||||
}
|
|
||||||
Purpose::ThirtyTwoBytes => {
|
|
||||||
let thirty_two_buf = self.decrypt_thirty_two()?;
|
|
||||||
Ok(thirty_two_buf.to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt_login(&self) -> Result<HalfKey> {
|
|
||||||
let cipher = Aes256Gcm::new(&self.aes_key.into());
|
|
||||||
let plain = cipher
|
|
||||||
.decrypt(&self.nonce.into(), &*self.cipher_text)
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
if plain.len() != SECRET_KEY_SIZE / 2 {
|
|
||||||
return Err(Error::msg("Plain text of invalid lenght for a login"));
|
|
||||||
}
|
|
||||||
let mut key_half = [0u8; SECRET_KEY_SIZE / 2];
|
|
||||||
key_half.copy_from_slice(&plain);
|
|
||||||
Ok(HalfKey(key_half))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decrypt_thirty_two(&self) -> Result<[u8; THIRTYTWO]> {
|
|
||||||
let cipher = Aes256Gcm::new(&self.aes_key.into());
|
|
||||||
let plain = cipher
|
|
||||||
.decrypt(&self.nonce.into(), &*self.cipher_text)
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
if plain.len() != THIRTYTWO {
|
|
||||||
return Err(Error::msg("Plain text of invalid length, should be 32"));
|
|
||||||
}
|
|
||||||
let mut thirty_two = [0u8; THIRTYTWO];
|
|
||||||
thirty_two.copy_from_slice(&plain);
|
|
||||||
Ok(thirty_two)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Aes256Encryption {
|
|
||||||
pub purpose: Purpose,
|
|
||||||
plaintext: Vec<u8>,
|
|
||||||
aes_key: [u8; 32],
|
|
||||||
nonce: [u8; 12],
|
|
||||||
shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Aes256Encryption {
|
|
||||||
pub fn new(purpose: Purpose, plaintext: Vec<u8>) -> Result<Self> {
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
let aes_key: [u8; 32] = Aes256Gcm::generate_key(&mut rng).into();
|
|
||||||
let nonce: [u8; 12] = Aes256Gcm::generate_nonce(&mut rng).into();
|
|
||||||
Self::import_key(purpose, plaintext, aes_key, nonce)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_shared_secret(
|
|
||||||
&mut self,
|
|
||||||
shared_secrets: HashMap<Txid, HashMap<SilentPaymentAddress, SharedSecret>>,
|
|
||||||
) {
|
|
||||||
self.shared_secrets = shared_secrets;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encrypt_keys_with_shared_secrets(
|
|
||||||
&self,
|
|
||||||
) -> Result<HashMap<SilentPaymentAddress, EncryptedKey>> {
|
|
||||||
let mut res = HashMap::new();
|
|
||||||
let mut rng = thread_rng();
|
|
||||||
|
|
||||||
for (_, sp_address2shared_secret) in self.shared_secrets.iter() {
|
|
||||||
for (sp_address, shared_secret) in sp_address2shared_secret {
|
|
||||||
let cipher = Aes256Gcm::new_from_slice(shared_secret.as_ref())
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
let nonce = Aes256Gcm::generate_nonce(&mut rng);
|
|
||||||
let encrypted_key = cipher
|
|
||||||
.encrypt(&nonce, self.aes_key.as_slice())
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
|
|
||||||
let mut ciphertext = Vec::<u8>::with_capacity(nonce.len() + encrypted_key.len());
|
|
||||||
ciphertext.extend(nonce);
|
|
||||||
ciphertext.extend(encrypted_key);
|
|
||||||
|
|
||||||
res.insert(sp_address.to_owned(), ciphertext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn import_key(
|
|
||||||
purpose: Purpose,
|
|
||||||
plaintext: Vec<u8>,
|
|
||||||
aes_key: [u8; 32],
|
|
||||||
nonce: [u8; 12],
|
|
||||||
) -> Result<Self> {
|
|
||||||
if plaintext.len() == 0 {
|
|
||||||
return Err(Error::msg("Can't create encryption for an empty message"));
|
|
||||||
}
|
|
||||||
Ok(Self {
|
|
||||||
purpose,
|
|
||||||
plaintext,
|
|
||||||
aes_key,
|
|
||||||
nonce,
|
|
||||||
shared_secrets: HashMap::new(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encrypt_with_aes_key(&self) -> Result<CipherText> {
|
|
||||||
match self.purpose {
|
|
||||||
Purpose::Login => self.encrypt_login(),
|
|
||||||
Purpose::ThirtyTwoBytes => self.encrypt_thirty_two(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encrypt_login(&self) -> Result<CipherText> {
|
|
||||||
let half_key: HalfKey = self.plaintext.clone().try_into()?;
|
|
||||||
let cipher = Aes256Gcm::new(&self.aes_key.into());
|
|
||||||
let cipher_text = cipher
|
|
||||||
.encrypt(&self.nonce.into(), half_key.as_slice())
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len());
|
|
||||||
res.extend_from_slice(&self.nonce);
|
|
||||||
res.extend_from_slice(&cipher_text);
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encrypt_thirty_two(&self) -> Result<CipherText> {
|
|
||||||
if self.plaintext.len() != 32 {
|
|
||||||
return Err(Error::msg("Invalid length, should be 32"));
|
|
||||||
}
|
|
||||||
let mut thirty_two = [0u8; 32];
|
|
||||||
thirty_two.copy_from_slice(&self.plaintext);
|
|
||||||
let cipher = Aes256Gcm::new(&self.aes_key.into());
|
|
||||||
let cipher_text = cipher
|
|
||||||
.encrypt(&self.nonce.into(), thirty_two.as_slice())
|
|
||||||
.map_err(|e| Error::msg(format!("{}", e)))?;
|
|
||||||
let mut res = Vec::with_capacity(self.nonce.len() + cipher_text.len());
|
|
||||||
log::info!("{}", cipher_text.len());
|
|
||||||
res.extend_from_slice(&self.nonce);
|
|
||||||
res.extend_from_slice(&cipher_text);
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
const ALICE_SP_ADDRESS: &str = "tsp1qqw3lqr6xravz9nf8ntazgwwl0fqv47kfjdxsnxs6eutavqfwyv5q6qk97mmyf6dtkdyzqlu2zv6h9j2ggclk7vn705q5u2phglpq7yw3dg5rwpdz";
|
|
||||||
const BOB_SP_ADDRESS: &str = "tsp1qq2hlsgrj0gz8kcfkf9flqw5llz0u2vr04telqndku9mcqm6dl4fhvq60t8r78srrf56w9yr7w9e9dusc2wjqc30up6fjwnh9mw3e3veqegdmtf08";
|
|
||||||
const TRANSACTION: &str = "4e6d03dec558e1b6624f813bf2da7cd8d8fb1c2296684c08cf38724dcfd8d10b";
|
|
||||||
const ALICE_SHARED_SECRET: &str =
|
|
||||||
"ccf02d364c2641ca129a3fdf49de57b705896e233f7ba6d738991993ea7e2106";
|
|
||||||
const BOB_SHARED_SECRET: &str =
|
|
||||||
"15ef3e377fb842e81de52dbaaea8ba30aeb051a81043ee19264afd27353da521";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn new_aes_empty_plaintext() {
|
|
||||||
let plaintext = Vec::new();
|
|
||||||
let aes_enc = Aes256Encryption::new(Purpose::Login, plaintext);
|
|
||||||
|
|
||||||
assert!(aes_enc.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn aes_encrypt_login_invalid_length() {
|
|
||||||
let plaintext = "example";
|
|
||||||
let aes_enc_short = Aes256Encryption::new(Purpose::Login, plaintext.as_bytes().to_vec());
|
|
||||||
|
|
||||||
assert!(aes_enc_short.is_ok());
|
|
||||||
|
|
||||||
let cipher = aes_enc_short.unwrap().encrypt_with_aes_key();
|
|
||||||
|
|
||||||
assert!(cipher.is_err());
|
|
||||||
|
|
||||||
let plaintext = [1u8; 64];
|
|
||||||
let aes_enc_long = Aes256Encryption::new(Purpose::Login, plaintext.to_vec());
|
|
||||||
|
|
||||||
assert!(aes_enc_long.is_ok());
|
|
||||||
|
|
||||||
let cipher = aes_enc_long.unwrap().encrypt_with_aes_key();
|
|
||||||
|
|
||||||
assert!(cipher.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn aes_encrypt_login() {
|
|
||||||
let plaintext = [1u8; HALFKEYSIZE];
|
|
||||||
let aes_key = Aes256Gcm::generate_key(&mut thread_rng());
|
|
||||||
let nonce = Aes256Gcm::generate_nonce(&mut thread_rng());
|
|
||||||
let aes_enc = Aes256Encryption::import_key(
|
|
||||||
Purpose::Login,
|
|
||||||
plaintext.to_vec(),
|
|
||||||
aes_key.into(),
|
|
||||||
nonce.into(),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(aes_enc.is_ok());
|
|
||||||
|
|
||||||
let cipher = aes_enc.unwrap().encrypt_with_aes_key();
|
|
||||||
|
|
||||||
assert!(cipher.is_ok());
|
|
||||||
|
|
||||||
let mut plain_key = [0u8; 32];
|
|
||||||
plain_key.copy_from_slice(&aes_key.to_vec());
|
|
||||||
|
|
||||||
let aes_dec =
|
|
||||||
Aes256Decryption::new(Purpose::Login, cipher.unwrap(), plain_key.to_vec(), None);
|
|
||||||
|
|
||||||
assert!(aes_dec.is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn aes_encrypt_key() {
|
|
||||||
let plaintext = [1u8; HALFKEYSIZE];
|
|
||||||
let mut aes_enc = Aes256Encryption::new(Purpose::Login, plaintext.to_vec()).unwrap();
|
|
||||||
|
|
||||||
let mut shared_secrets: HashMap<Txid, _> = HashMap::new();
|
|
||||||
let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> =
|
|
||||||
HashMap::new();
|
|
||||||
sp_address2shared_secrets.insert(
|
|
||||||
ALICE_SP_ADDRESS.try_into().unwrap(),
|
|
||||||
SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(),
|
|
||||||
);
|
|
||||||
shared_secrets.insert(
|
|
||||||
Txid::from_str(TRANSACTION).unwrap(),
|
|
||||||
sp_address2shared_secrets,
|
|
||||||
);
|
|
||||||
|
|
||||||
aes_enc.set_shared_secret(shared_secrets);
|
|
||||||
|
|
||||||
let sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets();
|
|
||||||
|
|
||||||
assert!(sp_address2encrypted_keys.is_ok());
|
|
||||||
|
|
||||||
let encrypted_key = sp_address2encrypted_keys
|
|
||||||
.unwrap()
|
|
||||||
.get(&ALICE_SP_ADDRESS.try_into().unwrap())
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
let ciphertext = aes_enc.encrypt_with_aes_key();
|
|
||||||
|
|
||||||
assert!(ciphertext.is_ok());
|
|
||||||
|
|
||||||
let aes_dec = Aes256Decryption::new(
|
|
||||||
Purpose::Login,
|
|
||||||
ciphertext.unwrap(),
|
|
||||||
encrypted_key.unwrap(),
|
|
||||||
Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()),
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(aes_dec.is_ok());
|
|
||||||
|
|
||||||
let retrieved_plain = aes_dec.unwrap().decrypt_with_key();
|
|
||||||
|
|
||||||
assert!(retrieved_plain.is_ok());
|
|
||||||
|
|
||||||
assert!(retrieved_plain.unwrap() == plaintext);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn aes_encrypt_key_many() {
|
|
||||||
let plaintext = [1u8; THIRTYTWO];
|
|
||||||
let mut aes_enc =
|
|
||||||
Aes256Encryption::new(Purpose::ThirtyTwoBytes, plaintext.to_vec()).unwrap();
|
|
||||||
|
|
||||||
let mut shared_secrets: HashMap<Txid, _> = HashMap::new();
|
|
||||||
let mut sp_address2shared_secrets: HashMap<SilentPaymentAddress, SharedSecret> =
|
|
||||||
HashMap::new();
|
|
||||||
sp_address2shared_secrets.insert(
|
|
||||||
ALICE_SP_ADDRESS.try_into().unwrap(),
|
|
||||||
SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap(),
|
|
||||||
);
|
|
||||||
sp_address2shared_secrets.insert(
|
|
||||||
BOB_SP_ADDRESS.try_into().unwrap(),
|
|
||||||
SharedSecret::from_str(BOB_SHARED_SECRET).unwrap(),
|
|
||||||
);
|
|
||||||
shared_secrets.insert(
|
|
||||||
Txid::from_str(TRANSACTION).unwrap(),
|
|
||||||
sp_address2shared_secrets,
|
|
||||||
);
|
|
||||||
|
|
||||||
aes_enc.set_shared_secret(shared_secrets);
|
|
||||||
|
|
||||||
let mut sp_address2encrypted_keys = aes_enc.encrypt_keys_with_shared_secrets();
|
|
||||||
|
|
||||||
assert!(sp_address2encrypted_keys.is_ok());
|
|
||||||
|
|
||||||
// Alice
|
|
||||||
let encrypted_key = sp_address2encrypted_keys
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.get(&ALICE_SP_ADDRESS.try_into().unwrap())
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
let ciphertext = aes_enc.encrypt_with_aes_key();
|
|
||||||
|
|
||||||
let aes_dec = Aes256Decryption::new(
|
|
||||||
Purpose::ThirtyTwoBytes,
|
|
||||||
ciphertext.unwrap(),
|
|
||||||
encrypted_key.unwrap(),
|
|
||||||
Some(SharedSecret::from_str(ALICE_SHARED_SECRET).unwrap()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let retrieved_plain = aes_dec.unwrap().decrypt_with_key();
|
|
||||||
|
|
||||||
assert!(retrieved_plain.unwrap() == plaintext);
|
|
||||||
|
|
||||||
// Bob
|
|
||||||
let encrypted_key = sp_address2encrypted_keys
|
|
||||||
.unwrap()
|
|
||||||
.get(&BOB_SP_ADDRESS.try_into().unwrap())
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
let ciphertext = aes_enc.encrypt_with_aes_key();
|
|
||||||
|
|
||||||
let aes_dec = Aes256Decryption::new(
|
|
||||||
Purpose::ThirtyTwoBytes,
|
|
||||||
ciphertext.unwrap(),
|
|
||||||
encrypted_key.unwrap(),
|
|
||||||
Some(SharedSecret::from_str(BOB_SHARED_SECRET).unwrap()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let retrieved_plain = aes_dec.unwrap().decrypt_with_key();
|
|
||||||
|
|
||||||
assert!(retrieved_plain.unwrap() == plaintext);
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,9 +5,7 @@ use std::sync::{Mutex, MutexGuard};
|
|||||||
|
|
||||||
mod Prd_list;
|
mod Prd_list;
|
||||||
pub mod api;
|
pub mod api;
|
||||||
mod crypto;
|
|
||||||
mod images;
|
mod images;
|
||||||
mod network;
|
|
||||||
mod peers;
|
mod peers;
|
||||||
mod process;
|
mod process;
|
||||||
mod silentpayments;
|
mod silentpayments;
|
||||||
|
@ -1,94 +0,0 @@
|
|||||||
use anyhow::{Error, Result};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use tsify::Tsify;
|
|
||||||
|
|
||||||
const RAWTXTOPIC: &'static str = "rawtx";
|
|
||||||
const RAWBLOCKTOPIC: &'static str = "rawblock";
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum BitcoinTopic {
|
|
||||||
RawTx,
|
|
||||||
RawBlock,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BitcoinTopic {
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Self::RawTx => RAWTXTOPIC,
|
|
||||||
Self::RawBlock => RAWBLOCKTOPIC,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Tsify)]
|
|
||||||
#[tsify(from_wasm_abi, into_wasm_abi)]
|
|
||||||
pub struct BitcoinNetworkMsg<'a> {
|
|
||||||
pub topic: BitcoinTopic,
|
|
||||||
pub data: &'a [u8],
|
|
||||||
pub sequence: &'a [u8],
|
|
||||||
pub addon: &'a [u8],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> BitcoinNetworkMsg<'a> {
|
|
||||||
pub fn new(raw_msg: &'a [u8]) -> Result<Self> {
|
|
||||||
let topic: BitcoinTopic;
|
|
||||||
let data: &[u8];
|
|
||||||
let sequence: &[u8];
|
|
||||||
let addon: &[u8];
|
|
||||||
let addon_len: usize;
|
|
||||||
let raw_msg_len = raw_msg.len();
|
|
||||||
|
|
||||||
if raw_msg.starts_with(RAWTXTOPIC.as_bytes()) {
|
|
||||||
topic = BitcoinTopic::RawTx;
|
|
||||||
addon_len = 33;
|
|
||||||
} else if raw_msg.starts_with(RAWBLOCKTOPIC.as_bytes()) {
|
|
||||||
topic = BitcoinTopic::RawBlock;
|
|
||||||
addon_len = 0;
|
|
||||||
} else {
|
|
||||||
return Err(Error::msg("Unknown prefix"));
|
|
||||||
}
|
|
||||||
|
|
||||||
data = &raw_msg[topic.as_str().as_bytes().len()..raw_msg_len - 4 - addon_len];
|
|
||||||
sequence = &raw_msg[raw_msg_len - 4 - addon_len..];
|
|
||||||
addon = &raw_msg[raw_msg_len - addon_len..];
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
topic,
|
|
||||||
data,
|
|
||||||
sequence,
|
|
||||||
addon,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum AnkTopic {
|
|
||||||
Faucet,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AnkTopic {
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Self::Faucet => "faucet",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct AnkNetworkMsg<'a> {
|
|
||||||
pub topic: AnkTopic,
|
|
||||||
pub content: &'a str,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> AnkNetworkMsg<'a> {
|
|
||||||
pub fn new(raw: &'a str) -> Result<Self> {
|
|
||||||
if raw.starts_with(AnkTopic::Faucet.as_str()) {
|
|
||||||
Ok(Self {
|
|
||||||
topic: AnkTopic::Faucet,
|
|
||||||
content: &raw[AnkTopic::Faucet.as_str().len()..],
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(Error::msg("Unknown 4nk message"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,3 @@
|
|||||||
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 anyhow::{Error, Result};
|
||||||
use rand::{self, thread_rng, Rng, RngCore};
|
use rand::{self, thread_rng, Rng, RngCore};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -29,10 +24,12 @@ use sp_backend::silentpayments::sending::SilentPaymentAddress;
|
|||||||
use sp_backend::spclient::SpendKey;
|
use sp_backend::spclient::SpendKey;
|
||||||
use sp_backend::spclient::{OutputList, SpWallet};
|
use sp_backend::spclient::{OutputList, SpWallet};
|
||||||
|
|
||||||
use crate::crypto::{Aes256Decryption, Aes256Encryption, HalfKey, Purpose};
|
|
||||||
use crate::peers::Peer;
|
use crate::peers::Peer;
|
||||||
use crate::user;
|
use crate::user;
|
||||||
use crate::MutexExt;
|
use crate::MutexExt;
|
||||||
|
use sdk_common::crypto::{
|
||||||
|
AeadCore, Aes256Decryption, Aes256Encryption, Aes256Gcm, HalfKey, KeyInit, Purpose,
|
||||||
|
};
|
||||||
|
|
||||||
type PreId = String;
|
type PreId = String;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user