feat(dubp): replace param PinLen by SecretCodeType
This commit is contained in:
parent
63dd4ee59b
commit
78740e13ec
|
@ -15,48 +15,26 @@
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub(super) fn gen_pin6() -> Result<String, DubpError> {
|
pub(super) fn change_secret_code(
|
||||||
let i = dup_crypto::rand::gen_u32().map_err(|_| DubpError::RandErr)?;
|
|
||||||
Ok(gen_pin6_inner(i))
|
|
||||||
}
|
|
||||||
pub(super) fn gen_pin8() -> Result<String, DubpError> {
|
|
||||||
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<String, DubpError> {
|
|
||||||
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: &str,
|
currency: &str,
|
||||||
dewif: &str,
|
dewif: &str,
|
||||||
old_pin: &str,
|
old_secret_code: &str,
|
||||||
member_wallet: bool,
|
member_wallet: bool,
|
||||||
|
secret_code_type: SecretCodeType,
|
||||||
) -> Result<Vec<String>, DubpError> {
|
) -> Result<Vec<String>, DubpError> {
|
||||||
let currency = parse_currency(currency)?;
|
let currency = parse_currency(currency)?;
|
||||||
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
let mut keypairs = dup_crypto::dewif::read_dewif_file_content(
|
||||||
ExpectedCurrency::Specific(currency),
|
ExpectedCurrency::Specific(currency),
|
||||||
dewif,
|
dewif,
|
||||||
old_pin,
|
old_secret_code,
|
||||||
)
|
)
|
||||||
.map_err(DubpError::DewifReadError)?;
|
.map_err(DubpError::DewifReadError)?;
|
||||||
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
if let Some(KeyPairEnum::Ed25519(keypair)) = keypairs.next() {
|
||||||
let new_pin = if member_wallet {
|
let new_secret_code = gen_secret_code(member_wallet, secret_code_type)?;
|
||||||
gen_pin10()?
|
|
||||||
} else {
|
|
||||||
gen_pin6()?
|
|
||||||
};
|
|
||||||
|
|
||||||
let dewif = dup_crypto::dewif::write_dewif_v1_content(currency, &keypair, &new_pin);
|
let dewif = dup_crypto::dewif::write_dewif_v1_content(currency, &keypair, &new_secret_code);
|
||||||
let pubkey = keypair.public_key().to_base58();
|
let pubkey = keypair.public_key().to_base58();
|
||||||
Ok(vec![dewif, new_pin, pubkey])
|
Ok(vec![dewif, new_secret_code, pubkey])
|
||||||
} else {
|
} else {
|
||||||
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
||||||
}
|
}
|
||||||
|
@ -64,24 +42,21 @@ pub(super) fn change_pin(
|
||||||
|
|
||||||
pub(super) fn gen_dewif(
|
pub(super) fn gen_dewif(
|
||||||
currency: &str,
|
currency: &str,
|
||||||
language: u32,
|
language: Language,
|
||||||
mnemonic: &str,
|
mnemonic: &str,
|
||||||
member_wallet: bool,
|
member_wallet: bool,
|
||||||
|
secret_code_type: SecretCodeType,
|
||||||
) -> Result<Vec<String>, DubpError> {
|
) -> Result<Vec<String>, DubpError> {
|
||||||
let currency = parse_currency(currency)?;
|
let currency = parse_currency(currency)?;
|
||||||
let mnemonic = Mnemonic::from_phrase(mnemonic, u32_to_language(language)?)
|
let mnemonic =
|
||||||
.map_err(|_| DubpError::WrongLanguage)?;
|
Mnemonic::from_phrase(mnemonic, language).map_err(|_| DubpError::WrongLanguage)?;
|
||||||
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
|
let seed = dup_crypto::mnemonic::mnemonic_to_seed(&mnemonic);
|
||||||
let keypair = KeyPairFromSeed32Generator::generate(seed);
|
let keypair = KeyPairFromSeed32Generator::generate(seed);
|
||||||
|
|
||||||
let pin = if member_wallet {
|
let secret_code = gen_secret_code(member_wallet, secret_code_type)?;
|
||||||
gen_pin10()?
|
let dewif = dup_crypto::dewif::write_dewif_v1_content(currency, &keypair, &secret_code);
|
||||||
} else {
|
|
||||||
gen_pin6()?
|
|
||||||
};
|
|
||||||
let dewif = dup_crypto::dewif::write_dewif_v1_content(currency, &keypair, &pin);
|
|
||||||
let pubkey = keypair.public_key().to_base58();
|
let pubkey = keypair.public_key().to_base58();
|
||||||
Ok(vec![dewif, pin, pubkey])
|
Ok(vec![dewif, secret_code, pubkey])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn get_pubkey(currency: Currency, dewif: &str, pin: &str) -> Result<String, DubpError> {
|
pub(super) fn get_pubkey(currency: Currency, dewif: &str, pin: &str) -> Result<String, DubpError> {
|
||||||
|
@ -136,83 +111,3 @@ pub(super) fn sign_several(
|
||||||
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ pub(crate) enum DubpError {
|
||||||
DewifReadError(DewifReadError),
|
DewifReadError(DewifReadError),
|
||||||
#[error("I/O error: {0}")]
|
#[error("I/O error: {0}")]
|
||||||
IoErr(io::Error),
|
IoErr(io::Error),
|
||||||
|
#[error("Digits secret code forbid for member wallet")]
|
||||||
|
DigitsCodeForbidForMemberWallet,
|
||||||
#[error("A given parameter is null")]
|
#[error("A given parameter is null")]
|
||||||
NullParamErr,
|
NullParamErr,
|
||||||
#[error("fail to generate random bytes")]
|
#[error("fail to generate random bytes")]
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub(crate) enum SecretCodeType {
|
||||||
|
Digits,
|
||||||
|
Letters,
|
||||||
|
}
|
||||||
|
impl From<u32> 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<Vec<&'a str>, 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<Currency, DubpError> {
|
||||||
|
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<Language, DubpError> {
|
||||||
|
match i {
|
||||||
|
0 => Ok(Language::English),
|
||||||
|
1 => Ok(Language::French),
|
||||||
|
_ => Err(DubpError::UnknownLanguage),
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,10 +18,14 @@
|
||||||
mod r#async;
|
mod r#async;
|
||||||
mod dewif;
|
mod dewif;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod inputs;
|
||||||
mod mnemonic;
|
mod mnemonic;
|
||||||
|
mod secret_code;
|
||||||
|
|
||||||
use crate::error::{DartRes, DubpError};
|
use crate::error::{DartRes, DubpError};
|
||||||
|
use crate::inputs::*;
|
||||||
use crate::r#async::exec_async;
|
use crate::r#async::exec_async;
|
||||||
|
use crate::secret_code::gen_secret_code;
|
||||||
use allo_isolate::{IntoDart, Isolate};
|
use allo_isolate::{IntoDart, Isolate};
|
||||||
use dup_crypto::{
|
use dup_crypto::{
|
||||||
bases::b58::ToBase58,
|
bases::b58::ToBase58,
|
||||||
|
@ -37,52 +41,14 @@ use once_cell::sync::Lazy;
|
||||||
use std::{ffi::CStr, io, os::raw};
|
use std::{ffi::CStr, io, os::raw};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn char_ptr_prt_to_vec_str<'a>(
|
|
||||||
char_ptr_ptr: *const *const raw::c_char,
|
|
||||||
len: u32,
|
|
||||||
) -> Result<Vec<&'a str>, 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<Currency, DubpError> {
|
|
||||||
let currency_code = match currency {
|
|
||||||
"g1" => G1_CURRENCY,
|
|
||||||
"g1-test" | "gt" => G1_TEST_CURRENCY,
|
|
||||||
_ => return Err(DubpError::UnknownCurrencyName),
|
|
||||||
};
|
|
||||||
Ok(Currency::from(currency_code))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u32_to_language(i: u32) -> Result<Language, DubpError> {
|
|
||||||
match i {
|
|
||||||
0 => Ok(Language::English),
|
|
||||||
1 => Ok(Language::French),
|
|
||||||
_ => Err(DubpError::UnknownLanguage),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn change_dewif_pin(
|
pub extern "C" fn change_dewif_secret_code(
|
||||||
port: i64,
|
port: i64,
|
||||||
currency: *const raw::c_char,
|
currency: *const raw::c_char,
|
||||||
dewif: *const raw::c_char,
|
dewif: *const raw::c_char,
|
||||||
old_pin: *const raw::c_char,
|
old_pin: *const raw::c_char,
|
||||||
member_wallet: u32,
|
member_wallet: u32,
|
||||||
|
secret_code_type: u32,
|
||||||
) {
|
) {
|
||||||
exec_async(
|
exec_async(
|
||||||
port,
|
port,
|
||||||
|
@ -91,10 +57,11 @@ pub extern "C" fn change_dewif_pin(
|
||||||
let dewif = char_ptr_to_str(dewif)?;
|
let dewif = char_ptr_to_str(dewif)?;
|
||||||
let old_pin = char_ptr_to_str(old_pin)?;
|
let old_pin = char_ptr_to_str(old_pin)?;
|
||||||
let member_wallet = member_wallet != 0;
|
let member_wallet = member_wallet != 0;
|
||||||
Ok((currency, dewif, old_pin, member_wallet))
|
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)| {
|
|(currency, dewif, old_pin, member_wallet, secret_code_type)| {
|
||||||
dewif::change_pin(currency, dewif, old_pin, member_wallet)
|
dewif::change_secret_code(currency, dewif, old_pin, member_wallet, secret_code_type)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -106,17 +73,32 @@ pub extern "C" fn gen_dewif(
|
||||||
language: u32,
|
language: u32,
|
||||||
mnemonic: *const raw::c_char,
|
mnemonic: *const raw::c_char,
|
||||||
member_wallet: u32,
|
member_wallet: u32,
|
||||||
|
secret_code_type: u32,
|
||||||
) {
|
) {
|
||||||
exec_async(
|
exec_async(
|
||||||
port,
|
port,
|
||||||
|| {
|
|| {
|
||||||
let currency = char_ptr_to_str(currency)?;
|
let currency = char_ptr_to_str(currency)?;
|
||||||
|
let language = u32_to_language(language)?;
|
||||||
let mnemonic = char_ptr_to_str(mnemonic)?;
|
let mnemonic = char_ptr_to_str(mnemonic)?;
|
||||||
let member_wallet = member_wallet != 0;
|
let member_wallet = member_wallet != 0;
|
||||||
Ok((currency, language, mnemonic, member_wallet))
|
let secret_code_type = SecretCodeType::from(secret_code_type);
|
||||||
|
Ok((
|
||||||
|
currency,
|
||||||
|
language,
|
||||||
|
mnemonic,
|
||||||
|
member_wallet,
|
||||||
|
secret_code_type,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
|(currency, language, mnemonic, member_wallet)| {
|
|(currency, language, mnemonic, member_wallet, secret_code_type)| {
|
||||||
dewif::gen_dewif(currency, language, mnemonic, member_wallet)
|
dewif::gen_dewif(
|
||||||
|
currency,
|
||||||
|
language,
|
||||||
|
mnemonic,
|
||||||
|
member_wallet,
|
||||||
|
secret_code_type,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -126,21 +108,6 @@ pub extern "C" fn gen_mnemonic(port: i64, language: u32) {
|
||||||
Isolate::new(port).post(DartRes::from(mnemonic::gen_mnemonic(language)));
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn get_dewif_pubkey(
|
pub extern "C" fn get_dewif_pubkey(
|
||||||
port: i64,
|
port: i64,
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
pub(crate) fn gen_secret_code(
|
||||||
|
member_wallet: bool,
|
||||||
|
secret_code_type: SecretCodeType,
|
||||||
|
) -> Result<String, DubpError> {
|
||||||
|
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<String, DubpError> {
|
||||||
|
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<String, DubpError> {
|
||||||
|
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<String, DubpError> {
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ class NewWallet {
|
||||||
/// DEWIF: Encrypted wallet
|
/// DEWIF: Encrypted wallet
|
||||||
String dewif;
|
String dewif;
|
||||||
|
|
||||||
/// Pin code
|
/// Secret code
|
||||||
String pin;
|
String pin;
|
||||||
|
|
||||||
/// Public key
|
/// Public key
|
||||||
|
@ -28,16 +28,13 @@ class NewWallet {
|
||||||
NewWallet._(this.dewif, this.pin, this.publicKey);
|
NewWallet._(this.dewif, this.pin, this.publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pin code length
|
/// Secret code type
|
||||||
enum PinLength {
|
enum SecretCodeType {
|
||||||
/// 6 characters
|
/// Digits
|
||||||
six,
|
digits,
|
||||||
|
|
||||||
/// 8 characters
|
/// Letters
|
||||||
eight,
|
letters,
|
||||||
|
|
||||||
/// 10 characters
|
|
||||||
ten,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DUBP Rust utilities
|
/// DUBP Rust utilities
|
||||||
|
@ -63,21 +60,23 @@ class DubpRust {
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the pin code that encrypts the `dewif` keypair.
|
/// Change the secret code that encrypts the `dewif` keypair.
|
||||||
static Future<NewWallet> changeDewifPin(
|
static Future<NewWallet> changeDewifPin({
|
||||||
{String currency = "g1",
|
String currency = "g1",
|
||||||
String dewif,
|
String dewif,
|
||||||
String oldPin,
|
String oldPin,
|
||||||
PinLength newPinLength = PinLength.six}) async {
|
SecretCodeType secretCodeType = SecretCodeType.letters,
|
||||||
|
}) async {
|
||||||
final completer = Completer<List<String>>();
|
final completer = Completer<List<String>>();
|
||||||
final sendPort = singleCompletePort<List<String>, List>(completer,
|
final sendPort = singleCompletePort<List<String>, List>(completer,
|
||||||
callback: _handleErrList);
|
callback: _handleErrList);
|
||||||
native.change_dewif_pin(
|
native.change_dewif_secret_code(
|
||||||
sendPort.nativePort,
|
sendPort.nativePort,
|
||||||
Utf8.toUtf8(currency),
|
Utf8.toUtf8(currency),
|
||||||
Utf8.toUtf8(dewif),
|
Utf8.toUtf8(dewif),
|
||||||
Utf8.toUtf8(oldPin),
|
Utf8.toUtf8(oldPin),
|
||||||
0,
|
0,
|
||||||
|
secretCodeType.index,
|
||||||
);
|
);
|
||||||
List<String> newWallet = await completer.future;
|
List<String> newWallet = await completer.future;
|
||||||
|
|
||||||
|
@ -91,11 +90,12 @@ class DubpRust {
|
||||||
///
|
///
|
||||||
/// If the wallet to be generated is not dedicated to the Ğ1 currency, you
|
/// 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.
|
/// must indicate the currency for which this wallet will be used.
|
||||||
static Future<NewWallet> genWalletFromMnemonic(
|
static Future<NewWallet> genWalletFromMnemonic({
|
||||||
{String currency = "g1",
|
String currency = "g1",
|
||||||
Language language = Language.english,
|
Language language = Language.english,
|
||||||
String mnemonic,
|
String mnemonic,
|
||||||
PinLength pinLength = PinLength.six}) async {
|
SecretCodeType secretCodeType = SecretCodeType.letters,
|
||||||
|
}) async {
|
||||||
final completer = Completer<List<String>>();
|
final completer = Completer<List<String>>();
|
||||||
final sendPort = singleCompletePort<List<String>, List>(completer,
|
final sendPort = singleCompletePort<List<String>, List>(completer,
|
||||||
callback: _handleErrList);
|
callback: _handleErrList);
|
||||||
|
@ -105,6 +105,7 @@ class DubpRust {
|
||||||
language.index,
|
language.index,
|
||||||
Utf8.toUtf8(mnemonic),
|
Utf8.toUtf8(mnemonic),
|
||||||
0,
|
0,
|
||||||
|
secretCodeType.index,
|
||||||
);
|
);
|
||||||
List<String> newWallet = await completer.future;
|
List<String> newWallet = await completer.future;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue