diff --git a/Cargo.lock b/Cargo.lock index 9c46888..d83c496 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -261,9 +261,9 @@ dependencies = [ [[package]] name = "dup-crypto" -version = "0.41.0" +version = "0.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6b6eb9f9a9e92e70515090be3733857966f2a635564f36e78af047e63a1bf" +checksum = "e69f621e9575ed2647fb67a9e8a8d8d5cc8d9281dec2fc848c7619a159501562" dependencies = [ "aes", "arrayvec", diff --git a/native/dubp_rs/Cargo.toml b/native/dubp_rs/Cargo.toml index 3d0519e..e51d6d3 100644 --- a/native/dubp_rs/Cargo.toml +++ b/native/dubp_rs/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["rlib"] [dependencies] allo-isolate = "0.1.6" -dup-crypto = { version = "0.41.0", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] } +dup-crypto = { version = "0.41.1", features = ["bip32-ed25519", "dewif", "mnemonic", "mnemonic_french", "rand", "scrypt"] } fast-threadpool = { version = "0.3.0", default-features = false } once_cell = { version = "1.3.1", default-features = false, features = ["std"] } thiserror = "1.0.23" diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs index 0c03efa..c017d69 100644 --- a/native/dubp_rs/src/dewif.rs +++ b/native/dubp_rs/src/dewif.rs @@ -19,14 +19,12 @@ pub mod classic; use crate::*; pub(super) fn change_secret_code( - currency: &str, dewif: &str, old_secret_code: &str, member_wallet: bool, secret_code_type: SecretCodeType, system_memory: i64, ) -> Result, DubpError> { - let currency = parse_currency(currency)?; let new_log_n = log_n(system_memory); let new_secret_code = gen_secret_code(member_wallet, secret_code_type, new_log_n)?; @@ -34,9 +32,7 @@ pub(super) fn change_secret_code( dup_crypto::dewif::change_dewif_passphrase(dewif, old_secret_code, &new_secret_code) .map_err(DubpError::DewifReadError)?; - let pubkey = get_pubkey(currency, &new_dewif, &new_secret_code)?; - - Ok(vec![new_dewif, new_secret_code, pubkey]) + Ok(vec![new_dewif, new_secret_code]) } pub(super) fn gen_dewif( @@ -56,28 +52,60 @@ pub(super) fn gen_dewif( let log_n = log_n(system_memory); let secret_code = gen_secret_code(member_wallet, secret_code_type, log_n)?; - let (dewif, pubkey) = match wallet_type { + let dewif = match wallet_type { WalletType::Bip32Ed25519 => { let keypair = dup_crypto::keys::ed25519::bip32::KeyPair::from_seed(seed.clone()); let pubkey = keypair.public_key(); - let dewif = dup_crypto::dewif::write_dewif_v4_content( - currency, - log_n, - &secret_code, - &pubkey, - seed, - ); - (dewif, pubkey.to_base58()) + dup_crypto::dewif::write_dewif_v4_content(currency, log_n, &secret_code, &pubkey, seed) } WalletType::Ed25519 => { let keypair = KeyPairFromSeed32Generator::generate(seed); - let dewif = - dup_crypto::dewif::write_dewif_v3_content(currency, &keypair, log_n, &secret_code); - (dewif, keypair.public_key().to_base58()) + dup_crypto::dewif::write_dewif_v3_content(currency, &keypair, log_n, &secret_code) } }; - Ok(vec![dewif, secret_code, pubkey]) + Ok(vec![dewif, secret_code]) +} + +pub(super) fn get_dewif_meta( + dewif: &str, + member_wallet: bool, + secret_code_type: SecretCodeType, +) -> Result, DubpError> { + let dup_crypto::dewif::DewifMeta { + currency, + log_n, + version, + } = dup_crypto::dewif::read_dewif_meta(dewif).map_err(DubpError::DewifReadError)?; + + let secret_code_len = + crate::secret_code::compute_secret_code_len(member_wallet, secret_code_type, log_n)?; + + Ok(vec![ + currency.to_string(), + secret_code_len.to_string(), + version.to_string(), + ]) +} + +pub(super) fn get_pubkey( + currency: Currency, + dewif: &str, + secret_code: &str, +) -> Result { + let mut keypairs = dup_crypto::dewif::read_dewif_file_content( + ExpectedCurrency::Specific(currency), + dewif, + &secret_code.to_ascii_uppercase(), + ) + .map_err(DubpError::DewifReadError)?; + + match keypairs.next() { + Some(KeyPairEnum::Ed25519(keypair)) => Ok(keypair.public_key().to_base58()), + Some(KeyPairEnum::Bip32Ed25519(_)) => Err(DubpError::GetMasterPubkeyOfHdWallet), + Some(_) => Err(DubpError::UnsupportedDewifVersion), + None => Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)), + } } pub(super) fn get_secret_code_len( @@ -99,24 +127,6 @@ pub(super) fn get_secret_code_len( )?) } -pub(super) fn get_pubkey( - currency: Currency, - dewif: &str, - secret_code: &str, -) -> Result { - let mut keypairs = dup_crypto::dewif::read_dewif_file_content( - ExpectedCurrency::Specific(currency), - dewif, - &secret_code.to_ascii_uppercase(), - ) - .map_err(DubpError::DewifReadError)?; - if let Some(keypair) = keypairs.next() { - Ok(keypair.public_key().to_base58()) - } else { - Err(DubpError::DewifReadError(DewifReadError::CorruptedContent)) - } -} - pub(crate) fn log_n(system_memory: i64) -> u8 { if system_memory > 3_000_000_000 { 15 diff --git a/native/dubp_rs/src/error.rs b/native/dubp_rs/src/error.rs index 2f55f01..379a48c 100644 --- a/native/dubp_rs/src/error.rs +++ b/native/dubp_rs/src/error.rs @@ -28,6 +28,8 @@ pub(crate) enum DubpError { InvalidDerivationIndex(InvalidDerivationIndex), #[error("Digits secret code forbid for member wallet")] DigitsCodeForbidForMemberWallet, + #[error("It is forbidden to retrieve the master public key of an HD wallet.")] + GetMasterPubkeyOfHdWallet, #[error("this wallet is not an HD wallet")] NotHdWallet, #[error("this account index is not a transparent account index")] @@ -40,6 +42,8 @@ pub(crate) enum DubpError { UnknownCurrencyName, #[error("Unknown language")] UnknownLanguage, + #[error("Unsupported DEWIF version")] + UnsupportedDewifVersion, #[error("{0}")] Utf8Error(std::str::Utf8Error), #[error("Wrong language")] diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs index 3a319ae..6109089 100644 --- a/native/dubp_rs/src/lib.rs +++ b/native/dubp_rs/src/lib.rs @@ -45,9 +45,8 @@ use thiserror::Error; #[no_mangle] 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, + old_secret_code: *const raw::c_char, member_wallet: u32, secret_code_type: u32, system_memory: i64, @@ -55,25 +54,22 @@ pub extern "C" fn change_dewif_secret_code( 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 old_secret_code = char_ptr_to_str(old_secret_code)?; let member_wallet = member_wallet != 0; let secret_code_type = SecretCodeType::from(secret_code_type); Ok(( - currency, dewif, - old_pin, + old_secret_code, member_wallet, secret_code_type, system_memory, )) }, - |(currency, dewif, old_pin, member_wallet, secret_code_type, system_memory)| { + |(dewif, old_secret_code, member_wallet, secret_code_type, system_memory)| { dewif::change_secret_code( - currency, dewif, - old_pin, + old_secret_code, member_wallet, secret_code_type, system_memory, @@ -180,6 +176,27 @@ pub extern "C" fn gen_mnemonic(port: i64, language: u32) { } #[no_mangle] +pub extern "C" fn get_dewif_meta( + port: i64, + dewif: *const raw::c_char, + member_wallet: u32, + secret_code_type: u32, +) { + exec_async( + port, + || { + let dewif = char_ptr_to_str(dewif)?; + let member_wallet = member_wallet != 0; + let secret_code_type = SecretCodeType::from(secret_code_type); + Ok((dewif, member_wallet, secret_code_type)) + }, + |(dewif, member_wallet, secret_code_type)| { + dewif::get_dewif_meta(dewif, member_wallet, secret_code_type) + }, + ) +} + +#[no_mangle] pub extern "C" fn get_dewif_secret_code_len( dewif: *const raw::c_char, member_wallet: u32, diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart index c80fafd..da50c41 100644 --- a/packages/dubp_rs/lib/dubp.dart +++ b/packages/dubp_rs/lib/dubp.dart @@ -6,6 +6,29 @@ import "package:system_info/system_info.dart"; import 'ffi.dart' as native; +/// DEWIF meta data +class DewifMetaData { + /// Currency name + String currency; + + /// Secret code length + int secretCodeLen; + + /// DEWIF version + int version; + + /// Wallet type + WalletType walletType; + + DewifMetaData._(this.currency, this.secretCodeLen, this.version) { + if (version == 4) { + walletType = WalletType.bip32Ed25519; + } else { + walletType = WalletType.ed25519; + } + } +} + /// Language enum Language { /// English @@ -23,10 +46,7 @@ class NewWallet { /// Secret code String pin; - /// Public key - String publicKey; - - NewWallet._(this.dewif, this.pin, this.publicKey); + NewWallet._(this.dewif, this.pin); } /// Secret code type @@ -60,7 +80,6 @@ class DubpRust { /// Change the secret code that encrypts the `dewif` keypair. static Future changeDewifPin({ - String currency = "g1", String dewif, String oldPin, SecretCodeType secretCodeType = SecretCodeType.letters, @@ -72,7 +91,6 @@ class DubpRust { callback: _handleErrList); native.change_dewif_secret_code( sendPort.nativePort, - Utf8.toUtf8(currency), Utf8.toUtf8(dewif), Utf8.toUtf8(oldPin), 0, @@ -81,7 +99,7 @@ class DubpRust { ); List newWallet = await completer.future; - return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2])); + return Future.value(NewWallet._(newWallet[0], newWallet[1])); } /// Generate a random mnemonic @@ -122,7 +140,7 @@ class DubpRust { ); List newWallet = await completer.future; - return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2])); + return Future.value(NewWallet._(newWallet[0], newWallet[1])); } /// Generate a wallet from a mnemonic phrase. @@ -157,7 +175,7 @@ class DubpRust { ); List newWallet = await completer.future; - return Future.value(NewWallet._(newWallet[0], newWallet[1], newWallet[2])); + return Future.value(NewWallet._(newWallet[0], newWallet[1])); } //get_bip32_dewif_accounts_pubkeys @@ -181,6 +199,21 @@ class DubpRust { return completer.future; } + /// Get `dewif` keypair meta data. + static Future getDewifMetaData( + {String dewif, + SecretCodeType secretCodeType = SecretCodeType.letters}) async { + final completer = Completer>(); + final sendPort = singleCompletePort, List>(completer, + callback: _handleErrList); + native.get_dewif_meta( + sendPort.nativePort, Utf8.toUtf8(dewif), 0, secretCodeType.index); + List dewifMetaData = await completer.future; + + return Future.value(DewifMetaData._(dewifMetaData[0], + int.parse(dewifMetaData[1]), int.parse(dewifMetaData[2]))); + } + /// Get public key (in base 58) of `dewif` keypair. static Future getDewifPublicKey( {String currency = "g1", String dewif, String pin}) async {