diff --git a/native/dubp_rs/src/dewif.rs b/native/dubp_rs/src/dewif.rs
index 6fe856aa66d812d1ccbc030cd6061d550bf1ae01..a7905e38e2b4118c65c4b7d4884861334014ef46 100644
--- a/native/dubp_rs/src/dewif.rs
+++ b/native/dubp_rs/src/dewif.rs
@@ -15,48 +15,26 @@
 
 use crate::*;
 
-pub(super) fn gen_pin6() -> Result<String, DubpError> {
-    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(
+pub(super) fn change_secret_code(
     currency: &str,
     dewif: &str,
-    old_pin: &str,
+    old_secret_code: &str,
     member_wallet: bool,
+    secret_code_type: SecretCodeType,
 ) -> Result<Vec<String>, 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() {
-        let new_pin = if member_wallet {
-            gen_pin10()?
-        } else {
-            gen_pin6()?
-        };
+        let new_secret_code = gen_secret_code(member_wallet, secret_code_type)?;
 
-        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();
-        Ok(vec![dewif, new_pin, pubkey])
+        Ok(vec![dewif, new_secret_code, pubkey])
     } else {
         Err(DubpError::DewifReadError(DewifReadError::CorruptedContent))
     }
@@ -64,24 +42,21 @@ pub(super) fn change_pin(
 
 pub(super) fn gen_dewif(
     currency: &str,
-    language: u32,
+    language: Language,
     mnemonic: &str,
     member_wallet: bool,
+    secret_code_type: SecretCodeType,
 ) -> Result<Vec<String>, 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);
 
-    let pin = if member_wallet {
-        gen_pin10()?
-    } else {
-        gen_pin6()?
-    };
-    let dewif = 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, pin, pubkey])
+    Ok(vec![dewif, secret_code, pubkey])
 }
 
 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))
     }
 }
-
-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
index 63bd5ec91b8e4e3043bf93a3a5037815ac4bde49..b8f3d415493b47fa0651a5ad693d3eb0f309bad2 100644
--- a/native/dubp_rs/src/error.rs
+++ b/native/dubp_rs/src/error.rs
@@ -22,6 +22,8 @@ pub(crate) enum DubpError {
     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")]
diff --git a/native/dubp_rs/src/inputs.rs b/native/dubp_rs/src/inputs.rs
new file mode 100644
index 0000000000000000000000000000000000000000..795958027daae86072d81e5fe9219b5efa08e348
--- /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 <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),
+    }
+}
diff --git a/native/dubp_rs/src/lib.rs b/native/dubp_rs/src/lib.rs
index 65be0566f194792556e59b275df58e8fca28ab8d..e0280e0d318073c39c40aa6912489400cede8d09 100644
--- a/native/dubp_rs/src/lib.rs
+++ b/native/dubp_rs/src/lib.rs
@@ -18,10 +18,14 @@
 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,
@@ -37,52 +41,14 @@ use once_cell::sync::Lazy;
 use std::{ffi::CStr, io, os::raw};
 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]
-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,
     member_wallet: u32,
+    secret_code_type: u32,
 ) {
     exec_async(
         port,
@@ -91,10 +57,11 @@ pub extern "C" fn change_dewif_pin(
             let dewif = char_ptr_to_str(dewif)?;
             let old_pin = char_ptr_to_str(old_pin)?;
             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)| {
-            dewif::change_pin(currency, dewif, old_pin, member_wallet)
+        |(currency, dewif, old_pin, member_wallet, secret_code_type)| {
+            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,
     mnemonic: *const raw::c_char,
     member_wallet: u32,
+    secret_code_type: u32,
 ) {
     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;
-            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)| {
-            dewif::gen_dewif(currency, language, mnemonic, member_wallet)
+        |(currency, language, mnemonic, member_wallet, secret_code_type)| {
+            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)));
 }
 
-#[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,
diff --git a/native/dubp_rs/src/secret_code.rs b/native/dubp_rs/src/secret_code.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f9581e441684934f652c8e3d081921f28c3b25a7
--- /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 <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(())
+    }
+}
diff --git a/packages/dubp_rs/lib/dubp.dart b/packages/dubp_rs/lib/dubp.dart
index 9856183a3691823485452f953eeccfa8cd0748ef..e2f1d2e3050edca2220e2621c3768f3e110fbbd9 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
@@ -63,21 +60,23 @@ class DubpRust {
     return completer.future;
   }
 
-  /// Change the pin code that encrypts the `dewif` keypair.
-  static Future<NewWallet> changeDewifPin(
-      {String currency = "g1",
-      String dewif,
-      String oldPin,
-      PinLength newPinLength = PinLength.six}) async {
+  /// Change the secret code that encrypts the `dewif` keypair.
+  static Future<NewWallet> changeDewifPin({
+    String currency = "g1",
+    String dewif,
+    String oldPin,
+    SecretCodeType secretCodeType = SecretCodeType.letters,
+  }) async {
     final completer = Completer<List<String>>();
     final sendPort = singleCompletePort<List<String>, List>(completer,
         callback: _handleErrList);
-    native.change_dewif_pin(
+    native.change_dewif_secret_code(
       sendPort.nativePort,
       Utf8.toUtf8(currency),
       Utf8.toUtf8(dewif),
       Utf8.toUtf8(oldPin),
       0,
+      secretCodeType.index,
     );
     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
   /// must indicate the currency for which this wallet will be used.
-  static Future<NewWallet> genWalletFromMnemonic(
-      {String currency = "g1",
-      Language language = Language.english,
-      String mnemonic,
-      PinLength pinLength = PinLength.six}) async {
+  static Future<NewWallet> genWalletFromMnemonic({
+    String currency = "g1",
+    Language language = Language.english,
+    String mnemonic,
+    SecretCodeType secretCodeType = SecretCodeType.letters,
+  }) async {
     final completer = Completer<List<String>>();
     final sendPort = singleCompletePort<List<String>, List>(completer,
         callback: _handleErrList);
@@ -105,6 +105,7 @@ class DubpRust {
       language.index,
       Utf8.toUtf8(mnemonic),
       0,
+      secretCodeType.index,
     );
     List<String> newWallet = await completer.future;