(port: i64, parse_params: F, async_job: F2)
+where
+ P: 'static + Send + Sync,
+ F: FnOnce() -> Result,
+ F2: 'static + Send + Sync + FnOnce(P) -> R,
+ DartRes: From,
+{
+ match parse_params() {
+ Ok(parsed_params) => {
+ if THREAD_POOL
+ .launch(move |_| Isolate::new(port).post(DartRes::from(async_job(parsed_params))))
+ .is_err()
+ {
+ Isolate::new(port).post(DartRes::err("thread pool panicked"));
+ }
+ }
+ Err(e) => {
+ Isolate::new(port).post(DartRes::err(e));
+ }
+ }
+}
diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs
index 7d07565..a7905e3 100644
--- a/native/dubp_rs/src/dewif.rs
+++ b/native/dubp_rs/src/dewif.rs
@@ -15,82 +15,51 @@
use crate::*;
-pub(super) fn gen_pin6() -> Result {
- let i = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
- Ok(gen_pin6_inner(i))
-}
-pub(super) fn gen_pin8() -> Result {
- let i = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
- let i2 = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
- let mut pin = gen_pin6_inner(i);
- gen_pin2_inner(i2, &mut pin);
- Ok(pin)
-}
-pub(super) fn gen_pin10() -> Result {
- let i = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
- let i2 = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
- let mut pin = gen_pin6_inner(i);
- gen_pin4_inner(i2, &mut pin);
- Ok(pin)
-}
-
-pub(super) fn change_pin(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- old_pin: *const raw::c_char,
- new_pin: *const raw::c_char,
-) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let old_pin = char_ptr_to_str(old_pin)?;
- let new_pin = char_ptr_to_str(new_pin)?;
-
+pub(super) fn change_secret_code(
+ currency: &str,
+ dewif: &str,
+ old_secret_code: &str,
+ member_wallet: bool,
+ secret_code_type: SecretCodeType,
+) -> Result, DubpError> {
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
dewif,
- old_pin,
+ old_secret_code,
)
.map_err(DubpError::DewifReadError)?;
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
- Ok(dup_crypto::dewif::write_dewif_v1_content(
- currency, &keypair, new_pin,
- ))
+ let new_secret_code = gen_secret_code(member_wallet, secret_code_type)?;
+
+ let dewif = dup_crypto::dewif::write_dewif_v1_content(currency, &keypair, &new_secret_code);
+ let pubkey = keypair.public_key().to_base58();
+ Ok(vec![dewif, new_secret_code, pubkey])
} else {
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
}
}
pub(super) fn gen_dewif(
- currency: *const raw::c_char,
- language: u32,
- mnemonic: *const raw::c_char,
- pin: *const raw::c_char,
-) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let mnemonic = char_ptr_to_str(mnemonic)?;
- let pin = char_ptr_to_str(pin)?;
-
+ currency: &str,
+ language: Language,
+ mnemonic: &str,
+ member_wallet: bool,
+ secret_code_type: SecretCodeType,
+) -> Result, DubpError> {
let currency = parse_currency(currency)?;
- let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
- .map_err(|_| DubpError::WrongLanguage)?;
+ let mnemonic =
+ Mnemonic::from_phrase(mnemonic, language).map_err(|_| DubpError::WrongLanguage)?;
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
let keypair = KeyPairFromSeed32Generator::generate(seed);
- Ok(dup_crypto::dewif::write_dewif_v1_content(
- currency, &keypair, pin,
- ))
+
+ let secret_code = gen_secret_code(member_wallet, secret_code_type)?;
+ let dewif = dup_crypto::dewif::write_dewif_v1_content(currency, &keypair, &secret_code);
+ let pubkey = keypair.public_key().to_base58();
+ Ok(vec![dewif, secret_code, pubkey])
}
-pub(super) fn get_pubkey(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- pin: *const raw::c_char,
-) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let pin = char_ptr_to_str(pin)?;
-
- let currency = parse_currency(currency)?;
+pub(super) fn get_pubkey(currency: Currency, dewif: &str, pin: &str) -> Result {
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
dewif,
@@ -104,17 +73,7 @@ pub(super) fn get_pubkey(
}
}
-pub(super) fn sign(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- pin: *const raw::c_char,
- msg: *const raw::c_char,
-) -> Result {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let pin = char_ptr_to_str(pin)?;
- let msg = char_ptr_to_str(msg)?;
-
+pub(super) fn sign(currency: &str, dewif: &str, pin: &str, msg: &str) -> Result {
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
@@ -130,22 +89,11 @@ pub(super) fn sign(
}
pub(super) fn sign_several(
- currency: *const raw::c_char,
- dewif: *const raw::c_char,
- pin: *const raw::c_char,
- msgs_len: usize,
- msgs: *const *const raw::c_char,
+ currency: &str,
+ dewif: &str,
+ pin: &str,
+ msgs: &[&str],
) -> Result, DubpError> {
- let currency = char_ptr_to_str(currency)?;
- let dewif = char_ptr_to_str(dewif)?;
- let pin = char_ptr_to_str(pin)?;
-
- let msgs_slice: &[*const raw::c_char] = unsafe { std::slice::from_raw_parts(msgs, msgs_len) };
- let mut msgs = Vec::with_capacity(msgs_len);
- for ptr_c_char in msgs_slice {
- msgs.push(char_ptr_to_str(*ptr_c_char)?);
- }
-
let currency = parse_currency(currency)?;
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
ExpectedCurrency::Specific(currency),
@@ -163,92 +111,3 @@ pub(super) fn sign_several(
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
}
}
-
-fn parse_currency(currency: &str) -> Result {
- let currency_code = match currency {
- "g1" => G1_CURRENCY,
- "g1-test" | "gt" => G1_TEST_CURRENCY,
- _ => return Err(DubpError::UnknownCurrencyName),
- };
- Ok(Currency::from(currency_code))
-}
-
-fn gen_pin2_inner(mut i: u32, pin: &mut String) {
- for _ in 0..2 {
- pin.push(to_char(i));
- i /= 35;
- }
-}
-fn gen_pin4_inner(mut i: u32, pin: &mut String) {
- for _ in 0..4 {
- pin.push(to_char(i));
- i /= 35;
- }
-}
-fn gen_pin6_inner(mut i: u32) -> String {
- let mut pin = String::new();
-
- for _ in 0..6 {
- pin.push(to_char(i));
- i /= 35;
- }
-
- pin
-}
-
-fn to_char(i: u32) -> char {
- match i % 35 {
- 0 => 'Z',
- 1 => '1',
- 2 => '2',
- 3 => '3',
- 4 => '4',
- 5 => '5',
- 6 => '6',
- 7 => '7',
- 8 => '8',
- 9 => '9',
- 10 => 'A',
- 11 => 'B',
- 12 => 'C',
- 13 => 'D',
- 14 => 'E',
- 15 => 'F',
- 16 => 'G',
- 17 => 'H',
- 18 => 'I',
- 19 => 'J',
- 20 => 'K',
- 21 => 'L',
- 22 => 'M',
- 23 => 'N',
- 24 => 'O',
- 25 => 'P',
- 26 => 'Q',
- 27 => 'R',
- 28 => 'S',
- 29 => 'T',
- 30 => 'U',
- 31 => 'V',
- 32 => 'W',
- 33 => 'X',
- 34 => 'Y',
- _ => unreachable!(),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_gen_pin_6() {
- assert_eq!("ZZZZZZ", &gen_pin6_inner(0));
- assert_eq!("YZZZZZ", &gen_pin6_inner(34));
- assert_eq!("Z1ZZZZ", &gen_pin6_inner(35));
- assert_eq!("ZZ1ZZZ", &gen_pin6_inner(1225));
- assert_eq!("2Z1ZZZ", &gen_pin6_inner(1227));
- assert_eq!("Z11ZZZ", &gen_pin6_inner(1260));
- assert_eq!("111ZZZ", &gen_pin6_inner(1261));
- }
-}
diff --git a/native/dubp_rs/src/error.rs b/native/dubp_rs/src/error.rs
new file mode 100644
index 0000000..b8f3d41
--- /dev/null
+++ b/native/dubp_rs/src/error.rs
@@ -0,0 +1,79 @@
+// Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::*;
+
+/// Dubp error
+#[derive(Debug, Error)]
+pub(crate) enum DubpError {
+ #[error("{0}")]
+ DewifReadError(DewifReadError),
+ #[error("I/O error: {0}")]
+ IoErr(io::Error),
+ #[error("Digits secret code forbid for member wallet")]
+ DigitsCodeForbidForMemberWallet,
+ #[error("A given parameter is null")]
+ NullParamErr,
+ #[error("fail to generate random bytes")]
+ RandErr,
+ #[error("Unknown currency name")]
+ UnknownCurrencyName,
+ #[error("Unknown language")]
+ UnknownLanguage,
+ #[error("{0}")]
+ Utf8Error(std::str::Utf8Error),
+ #[error("Wrong language")]
+ WrongLanguage,
+}
+
+impl From for DubpError {
+ fn from(e: io::Error) -> Self {
+ Self::IoErr(e)
+ }
+}
+
+pub(crate) struct DartRes(allo_isolate::ffi::DartCObject);
+impl DartRes {
+ pub(crate) fn err(e: E) -> allo_isolate::ffi::DartCObject {
+ vec![format!("DUBP_RS_ERROR: {}", e.to_string())].into_dart()
+ }
+}
+impl IntoDart for DartRes {
+ fn into_dart(self) -> allo_isolate::ffi::DartCObject {
+ self.0.into_dart()
+ }
+}
+impl From> for DartRes
+where
+ E: ToString,
+{
+ fn from(res: Result) -> Self {
+ match res {
+ Ok(string) => Self(string.into_dart()),
+ Err(e) => Self(format!("DUBP_RS_ERROR: {}", e.to_string()).into_dart()),
+ }
+ }
+}
+impl From, E>> for DartRes
+where
+ E: ToString,
+{
+ fn from(res: Result, E>) -> Self {
+ match res {
+ Ok(vec_string) => Self(vec_string.into_dart()),
+ Err(e) => Self(vec![format!("DUBP_RS_ERROR: {}", e.to_string())].into_dart()),
+ }
+ }
+}
diff --git a/native/dubp_rs/src/inputs.rs b/native/dubp_rs/src/inputs.rs
new file mode 100644
index 0000000..7959580
--- /dev/null
+++ b/native/dubp_rs/src/inputs.rs
@@ -0,0 +1,69 @@
+// Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::*;
+
+pub(crate) enum SecretCodeType {
+ Digits,
+ Letters,
+}
+impl From for SecretCodeType {
+ fn from(i: u32) -> Self {
+ if i == 0 {
+ SecretCodeType::Digits
+ } else {
+ SecretCodeType::Letters
+ }
+ }
+}
+
+pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
+ if c_char_ptr.is_null() {
+ Err(DubpError::NullParamErr)
+ } else {
+ unsafe { CStr::from_ptr(c_char_ptr).to_str() }.map_err(DubpError::Utf8Error)
+ }
+}
+
+pub(crate) fn char_ptr_prt_to_vec_str<'a>(
+ char_ptr_ptr: *const *const raw::c_char,
+ len: u32,
+) -> Result, DubpError> {
+ let len = len as usize;
+ let char_ptr_slice: &[*const raw::c_char] =
+ unsafe { std::slice::from_raw_parts(char_ptr_ptr, len) };
+ let mut str_vec = Vec::with_capacity(len);
+ for char_ptr in char_ptr_slice {
+ str_vec.push(char_ptr_to_str(*char_ptr)?);
+ }
+ Ok(str_vec)
+}
+
+pub(crate) fn parse_currency(currency: &str) -> Result {
+ let currency_code = match currency {
+ "g1" => G1_CURRENCY,
+ "g1-test" | "gt" => G1_TEST_CURRENCY,
+ _ => return Err(DubpError::UnknownCurrencyName),
+ };
+ Ok(Currency::from(currency_code))
+}
+
+pub(crate) fn u32_to_language(i: u32) -> Result {
+ match i {
+ 0 => Ok(Language::English),
+ 1 => Ok(Language::French),
+ _ => Err(DubpError::UnknownLanguage),
+ }
+}
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 8d2f03a..e0280e0 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -15,9 +15,17 @@
#![allow(clippy::missing_safety_doc, clippy::not_unsafe_ptr_arg_deref)]
+mod r#async;
mod dewif;
+mod error;
+mod inputs;
mod mnemonic;
+mod secret_code;
+use crate::error::{DartRes, DubpError};
+use crate::inputs::*;
+use crate::r#async::exec_async;
+use crate::secret_code::gen_secret_code;
use allo_isolate::{IntoDart, Isolate};
use dup_crypto::{
bases::b58::ToBase58,
@@ -28,84 +36,34 @@ use dup_crypto::{
},
mnemonic::{Language, Mnemonic, MnemonicType},
};
+use fast_threadpool::{ThreadPool, ThreadPoolConfig, ThreadPoolSyncHandler};
+use once_cell::sync::Lazy;
use std::{ffi::CStr, io, os::raw};
use thiserror::Error;
-/// Dubp error
-#[derive(Debug, Error)]
-pub enum DubpError {
- #[error("{0}")]
- DewifReadError(DewifReadError),
- #[error("I/O error: {0}")]
- IoErr(io::Error),
- #[error("A given parameter is null")]
- NullParamErr,
- #[error("fail to generate random bytes")]
- RandErr,
- #[error("Unknown currency name")]
- UnknownCurrencyName,
- #[error("Unknown language")]
- UnknownLanguage,
- #[error("{0}")]
- Utf8Error(std::str::Utf8Error),
- #[error("Wrong language")]
- WrongLanguage,
-}
-
-impl From for DubpError {
- fn from(e: io::Error) -> Self {
- Self::IoErr(e)
- }
-}
-
-struct DartRes(allo_isolate::ffi::DartCObject);
-impl IntoDart for DartRes {
- fn into_dart(self) -> allo_isolate::ffi::DartCObject {
- self.0.into_dart()
- }
-}
-impl From> for DartRes
-where
- E: ToString,
-{
- fn from(res: Result) -> Self {
- match res {
- Ok(string) => Self(vec![string].into_dart()),
- Err(e) => Self(vec![String::from("_"), e.to_string()].into_dart()),
- }
- }
-}
-impl From, E>> for DartRes
-where
- E: ToString,
-{
- fn from(res: Result, E>) -> Self {
- match res {
- Ok(vec_string) => Self(vec_string.into_dart()),
- Err(e) => Self(vec![String::with_capacity(0), e.to_string()].into_dart()),
- }
- }
-}
-
-pub(crate) fn char_ptr_to_str<'a>(c_char_ptr: *const raw::c_char) -> Result<&'a str, DubpError> {
- if c_char_ptr.is_null() {
- Err(DubpError::NullParamErr)
- } else {
- unsafe { CStr::from_ptr(c_char_ptr).to_str() }.map_err(DubpError::Utf8Error)
- }
-}
-
#[no_mangle]
-pub extern "C" fn change_dewif_pin(
+pub extern "C" fn change_dewif_secret_code(
port: i64,
currency: *const raw::c_char,
dewif: *const raw::c_char,
old_pin: *const raw::c_char,
- new_pin: *const raw::c_char,
+ member_wallet: u32,
+ secret_code_type: u32,
) {
- Isolate::new(port).post(DartRes::from(dewif::change_pin(
- currency, dewif, old_pin, new_pin,
- )));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let old_pin = char_ptr_to_str(old_pin)?;
+ let member_wallet = member_wallet != 0;
+ let secret_code_type = SecretCodeType::from(secret_code_type);
+ Ok((currency, dewif, old_pin, member_wallet, secret_code_type))
+ },
+ |(currency, dewif, old_pin, member_wallet, secret_code_type)| {
+ dewif::change_secret_code(currency, dewif, old_pin, member_wallet, secret_code_type)
+ },
+ )
}
#[no_mangle]
@@ -114,11 +72,35 @@ pub extern "C" fn gen_dewif(
currency: *const raw::c_char,
language: u32,
mnemonic: *const raw::c_char,
- pin: *const raw::c_char,
+ member_wallet: u32,
+ secret_code_type: u32,
) {
- Isolate::new(port).post(DartRes::from(dewif::gen_dewif(
- currency, language, mnemonic, pin,
- )));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let language = u32_to_language(language)?;
+ let mnemonic = char_ptr_to_str(mnemonic)?;
+ let member_wallet = member_wallet != 0;
+ let secret_code_type = SecretCodeType::from(secret_code_type);
+ Ok((
+ currency,
+ language,
+ mnemonic,
+ member_wallet,
+ secret_code_type,
+ ))
+ },
+ |(currency, language, mnemonic, member_wallet, secret_code_type)| {
+ dewif::gen_dewif(
+ currency,
+ language,
+ mnemonic,
+ member_wallet,
+ secret_code_type,
+ )
+ },
+ )
}
#[no_mangle]
@@ -126,21 +108,6 @@ pub extern "C" fn gen_mnemonic(port: i64, language: u32) {
Isolate::new(port).post(DartRes::from(mnemonic::gen_mnemonic(language)));
}
-#[no_mangle]
-pub extern "C" fn gen_pin6(port: i64) {
- Isolate::new(port).post(DartRes::from(dewif::gen_pin6()));
-}
-
-#[no_mangle]
-pub extern "C" fn gen_pin8(port: i64) {
- Isolate::new(port).post(DartRes::from(dewif::gen_pin8()));
-}
-
-#[no_mangle]
-pub extern "C" fn gen_pin10(port: i64) {
- Isolate::new(port).post(DartRes::from(dewif::gen_pin10()));
-}
-
#[no_mangle]
pub extern "C" fn get_dewif_pubkey(
port: i64,
@@ -148,7 +115,16 @@ pub extern "C" fn get_dewif_pubkey(
dewif: *const raw::c_char,
pin: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(dewif::get_pubkey(currency, dewif, pin)));
+ exec_async(
+ port,
+ || {
+ let currency = parse_currency(char_ptr_to_str(currency)?)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let pin = char_ptr_to_str(pin)?;
+ Ok((currency, dewif, pin))
+ },
+ |(currency, dewif, pin)| dewif::get_pubkey(currency, dewif, pin),
+ )
}
#[no_mangle]
@@ -157,10 +133,14 @@ pub extern "C" fn mnemonic_to_pubkey(
language: u32,
mnemonic_phrase: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(mnemonic::mnemonic_to_pubkey(
- language,
- mnemonic_phrase,
- )));
+ exec_async(
+ port,
+ || {
+ let mnemonic_phrase = char_ptr_to_str(mnemonic_phrase)?;
+ Ok((language, mnemonic_phrase))
+ },
+ |(language, mnemonic_phrase)| mnemonic::mnemonic_to_pubkey(language, mnemonic_phrase),
+ )
}
#[no_mangle]
@@ -171,7 +151,17 @@ pub extern "C" fn sign(
pin: *const raw::c_char,
msg: *const raw::c_char,
) {
- Isolate::new(port).post(DartRes::from(dewif::sign(currency, dewif, pin, msg)));
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let pin = char_ptr_to_str(pin)?;
+ let msg = char_ptr_to_str(msg)?;
+ Ok((currency, dewif, pin, msg))
+ },
+ |(currency, dewif, pin, msg)| dewif::sign(currency, dewif, pin, msg),
+ )
}
#[no_mangle]
@@ -180,16 +170,18 @@ pub extern "C" fn sign_several(
currency: *const raw::c_char,
dewif: *const raw::c_char,
pin: *const raw::c_char,
- msgs_len: usize,
+ msgs_len: u32,
msgs: *const *const raw::c_char,
) {
- Isolate::new(port).post(dewif::sign_several(currency, dewif, pin, msgs_len, msgs));
-}
-
-fn u32_to_language(i: u32) -> Result {
- match i {
- 0 => Ok(Language::English),
- 1 => Ok(Language::French),
- _ => Err(DubpError::UnknownLanguage),
- }
+ exec_async(
+ port,
+ || {
+ let currency = char_ptr_to_str(currency)?;
+ let dewif = char_ptr_to_str(dewif)?;
+ let pin = char_ptr_to_str(pin)?;
+ let msgs = char_ptr_prt_to_vec_str(msgs, msgs_len)?;
+ Ok((currency, dewif, pin, msgs))
+ },
+ |(currency, dewif, pin, msgs)| dewif::sign_several(currency, dewif, pin, &msgs),
+ )
}
diff --git a/native/dubp_rs/src/mnemonic.rs b/native/dubp_rs/src/mnemonic.rs
index ac17486..765427d 100644
--- a/native/dubp_rs/src/mnemonic.rs
+++ b/native/dubp_rs/src/mnemonic.rs
@@ -21,12 +21,7 @@ pub(super) fn gen_mnemonic(language: u32) -> Result {
Ok(mnemonic.phrase().to_owned())
}
-pub(super) fn mnemonic_to_pubkey(
- language: u32,
- mnemonic: *const raw::c_char,
-) -> Result {
- let mnemonic = char_ptr_to_str(mnemonic)?;
-
+pub(super) fn mnemonic_to_pubkey(language: u32, mnemonic: &str) -> Result {
let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
.map_err(|_| DubpError::WrongLanguage)?;
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
diff --git a/native/dubp_rs/src/secret_code.rs b/native/dubp_rs/src/secret_code.rs
new file mode 100644
index 0000000..f9581e4
--- /dev/null
+++ b/native/dubp_rs/src/secret_code.rs
@@ -0,0 +1,130 @@
+// Copyright (C) 2020 Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+use crate::*;
+
+pub(crate) fn gen_secret_code(
+ member_wallet: bool,
+ secret_code_type: SecretCodeType,
+) -> Result {
+ match secret_code_type {
+ SecretCodeType::Digits => {
+ if member_wallet {
+ Err(DubpError::DigitsCodeForbidForMemberWallet)
+ } else {
+ gen_random_digits(8)
+ }
+ }
+ SecretCodeType::Letters => {
+ if member_wallet {
+ gen_random_letters(10)
+ } else {
+ gen_random_letters(6)
+ }
+ }
+ }
+}
+
+fn gen_random_digits(n: usize) -> Result {
+ let mut digits_string = dup_crypto::rand::gen_u32()
+ .map_err(|_| DubpError::RandErr)?
+ .to_string();
+ digits_string.truncate(n);
+
+ if digits_string.len() == n {
+ Ok(digits_string)
+ } else {
+ let missing_digits = n - digits_string.len();
+ let mut digits_string_ = String::with_capacity(n);
+ for _ in 0..missing_digits {
+ digits_string_.push('0');
+ }
+ digits_string_.push_str(&digits_string);
+ Ok(digits_string_)
+ }
+}
+
+fn gen_random_letters(mut n: usize) -> Result {
+ let mut letters = String::with_capacity(n);
+ while n >= 6 {
+ letters.push_str(&gen_random_letters_inner(6)?);
+ n -= 6;
+ }
+ letters.push_str(&gen_random_letters_inner(n)?);
+
+ Ok(letters)
+}
+
+fn gen_random_letters_inner(n: usize) -> Result {
+ let mut i = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
+ let mut letters = String::new();
+
+ for _ in 0..n {
+ letters.push(to_char(i));
+ i /= 26;
+ }
+
+ Ok(letters)
+}
+
+fn to_char(i: u32) -> char {
+ match i % 26 {
+ 0 => 'A',
+ 1 => 'B',
+ 2 => 'C',
+ 3 => 'D',
+ 4 => 'E',
+ 5 => 'F',
+ 6 => 'G',
+ 7 => 'H',
+ 8 => 'I',
+ 9 => 'J',
+ 10 => 'K',
+ 11 => 'L',
+ 12 => 'M',
+ 13 => 'N',
+ 14 => 'O',
+ 15 => 'P',
+ 16 => 'Q',
+ 17 => 'R',
+ 18 => 'S',
+ 19 => 'T',
+ 20 => 'U',
+ 21 => 'V',
+ 22 => 'W',
+ 23 => 'X',
+ 24 => 'Y',
+ 25 => 'Z',
+ _ => unreachable!(),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_gen_random_digits() -> Result<(), DubpError> {
+ assert_eq!(gen_random_digits(8)?.len(), 8);
+ //println!("TMP: {}", gen_random_digits(8)?);
+ Ok(())
+ }
+ #[test]
+ fn test_gen_random_letters() -> Result<(), DubpError> {
+ assert_eq!(gen_random_letters(6)?.len(), 6);
+ //println!("TMP: {}", gen_random_letters(6)?);
+ Ok(())
+ }
+}
diff --git a/packages/dubp_rs/README.md b/packages/dubp_rs/README.md
index 305dcb4..2c27fe8 100644
--- a/packages/dubp_rs/README.md
+++ b/packages/dubp_rs/README.md
@@ -57,7 +57,7 @@ The project use [`dart-bindgen`](https://github.com/sunshine-protocol/dart-bindg
* 32bit emulator (`x86`/`i686` architecture)
```sh
-cargo make android-dev32
+cargo bd
```
* 64bit emulator (`x86_64` architecture)
@@ -71,7 +71,7 @@ cargo make android-dev
In the Root of the project simply run:
```sh
-cargo make
+cargo br
```
WARNING: This will take a lot of time because the Rust code will have to be recompiled for each different architecture, 4 times for android and 2 times for iOS!
@@ -113,7 +113,7 @@ static Future genWalletFromMnemonic({
String currency = "g1",
Language language = Language.english,
String mnemonic,
- PinLength pinLength = PinLength.six
+ SecretCodeType secretCodeType = SecretCodeType.letters
});
```
@@ -129,13 +129,13 @@ NewWallet new_wallet = await DubpRust.genWalletFromMnemonic(
);
```
-You can choose a different length for the pin code (6 by default):
+You can choose a different secret code type:
```dart
NewWallet new_wallet = await DubpRust.genWalletFromMnemonic(
language: Language.english,
mnemonic: "tongue cute mail fossil great frozen same social weasel impact brush kind",
- pinLength: PinLength.eight
+ secretCodeType: SecretCodeType.digits
);
```
@@ -164,9 +164,9 @@ String signature = await DubpRust.sign(
);
```
-### Change pin code
+### Change secret code
-You can change the pin code that encrypts the [DEWIF].
+You can change the secret code that encrypts the [DEWIF].
#### Function signature
@@ -175,7 +175,7 @@ static Future changeDewifPin({
String currency = "g1",
String dewif,
String oldPin,
- PinLength newPinLength = PinLength.six
+ SecretCodeType secretCodeType = SecretCodeType.letters
});
```
@@ -186,7 +186,7 @@ If the wallet is not dedicated to the Ğ1 currency, you must indicate the curren
```dart
NewWallet new_wallet = await DubpRust.changeDewifPin(
dewif: "AAAAARAAAAGfFDAs+jVZYkfhBlHZZ2fEQIvBqnG16g5+02cY18wSOjW0cUg2JV3SUTJYN2CrbQeRDwGazWnzSFBphchMmiL0",
- oldPin: "CDJ4UB",
+ oldPin: "CDJAUB",
);
```
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index a3384e8..e2f1d2e 100644
--- a/packages/dubp_rs/lib/dubp.dart
+++ b/packages/dubp_rs/lib/dubp.dart
@@ -19,7 +19,7 @@ class NewWallet {
/// DEWIF: Encrypted wallet
String dewif;
- /// Pin code
+ /// Secret code
String pin;
/// Public key
@@ -28,16 +28,13 @@ class NewWallet {
NewWallet._(this.dewif, this.pin, this.publicKey);
}
-/// Pin code length
-enum PinLength {
- /// 6 characters
- six,
+/// Secret code type
+enum SecretCodeType {
+ /// Digits
+ digits,
- /// 8 characters
- eight,
-
- /// 10 characters
- ten,
+ /// Letters
+ letters,
}
/// DUBP Rust utilities
@@ -55,7 +52,7 @@ class DubpRust {
static Future genMnemonic({Language language = Language.english}) {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.gen_mnemonic(
sendPort.nativePort,
language.index,
@@ -63,70 +60,27 @@ class DubpRust {
return completer.future;
}
- static Future _genPin(PinLength pinLength) {
- final completer = Completer();
- final sendPort =
- singleCompletePort(completer, callback: _handleErr);
- switch (pinLength) {
- case PinLength.ten:
- native.gen_pin10(
- sendPort.nativePort,
- );
- break;
- case PinLength.eight:
- native.gen_pin8(
- sendPort.nativePort,
- );
- break;
- case PinLength.six:
- default:
- native.gen_pin6(
- sendPort.nativePort,
- );
- break;
- }
- return completer.future;
- }
+ /// Change the secret code that encrypts the `dewif` keypair.
+ static Future changeDewifPin({
+ String currency = "g1",
+ String dewif,
+ String oldPin,
+ SecretCodeType secretCodeType = SecretCodeType.letters,
+ }) async {
+ final completer = Completer>();
+ final sendPort = singleCompletePort, List>(completer,
+ callback: _handleErrList);
+ native.change_dewif_secret_code(
+ sendPort.nativePort,
+ Utf8.toUtf8(currency),
+ Utf8.toUtf8(dewif),
+ Utf8.toUtf8(oldPin),
+ 0,
+ secretCodeType.index,
+ );
+ List newWallet = await completer.future;
- /// Change the pin code that encrypts the `dewif` keypair.
- static Future changeDewifPin(
- {String currency = "g1",
- String dewif,
- String oldPin,
- PinLength newPinLength = PinLength.six}) async {
- // pin
- String newPin = await _genPin(newPinLength);
- // dewif
- String newDewif;
- {
- final completer = Completer();
- final sendPort =
- singleCompletePort(completer, callback: _handleErr);
- native.change_dewif_pin(
- sendPort.nativePort,
- Utf8.toUtf8(currency),
- Utf8.toUtf8(dewif),
- Utf8.toUtf8(oldPin),
- Utf8.toUtf8(newPin),
- );
- newDewif = await completer.future;
- }
- // publicKey
- String publicKey;
- {
- final completer = Completer();
- final sendPort =
- singleCompletePort(completer, callback: _handleErr);
- native.get_dewif_pubkey(
- sendPort.nativePort,
- Utf8.toUtf8(currency),
- Utf8.toUtf8(newDewif),
- Utf8.toUtf8(newPin),
- );
- publicKey = await completer.future;
- }
-
- return Future.value(NewWallet._(newDewif, newPin, publicKey));
+ return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2]));
}
/// Generate a wallet from a mnemonic phrase.
@@ -136,42 +90,26 @@ class DubpRust {
///
/// If the wallet to be generated is not dedicated to the Ğ1 currency, you
/// must indicate the currency for which this wallet will be used.
- static Future genWalletFromMnemonic(
- {String currency = "g1",
- Language language = Language.english,
- String mnemonic,
- PinLength pinLength = PinLength.six}) async {
- // pin
- String pin = await _genPin(pinLength);
- // publicKey
- String publicKey;
- {
- final completer = Completer();
- final sendPort =
- singleCompletePort(completer, callback: _handleErr);
- native.mnemonic_to_pubkey(
- sendPort.nativePort,
- language.index,
- Utf8.toUtf8(mnemonic),
- );
- publicKey = await completer.future;
- }
- // dewif
- String dewif;
- {
- final completer = Completer();
- final sendPort =
- singleCompletePort(completer, callback: _handleErr);
- native.gen_dewif(
- sendPort.nativePort,
- Utf8.toUtf8(currency),
- language.index,
- Utf8.toUtf8(mnemonic),
- Utf8.toUtf8(pin),
- );
- dewif = await completer.future;
- }
- return Future.value(NewWallet._(dewif, pin, publicKey));
+ static Future genWalletFromMnemonic({
+ String currency = "g1",
+ Language language = Language.english,
+ String mnemonic,
+ SecretCodeType secretCodeType = SecretCodeType.letters,
+ }) async {
+ final completer = Completer>();
+ final sendPort = singleCompletePort, List>(completer,
+ callback: _handleErrList);
+ native.gen_dewif(
+ sendPort.nativePort,
+ Utf8.toUtf8(currency),
+ language.index,
+ Utf8.toUtf8(mnemonic),
+ 0,
+ secretCodeType.index,
+ );
+ List newWallet = await completer.future;
+
+ return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2]));
}
/// Get pulblic key (in base 58) of `dewif` keypair.
@@ -179,7 +117,7 @@ class DubpRust {
{String currency = "g1", String dewif, String pin}) async {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.get_dewif_pubkey(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -196,7 +134,7 @@ class DubpRust {
{String currency = "g1", String dewif, String pin, String message}) {
final completer = Completer();
final sendPort =
- singleCompletePort(completer, callback: _handleErr);
+ singleCompletePort(completer, callback: _handleErr);
native.sign(
sendPort.nativePort,
Utf8.toUtf8(currency),
@@ -243,21 +181,20 @@ class DubpRust {
return ptr;
}
- static String _handleErr(List res) {
- final List arr = res.cast();
- if (arr.length == 1) {
- return arr[0];
- } else {
- final error = arr[1];
+ static String _handleErr(String res) {
+ if (res.startsWith('DUBP_RS_ERROR: ')) {
+ final error = res;
print(error);
throw error;
+ } else {
+ return res;
}
}
static List _handleErrList(List res) {
final List arr = res.cast();
- if (arr.isNotEmpty && arr[0].isEmpty) {
- final error = arr[1];
+ if (arr.isNotEmpty && arr[0].startsWith('DUBP_RS_ERROR: ')) {
+ final error = arr[0];
print(error);
throw error;
} else {
diff --git a/pubspec.lock b/pubspec.lock
index 376b9d0..8446555 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -21,42 +21,42 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
- version: "2.5.0-nullsafety.3"
+ version: "2.5.0-nullsafety.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.3"
+ version: "2.1.0-nullsafety.1"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.5"
+ version: "1.1.0-nullsafety.3"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0-nullsafety.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.3"
+ version: "1.1.0-nullsafety.1"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.dartlang.org"
source: hosted
- version: "1.15.0-nullsafety.5"
+ version: "1.15.0-nullsafety.3"
connectivity:
dependency: transitive
description:
@@ -112,7 +112,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0-nullsafety.1"
ffi:
dependency: transitive
description:
@@ -282,27 +282,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
- js:
- dependency: transitive
- description:
- name: js
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.6.3-nullsafety.3"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
- version: "0.12.10-nullsafety.3"
+ version: "0.12.10-nullsafety.1"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0-nullsafety.6"
+ version: "1.3.0-nullsafety.3"
nested:
dependency: transitive
description:
@@ -330,7 +323,7 @@ packages:
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0-nullsafety.3"
+ version: "1.8.0-nullsafety.1"
path_provider:
dependency: "direct main"
description:
@@ -468,42 +461,42 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
- version: "1.8.0-nullsafety.4"
+ version: "1.8.0-nullsafety.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.dartlang.org"
source: hosted
- version: "1.10.0-nullsafety.6"
+ version: "1.10.0-nullsafety.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.3"
+ version: "2.1.0-nullsafety.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.1.0-nullsafety.3"
+ version: "1.1.0-nullsafety.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.dartlang.org"
source: hosted
- version: "1.2.0-nullsafety.3"
+ version: "1.2.0-nullsafety.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.19-nullsafety.6"
+ version: "0.2.19-nullsafety.2"
truncate:
dependency: "direct main"
description:
@@ -517,7 +510,7 @@ packages:
name: typed_data
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.0-nullsafety.5"
+ version: "1.3.0-nullsafety.3"
uuid:
dependency: transitive
description:
@@ -538,7 +531,7 @@ packages:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0-nullsafety.5"
+ version: "2.1.0-nullsafety.3"
websocket:
dependency: transitive
description:
@@ -575,5 +568,5 @@ packages:
source: hosted
version: "2.2.1"
sdks:
- dart: ">=2.12.0-0.0 <3.0.0"
+ dart: ">=2.10.0-110 <2.11.0"
flutter: ">=1.22.0 <2.0.0"