From 41281ed1b7e056dc5453e601b97c2fefc61f0cc1 Mon Sep 17 00:00:00 2001
From: dvermd <888-dvermd@users.noreply.git.duniter.org>
Date: Sun, 15 Mar 2020 07:36:14 +0100
Subject: [PATCH] [feat] whole: migrate dup-crypto to v0.15.0 and use DEWIF
 format

---
 Cargo.lock                                    |  69 ++++++-
 lib/core/conf/Cargo.toml                      |   2 +-
 lib/core/conf/src/errors.rs                   |  21 +++
 lib/core/conf/src/keypairs.rs                 | 172 ++++++++++--------
 lib/core/conf/src/keypairs/cli.rs             |  74 ++++++--
 lib/core/conf/src/ui/mod.rs                   |   5 +-
 lib/core/conf/src/ui/ui_trait.rs              |   2 +-
 lib/core/core/Cargo.toml                      |   2 +-
 lib/core/core/src/commands/keys.rs            | 127 ++++++++++---
 lib/core/core/src/commands/mod.rs             |  40 +++-
 lib/core/core/src/errors.rs                   |   4 +-
 lib/core/core/src/lib.rs                      |   3 +
 lib/core/message/Cargo.toml                   |   2 +-
 lib/core/module/Cargo.toml                    |   2 +-
 lib/core/network/Cargo.toml                   |   2 +-
 lib/dubp/block-doc/Cargo.toml                 |   2 +-
 lib/dubp/common-doc/Cargo.toml                |   2 +-
 lib/dubp/indexes/Cargo.toml                   |   2 +-
 lib/dubp/user-docs/Cargo.toml                 |   2 +-
 .../src/documents/certification/v10.rs        |   5 +-
 .../user-docs/src/documents/identity/v10.rs   |   3 +-
 .../user-docs/src/documents/membership/v10.rs |   5 +-
 .../user-docs/src/documents/revocation/v10.rs |   7 +-
 .../user-docs/src/documents/transaction.rs    |   3 +-
 .../src/documents/transaction/v10.rs          |   3 +-
 lib/dubp/wot/Cargo.toml                       |   2 +-
 lib/dunp/network-documents/Cargo.toml         |   2 +-
 .../network-documents/src/network_head_v3.rs  |   3 +-
 .../network-documents/src/network_peer.rs     |   5 +-
 lib/modules-lib/bc-db-reader/Cargo.toml       |   2 +-
 .../blockchain/bc-db-writer/Cargo.toml        |   2 +-
 lib/modules/blockchain/blockchain/Cargo.toml  |   2 +-
 .../blockchain/tests/revert_blocks.rs         |   6 +-
 lib/modules/gva/Cargo.toml                    |   2 +-
 lib/modules/skeleton/Cargo.toml               |   2 +-
 lib/modules/tui/Cargo.toml                    |   2 +-
 lib/modules/ws2p-v1-legacy/Cargo.toml         |   2 +-
 lib/modules/ws2p-v1-legacy/src/lib.rs         |   6 +-
 .../src/ws_connections/handler.rs             |   7 +-
 lib/modules/ws2p/ws2p-messages/Cargo.toml     |   2 +-
 lib/modules/ws2p/ws2p-messages/lib.rs         |   5 +-
 lib/modules/ws2p/ws2p-messages/v2/connect.rs  |   3 +-
 lib/modules/ws2p/ws2p-messages/v2/mod.rs      |   3 +-
 .../ws2p/ws2p-messages/v2/secret_flags.rs     |   3 +-
 lib/modules/ws2p/ws2p-protocol/Cargo.toml     |   2 +-
 .../src/controller/meta_datas.rs              |   7 +-
 lib/modules/ws2p/ws2p/Cargo.toml              |   2 +-
 lib/tests-tools/bc-db-tests-tools/Cargo.toml  |   2 +-
 lib/tests-tools/blocks-tests-tools/Cargo.toml |   2 +-
 lib/tests-tools/crypto-tests-tools/Cargo.toml |   2 +-
 .../user-docs-tests-tools/Cargo.toml          |   2 +-
 51 files changed, 432 insertions(+), 209 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7abe4899..f4a5e3fb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -275,6 +275,38 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
 
+[[package]]
+name = "aes"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9"
+dependencies = [
+ "aes-soft",
+ "aesni",
+ "block-cipher-trait",
+]
+
+[[package]]
+name = "aes-soft"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d"
+dependencies = [
+ "block-cipher-trait",
+ "byteorder",
+ "opaque-debug",
+]
+
+[[package]]
+name = "aesni"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f70a6b5f971e473091ab7cfb5ffac6cde81666c4556751d8d5620ead8abf100"
+dependencies = [
+ "block-cipher-trait",
+ "opaque-debug",
+]
+
 [[package]]
 name = "aho-corasick"
 version = "0.7.10"
@@ -472,6 +504,15 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "block-cipher-trait"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "block-padding"
 version = "0.1.5"
@@ -696,7 +737,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
 dependencies = [
  "generic-array",
- "subtle",
+ "subtle 1.0.0",
 ]
 
 [[package]]
@@ -709,6 +750,19 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "curve25519-dalek"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839"
+dependencies = [
+ "byteorder",
+ "digest",
+ "rand_core",
+ "subtle 2.2.2",
+ "zeroize",
+]
+
 [[package]]
 name = "derive_more"
 version = "0.99.3"
@@ -902,13 +956,16 @@ dependencies = [
 
 [[package]]
 name = "dup-crypto"
-version = "0.8.4"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f3dd6cfda1cf0b324169c142cc678a8fe5c3ce4fed3bac2958aab6faf745e25"
+checksum = "0d1f07e794fd7bbe2851c9c2538b470ab5f99ef46b470b1ec28a2dc565d52127"
 dependencies = [
+ "aes",
+ "arrayvec",
  "base64 0.11.0",
  "bs58",
  "byteorder",
+ "curve25519-dalek",
  "ring",
  "scrypt",
  "serde",
@@ -2847,6 +2904,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
 
+[[package]]
+name = "subtle"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941"
+
 [[package]]
 name = "syn"
 version = "1.0.17"
diff --git a/lib/core/conf/Cargo.toml b/lib/core/conf/Cargo.toml
index ca9de66e..cf42c529 100644
--- a/lib/core/conf/Cargo.toml
+++ b/lib/core/conf/Cargo.toml
@@ -11,7 +11,7 @@ path = "src/lib.rs"
 
 [dependencies]
 dirs = "2.0.2"
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
 durs-message =  { path = "../message" }
diff --git a/lib/core/conf/src/errors.rs b/lib/core/conf/src/errors.rs
index 18884dc0..16538705 100644
--- a/lib/core/conf/src/errors.rs
+++ b/lib/core/conf/src/errors.rs
@@ -15,6 +15,7 @@
 
 //! Dunitrust configuration errors
 
+use dup_crypto::dewif::DewifReadError;
 use failure::Fail;
 
 /// Error with configuration file
@@ -26,6 +27,9 @@ pub enum DursConfError {
     /// File error
     #[fail(display = "{}", _0)]
     FileErr(DursConfFileError),
+    /// Keypairs error
+    #[fail(display = "{}", _0)]
+    KeypairsError(DursKeypairsError),
 }
 
 /// Error with configuration file
@@ -63,3 +67,20 @@ pub enum DursConfFileError {
     #[fail(display = "fail to write configuration file: {}", _0)]
     WriteError(std::io::Error),
 }
+
+/// Error with keypairs file
+#[derive(Debug, Fail)]
+pub enum DursKeypairsError {
+    /// Currency error
+    #[fail(display = "unknown currency {}", _0)]
+    CurrencyError(String),
+    /// File error
+    #[fail(display = "fail to read keypairs file: {}", _0)]
+    FileError(String),
+    /// Read error
+    #[fail(display = "fail to read keypairs file: {}", _0)]
+    ReadError(DewifReadError),
+    /// Write error
+    #[fail(display = "fail to write keypairs file: {}", _0)]
+    WriteError(std::io::Error),
+}
diff --git a/lib/core/conf/src/keypairs.rs b/lib/core/conf/src/keypairs.rs
index 643a4be4..41af0f69 100644
--- a/lib/core/conf/src/keypairs.rs
+++ b/lib/core/conf/src/keypairs.rs
@@ -18,13 +18,20 @@
 pub mod cli;
 
 use crate::constants;
-use crate::errors::DursConfError;
+use crate::errors::DursKeypairsError;
+use crate::ui::ui_trait::UserInteractionTrait;
+use dubp_currency_params::CurrencyName;
+use dup_crypto::dewif::{
+    read_dewif_file_content, write_dewif_v1_content, write_dewif_v2_content, Currency,
+    ExpectedCurrency,
+};
 use dup_crypto::keys::*;
 use durs_module::{RequiredKeys, RequiredKeysContent};
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 use std::fs::File;
 use std::io::{Read, Write};
 use std::path::PathBuf;
+use std::str::FromStr;
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 /// Keypairs filled in by the user (via a file or by direct entry in the terminal).
@@ -106,24 +113,72 @@ fn generate_random_keypair(algo: KeysAlgo) -> KeyPairEnum {
 /// Save keypairs in profile folder
 // Warning: This function cannot use the macro fatal_error! because the logger is not yet initialized, so it must use panic !
 pub fn write_keypairs_file(
+    currency_name: &Option<CurrencyName>,
     file_path: &PathBuf,
     keypairs: &DuniterKeyPairs,
+    keypairs_passphrase: &String,
 ) -> Result<(), std::io::Error> {
+    let currency = if let Some(currency) = currency_name {
+        Currency::from_str(currency.to_string().as_str()).map_err(|_| {
+            std::io::Error::new(
+                std::io::ErrorKind::Other,
+                "Unkown currency for DEWIF format",
+            )
+        })?
+    } else {
+        Currency::none()
+    };
+    let network_keypair = if let KeyPairEnum::Ed25519(ref keypair) = keypairs.network_keypair {
+        Ok(keypair)
+    } else {
+        Err(std::io::Error::new(
+            std::io::ErrorKind::Other,
+            "Wrong network keypair format: only Ed25519 format it allowed",
+        ))
+    }?;
+    // Serialize keypair in DEWIF format
+    let dewif_content = if let Some(ref member_keypairs) = keypairs.member_keypair {
+        let member_keypair = if let KeyPairEnum::Ed25519(keypair) = member_keypairs {
+            Ok(keypair)
+        } else {
+            Err(std::io::Error::new(
+                std::io::ErrorKind::Other,
+                "Wrong member keypair format: only Ed25519 format it allowed",
+            ))
+        }?;
+        write_dewif_v2_content(
+            currency,
+            network_keypair,
+            member_keypair,
+            keypairs_passphrase,
+        )
+    } else {
+        write_dewif_v1_content(currency, network_keypair, keypairs_passphrase)
+    };
+
     let mut f = File::create(file_path.as_path())?;
-    f.write_all(
-        serde_json::to_string_pretty(keypairs)
-            .unwrap_or_else(|_| panic!(dbg!("Fatal error : fail to deserialize keypairs !")))
-            .as_bytes(),
-    )?;
+    f.write_all(dewif_content.as_bytes())?;
     f.sync_all()?;
     Ok(())
 }
 
+/// Create keypairs with random network keypair
+pub fn generate_random_keypairs() -> DuniterKeyPairs {
+    DuniterKeyPairs {
+        network_keypair: generate_random_keypair(KeysAlgo::Ed25519),
+        member_keypair: None,
+    }
+}
+
 /// Load keypairs from file
-pub fn load_keypairs_from_file(
+pub fn load_keypairs_from_file<UI: UserInteractionTrait>(
     profile_path: &PathBuf,
     keypairs_file_path: &Option<PathBuf>,
-) -> Result<DuniterKeyPairs, DursConfError> {
+    currency: &CurrencyName,
+    ui: &UI,
+) -> Result<(String, DuniterKeyPairs), DursKeypairsError> {
+    let dewif_currency = Currency::from_str(&*currency.0)
+        .map_err(|_| DursKeypairsError::CurrencyError(currency.0.clone()))?;
     // Get KeyPairs
     let keypairs_path = if let Some(ref keypairs_file_path) = keypairs_file_path {
         keypairs_file_path.clone()
@@ -136,80 +191,41 @@ pub fn load_keypairs_from_file(
         if let Ok(mut f) = File::open(keypairs_path.as_path()) {
             let mut contents = String::new();
             if f.read_to_string(&mut contents).is_ok() {
-                let json_conf: serde_json::Value =
-                    serde_json::from_str(&contents).expect("Conf: Fail to parse keypairs file !");
-
-                if let Some(network_seed) = json_conf.get("network_seed") {
-                    if let Some(network_pub) = json_conf.get("network_pub") {
-                        let network_seed = network_seed
-                            .as_str()
-                            .expect("Conf: Fail to parse keypairs file !");
-                        let network_pub = network_pub
-                            .as_str()
-                            .expect("Conf: Fail to parse keypairs file !");
-                        let network_keypair = KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
-                            seed: Seed32::from_base58(network_seed)
-                                .expect("conf : keypairs file : fail to parse network_seed !"),
-                            pubkey: ed25519::PublicKey::from_base58(network_pub)
-                                .expect("conf : keypairs file : fail to parse network_pub !"),
-                        });
-
-                        let member_keypair = if let Some(member_seed) = json_conf.get("member_seed")
-                        {
-                            if let Some(member_pub) = json_conf.get("member_pub") {
-                                let member_seed = member_seed
-                                    .as_str()
-                                    .expect("Conf: Fail to parse keypairs file !");
-                                let member_pub = member_pub
-                                    .as_str()
-                                    .expect("Conf: Fail to parse keypairs file !");
-                                if member_seed.is_empty() || member_pub.is_empty() {
-                                    None
-                                } else {
-                                    Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
-                                        seed: Seed32::from_base58(member_seed).expect(
-                                            "conf : keypairs file : fail to parse member_seed !",
-                                        ),
-                                        pubkey: ed25519::PublicKey::from_base58(member_pub).expect(
-                                            "conf : keypairs file : fail to parse member_pub !",
-                                        ),
-                                    }))
-                                }
-                            } else {
-                                panic!("Fatal error : keypairs file wrong format : no field member_pub !")
-                            }
-                        } else {
-                            panic!(
-                                "Fatal error : keypairs file wrong format : no field member_seed !"
-                            )
-                        };
-
-                        // Return keypairs
-                        Ok(DuniterKeyPairs {
-                            network_keypair,
-                            member_keypair,
-                        })
-                    } else {
-                        panic!("Fatal error : keypairs file wrong format : no field salt !")
-                    }
-                } else {
-                    panic!("Fatal error : keypairs file wrong format : no field password !")
-                }
+                let passphrase = ui
+                    .get_password("PassPhrase: ")
+                    .map_err(|_| DursKeypairsError::FileError("Bad Input for passphrase".into()))?;
+                let expected_currency = ExpectedCurrency::Specific(dewif_currency);
+                // Read DEWIF file content
+                // If the file content is correct, we get a key-pair iterator.
+                let mut key_pair_iter =
+                    read_dewif_file_content(expected_currency, &contents, &passphrase)
+                        .map_err(DursKeypairsError::ReadError)?;
+                // Return keypairs
+                Ok((
+                    passphrase,
+                    DuniterKeyPairs {
+                        network_keypair: key_pair_iter
+                            .next()
+                            .expect("There should always be at least a keypair in the file"),
+                        member_keypair: key_pair_iter.next(),
+                    },
+                ))
             } else {
-                panic!("Fail to read keypairs file !");
+                Err(DursKeypairsError::FileError(format!(
+                    "Fail to read content of keypairs file {}",
+                    profile_path.display()
+                )))
             }
         } else {
-            panic!("Fail to open keypairs file !");
+            Err(DursKeypairsError::FileError(format!(
+                "Fail to open keypairs file {}",
+                profile_path.display()
+            )))
         }
     } else {
-        // Create keypairs file with random keypair
-        let keypairs = DuniterKeyPairs {
-            network_keypair: generate_random_keypair(KeysAlgo::Ed25519),
-            member_keypair: None,
-        };
-        write_keypairs_file(&keypairs_path, &keypairs).unwrap_or_else(|_| {
-            panic!(dbg!("Fatal error : fail to write default keypairs file !"))
-        });
-        Ok(keypairs)
+        Err(DursKeypairsError::FileError(format!(
+            "No such keypairs file {}",
+            profile_path.display()
+        )))
     }
 }
diff --git a/lib/core/conf/src/keypairs/cli.rs b/lib/core/conf/src/keypairs/cli.rs
index e1524a0c..99fb6637 100644
--- a/lib/core/conf/src/keypairs/cli.rs
+++ b/lib/core/conf/src/keypairs/cli.rs
@@ -31,6 +31,48 @@ use crate::ui::ui_trait::*;
 use crate::ui::UiError;
 use crate::*;
 
+/// The wizard key function
+pub fn create_keys<UI: UserInteractionTrait>(
+    user_interaction: &UI,
+) -> Result<DuniterKeyPairs, UiError> {
+    let mut answer = user_interaction.question_prompt(
+        "Network keypair: Generate a random (r) or salted (s) keypair?",
+        &["r", "s"],
+    )?;
+
+    let network_keypair = if answer == 0 {
+        // Generate random keys
+        Ok(super::generate_random_keypair(KeysAlgo::Ed25519))
+    } else if answer == 1 {
+        // Get salt and password for keys
+        salt_password_prompt(user_interaction)
+    } else {
+        Err(UiError::BadInput)
+    }?;
+
+    answer = user_interaction.question_prompt(
+        "Member keypair: Generate a random (r), salted (s) or no (n) keypair?",
+        &["r", "s", "n"],
+    )?;
+    let member_keypair = if answer == 0 {
+        // Generate random keys
+        Ok(Some(super::generate_random_keypair(KeysAlgo::Ed25519)))
+    } else if answer == 1 {
+        // Get salt and password for keys
+        Ok(Some(salt_password_prompt(user_interaction)?))
+    } else if answer == 2 {
+        // Do not create a member key
+        Ok(None)
+    } else {
+        Err(UiError::BadInput)
+    }?;
+
+    Ok(DuniterKeyPairs {
+        network_keypair,
+        member_keypair,
+    })
+}
+
 #[inline]
 /// Modify network keys command
 pub fn modify_network_keys<UI: UserInteractionTrait>(
@@ -131,9 +173,11 @@ pub fn show_member_keys<UI: UserInteractionTrait>(
 
 /// Save keys after a command run
 pub fn save_keypairs(
+    currency_name: &Option<CurrencyName>,
     profile_path: PathBuf,
     keypairs_file_path: &Option<PathBuf>,
     key_pairs: &DuniterKeyPairs,
+    keypairs_passphrase: &String,
 ) -> Result<(), std::io::Error> {
     let conf_keys_path: PathBuf = if let Some(keypairs_file_path) = keypairs_file_path {
         keypairs_file_path.to_path_buf()
@@ -142,7 +186,12 @@ pub fn save_keypairs(
         conf_keys_path.push(crate::constants::KEYPAIRS_FILENAME);
         conf_keys_path
     };
-    super::write_keypairs_file(&conf_keys_path, &key_pairs)
+    super::write_keypairs_file(
+        currency_name,
+        &conf_keys_path,
+        &key_pairs,
+        keypairs_passphrase,
+    )
 }
 
 fn salt_password_prompt<UI: UserInteractionTrait>(
@@ -190,12 +239,13 @@ pub fn key_wizard<UI: UserInteractionTrait>(
 #[cfg(test)]
 mod tests {
     use super::*;
-    // use crate::ui::ui_trait::MockU;
 
+    // use crate::ui::ui_trait::MockU;
+    use dup_crypto::keys::ed25519::KeyPairFromSeed32Generator;
     use unwrap::unwrap;
 
     static BASE58_SEED_INIT: &str = "4iXXx5GgRkZ85BVPwn8vFXvztdXAAa5yB573ErcAnngA";
-    static BASE58_PUB_INIT: &str = "otDgSpKvKAPPmE1MUYxc3UQ3RtEnKYz4iGD3BmwKPzM";
+    static BASE58_PUB_INIT: &str = "J2rQNuhMGwXKDJ4v9WJDczMSH7oVE4yyg5hDcroFmwCi";
 
     static BASE58_SEED_TEST: &str = "ELjDWGPyCGMuhr7R7H2aip6UJA9qLRepmK77pcD41UqQ";
     static BASE58_PUB_TEST: &str = "6sewkaNWyEMqkEa2PVRWrDb3hxWtjPdUSB1zXVCqhdWV";
@@ -221,22 +271,18 @@ mod tests {
 
     fn setup_keys(both_keys: bool) -> DuniterKeyPairs {
         let member_keypair = if both_keys {
-            Some(KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
-                seed: Seed32::from_base58(BASE58_SEED_INIT)
-                    .expect("conf : keypairs file : fail to parse network_seed !"),
-                pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT)
-                    .expect("conf : keypairs file : fail to parse network_pub !"),
-            }))
+            Some(KeyPairEnum::Ed25519(KeyPairFromSeed32Generator::generate(
+                Seed32::from_base58(BASE58_SEED_INIT)
+                    .expect("conf : keypairs file : fail to parse member_seed !"),
+            )))
         } else {
             None
         };
         DuniterKeyPairs {
-            network_keypair: KeyPairEnum::Ed25519(ed25519::Ed25519KeyPair {
-                seed: Seed32::from_base58(BASE58_SEED_INIT)
+            network_keypair: KeyPairEnum::Ed25519(KeyPairFromSeed32Generator::generate(
+                Seed32::from_base58(BASE58_SEED_INIT)
                     .expect("conf : keypairs file : fail to parse network_seed !"),
-                pubkey: ed25519::PublicKey::from_base58(BASE58_PUB_INIT)
-                    .expect("conf : keypairs file : fail to parse network_pub !"),
-            }),
+            )),
             member_keypair,
         }
     }
diff --git a/lib/core/conf/src/ui/mod.rs b/lib/core/conf/src/ui/mod.rs
index adc7bdcf..d9796d6e 100644
--- a/lib/core/conf/src/ui/mod.rs
+++ b/lib/core/conf/src/ui/mod.rs
@@ -1,14 +1,17 @@
 //! Durs-core ui module.
 pub mod ui_cli;
 pub mod ui_trait;
+use failure::Fail;
 
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, Fail)]
 /// Errors encountered by the user interaction
 pub enum UiError {
     /// Canceled
+    #[fail(display = "input canceled")]
     Canceled,
 
     /// Bad input
+    #[fail(display = "wrong input")]
     BadInput,
 }
 
diff --git a/lib/core/conf/src/ui/ui_trait.rs b/lib/core/conf/src/ui/ui_trait.rs
index b0333439..5b7b42f9 100644
--- a/lib/core/conf/src/ui/ui_trait.rs
+++ b/lib/core/conf/src/ui/ui_trait.rs
@@ -10,7 +10,7 @@ pub trait UserInteractionTrait {
     /// Print a message to the user
     fn message(&self, message: &str);
 
-    /// Ask a question to the user
+    /// Ask a question to the user, return the index of the answer in `answers` or a `UiError`
     fn question_prompt<'a>(&self, question: &str, answers: &[&'a str]) -> Result<usize, UiError>;
 
     /// Get a password from the user
diff --git a/lib/core/core/Cargo.toml b/lib/core/core/Cargo.toml
index 2be3c3ce..9491e99e 100644
--- a/lib/core/core/Cargo.toml
+++ b/lib/core/core/Cargo.toml
@@ -17,7 +17,7 @@ durs-common-tools = { path = "../../tools/common-tools" }
 durs-bc-db-reader = { path = "../../modules-lib/bc-db-reader" }
 durs-conf = { path = "../conf" }
 durs-dbs-tools = { path = "../../tools/dbs-tools" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-currency-params = { path = "../../dubp/currency-params" }
 durs-message =  { path = "../message" }
 durs-module = { path = "../module" }
diff --git a/lib/core/core/src/commands/keys.rs b/lib/core/core/src/commands/keys.rs
index 0ad07dda..0a4efe1c 100644
--- a/lib/core/core/src/commands/keys.rs
+++ b/lib/core/core/src/commands/keys.rs
@@ -21,6 +21,7 @@ use crate::DursCore;
 use clap::arg_enum;
 use durs_conf::keypairs::cli::*;
 use durs_conf::ui::ui_cli::CLI;
+use durs_conf::ui::ui_trait::UserInteractionTrait;
 use durs_conf::{DuRsConf, DuniterKeyPairs};
 
 #[derive(StructOpt, Debug, Clone, Copy)]
@@ -38,13 +39,21 @@ pub struct KeysOpt {
 
 impl CommandNeedKeypairs for KeysOpt {
     fn needs_keypairs(&self) -> bool {
-        true
+        if let KeysSubCommand::Create(_) = self.subcommand {
+            false
+        } else {
+            true
+        }
     }
 }
 
 #[derive(StructOpt, Debug, Clone, Copy)]
 /// keys subcommands
 pub enum KeysSubCommand {
+    /// Create keys
+    #[structopt(name = "create", setting(structopt::clap::AppSettings::ColoredHelp))]
+    Create(CreateOpt),
+
     /// Modify keys
     #[structopt(
         name = "modify",
@@ -78,6 +87,10 @@ pub enum KeysSubCommand {
     Wizard(WizardOpt),
 }
 
+#[derive(StructOpt, Debug, Copy, Clone)]
+/// CreateOpt
+pub struct CreateOpt {}
+
 #[derive(StructOpt, Debug, Clone, Copy)]
 /// ModifyOpt
 pub struct ModifyOpt {
@@ -146,33 +159,90 @@ impl DursExecutableCoreCommand for KeysOpt {
         let keypairs_file = durs_core.options.keypairs_file;
 
         match self.subcommand {
+            KeysSubCommand::Create(_) => {
+                let new_keypairs = create_keys(&cli)?;
+                let passphrase =
+                    if let Some(keypairs_file_passphrase) = durs_core.keypairs_passphrase {
+                        keypairs_file_passphrase
+                    } else {
+                        cli.get_password("PassPhrase: ")?
+                    };
+                save_keypairs(
+                    &durs_core.currency_name,
+                    profile_path,
+                    &keypairs_file,
+                    &new_keypairs,
+                    &passphrase,
+                )
+                .map_err(DursCoreError::FailWriteKeypairsFile)
+                .and_then(|_| {
+                    show_keys(&cli, new_keypairs);
+                    Ok(())
+                })
+            }
             KeysSubCommand::Wizard(_) => {
                 let new_keypairs = key_wizard(&cli, keypairs)?;
-                save_keypairs(profile_path, &keypairs_file, &new_keypairs)
-                    .map_err(DursCoreError::FailWriteKeypairsFile)
-                    .and_then(|_| {
-                        show_keys(&cli, new_keypairs);
-                        Ok(())
-                    })
+                let passphrase =
+                    if let Some(keypairs_file_passphrase) = durs_core.keypairs_passphrase {
+                        keypairs_file_passphrase
+                    } else {
+                        cli.get_password("PassPhrase: ")?
+                    };
+                save_keypairs(
+                    &durs_core.currency_name,
+                    profile_path,
+                    &keypairs_file,
+                    &new_keypairs,
+                    &passphrase,
+                )
+                .map_err(DursCoreError::FailWriteKeypairsFile)
+                .and_then(|_| {
+                    show_keys(&cli, new_keypairs);
+                    Ok(())
+                })
             }
             KeysSubCommand::Modify(modify_opt) => match modify_opt.subcommand {
                 ModifySubCommand::NetworkSaltPassword => {
                     let new_keypairs = modify_network_keys(&cli, keypairs)?;
-                    save_keypairs(profile_path, &keypairs_file, &new_keypairs)
-                        .map_err(DursCoreError::FailWriteKeypairsFile)
-                        .and_then(|_| {
-                            show_network_keys(&cli, &new_keypairs);
-                            Ok(())
-                        })
+                    let passphrase =
+                        if let Some(keypairs_file_passphrase) = durs_core.keypairs_passphrase {
+                            keypairs_file_passphrase
+                        } else {
+                            cli.get_password("PassPhrase: ")?
+                        };
+                    save_keypairs(
+                        &durs_core.currency_name,
+                        profile_path,
+                        &keypairs_file,
+                        &new_keypairs,
+                        &passphrase,
+                    )
+                    .map_err(DursCoreError::FailWriteKeypairsFile)
+                    .and_then(|_| {
+                        show_network_keys(&cli, &new_keypairs);
+                        Ok(())
+                    })
                 }
                 ModifySubCommand::MemberSaltPassword => {
                     let new_keypairs = modify_member_keys(&cli, keypairs)?;
-                    save_keypairs(profile_path, &keypairs_file, &new_keypairs)
-                        .map_err(DursCoreError::FailWriteKeypairsFile)
-                        .and_then(|_| {
-                            show_member_keys(&cli, &new_keypairs);
-                            Ok(())
-                        })
+                    let passphrase =
+                        if let Some(keypairs_file_passphrase) = durs_core.keypairs_passphrase {
+                            keypairs_file_passphrase
+                        } else {
+                            cli.get_password("PassPhrase: ")?
+                        };
+                    save_keypairs(
+                        &durs_core.currency_name,
+                        profile_path,
+                        &keypairs_file,
+                        &new_keypairs,
+                        &passphrase,
+                    )
+                    .map_err(DursCoreError::FailWriteKeypairsFile)
+                    .and_then(|_| {
+                        show_member_keys(&cli, &new_keypairs);
+                        Ok(())
+                    })
                 }
             },
             KeysSubCommand::Clear(clear_opt) => {
@@ -182,12 +252,19 @@ impl DursExecutableCoreCommand for KeysOpt {
                     clear_opt.key.is_member(),
                     keypairs,
                 );
-                save_keypairs(profile_path, &keypairs_file, &new_keypairs)
-                    .map_err(DursCoreError::FailWriteKeypairsFile)
-                    .and_then(|_| {
-                        show_keys(&cli, new_keypairs);
-                        Ok(())
-                    })
+                let passphrase = durs_core.keypairs_passphrase.expect("Cannot clear a keypairs file without a passphrase to have it open in the first place");
+                save_keypairs(
+                    &durs_core.currency_name,
+                    profile_path,
+                    &keypairs_file,
+                    &new_keypairs,
+                    &passphrase,
+                )
+                .map_err(DursCoreError::FailWriteKeypairsFile)
+                .and_then(|_| {
+                    show_keys(&cli, new_keypairs);
+                    Ok(())
+                })
             }
             KeysSubCommand::Show(_) => {
                 show_keys(&cli, keypairs);
diff --git a/lib/core/core/src/commands/mod.rs b/lib/core/core/src/commands/mod.rs
index c2c0bcd8..c264b396 100644
--- a/lib/core/core/src/commands/mod.rs
+++ b/lib/core/core/src/commands/mod.rs
@@ -25,6 +25,8 @@ use crate::constants::DEFAULT_USER_PROFILE;
 use crate::errors::DursCoreError;
 use crate::DursCore;
 pub use dbex::*;
+use durs_conf::errors::*;
+use durs_conf::ui::ui_cli;
 use durs_conf::{DuRsConf, DuniterKeyPairs};
 use durs_dbs_tools::kv_db_old::KvFileDbHandler;
 pub use durs_network::cli::sync::SyncOpt;
@@ -107,6 +109,15 @@ pub enum DursCommandEnum<T: ExecutableModuleCommand> {
     Other(T),
 }
 
+impl<T: ExecutableModuleCommand> CommandNeedKeypairs for DursCommandEnum<T> {
+    fn needs_keypairs(&self) -> bool {
+        match self {
+            DursCommandEnum::Core(core_cmd) => core_cmd.needs_keypairs(),
+            DursCommandEnum::Other(cmd) => cmd.needs_keypairs(),
+        }
+    }
+}
+
 impl<T: ExecutableModuleCommand> DursCommand<T> {
     fn open_bc_db(&self, profile_path: &PathBuf) -> Result<KvFileDbHandler, DursCoreError> {
         let bc_db_path = durs_conf::get_blockchain_db_path(profile_path.clone());
@@ -129,13 +140,28 @@ impl<T: ExecutableModuleCommand> DursCommand<T> {
         let profile_path = self.options.define_profile_path();
         let bc_db = self.open_bc_db(&profile_path)?;
 
-        let durs_core = DursCore::<DuRsConf>::init(soft_name, soft_version, self.options, 0)?;
-
-        let keypairs = durs_conf::keypairs::load_keypairs_from_file(
-            &profile_path,
-            &durs_core.options.keypairs_file,
-        )
-        .map_err(DursCoreError::LoadConfError)?;
+        let mut durs_core = DursCore::<DuRsConf>::init(soft_name, soft_version, self.options, 0)?;
+        let currency = durs_core.currency_name.clone().ok_or_else(|| {
+            DursCoreError::LoadConfError(DursConfError::KeypairsError(
+                DursKeypairsError::CurrencyError("No Currency".to_string()),
+            ))
+        })?;
+
+        let keypairs;
+        if self.command.needs_keypairs() {
+            let cli = ui_cli::CLI {};
+            let (read_passphrase, read_keypairs) = durs_conf::keypairs::load_keypairs_from_file(
+                &profile_path,
+                &durs_core.options.keypairs_file,
+                &currency,
+                &cli,
+            )
+            .map_err(|e| DursCoreError::LoadConfError(DursConfError::KeypairsError(e)))?;
+            keypairs = read_keypairs;
+            durs_core.keypairs_passphrase = Some(read_passphrase);
+        } else {
+            keypairs = durs_conf::keypairs::generate_random_keypairs();
+        };
 
         match self.command {
             DursCommandEnum::Core(core_cmd) => DursCore::execute_core_command(
diff --git a/lib/core/core/src/errors.rs b/lib/core/core/src/errors.rs
index 97faf814..c523f35e 100644
--- a/lib/core/core/src/errors.rs
+++ b/lib/core/core/src/errors.rs
@@ -67,7 +67,7 @@ pub enum DursCoreError {
     SyncWithoutSource,
     /// Error on keys sub-command
     #[fail(display = "Error on keys sub-command")]
-    WizardKeysError(UiError),
+    WizardKeyError(UiError),
 }
 
 impl From<InitLoggerError> for DursCoreError {
@@ -78,6 +78,6 @@ impl From<InitLoggerError> for DursCoreError {
 
 impl From<UiError> for DursCoreError {
     fn from(e: UiError) -> Self {
-        DursCoreError::WizardKeysError(e)
+        DursCoreError::WizardKeyError(e)
     }
 }
diff --git a/lib/core/core/src/lib.rs b/lib/core/core/src/lib.rs
index 2ab78c33..44dc056a 100644
--- a/lib/core/core/src/lib.rs
+++ b/lib/core/core/src/lib.rs
@@ -92,6 +92,8 @@ pub struct DursCore<DC: DursConfTrait> {
     pub modules_names: Vec<ModuleStaticName>,
     /// Threads handlers that execute plugged modules
     pub threads: HashMap<ModuleStaticName, thread::JoinHandle<()>>,
+    /// Keypairs Passphrase
+    pub keypairs_passphrase: Option<String>,
 }
 
 #[derive(Debug, Clone)]
@@ -265,6 +267,7 @@ impl DursCore<DuRsConf> {
                 soft_version,
             },
             threads: HashMap::new(),
+            keypairs_passphrase: None,
         })
     }
     /// Start durs server
diff --git a/lib/core/message/Cargo.toml b/lib/core/message/Cargo.toml
index 34ad1979..51a1e26b 100644
--- a/lib/core/message/Cargo.toml
+++ b/lib/core/message/Cargo.toml
@@ -14,7 +14,7 @@ dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-module = { path = "../module" }
 durs-network = { path = "../network" }
 durs-network-documents = { path = "../../dunp/network-documents" }
diff --git a/lib/core/module/Cargo.toml b/lib/core/module/Cargo.toml
index 3fd1ea6c..61d6c57c 100644
--- a/lib/core/module/Cargo.toml
+++ b/lib/core/module/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2018"
 path = "src/lib.rs"
 
 [dependencies]
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs = { path = "../../dubp/user-docs" }
 durs-common-tools = { path = "../../tools/common-tools" }
diff --git a/lib/core/network/Cargo.toml b/lib/core/network/Cargo.toml
index bda1cfcd..58c75924 100644
--- a/lib/core/network/Cargo.toml
+++ b/lib/core/network/Cargo.toml
@@ -13,7 +13,7 @@ path = "lib.rs"
 dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tools = { path = "../../tools/common-tools" }
 durs-module = { path = "../module" }
 durs-network-documents = { path = "../../dunp/network-documents" }
diff --git a/lib/dubp/block-doc/Cargo.toml b/lib/dubp/block-doc/Cargo.toml
index d7754fc6..0ee6fa48 100644
--- a/lib/dubp/block-doc/Cargo.toml
+++ b/lib/dubp/block-doc/Cargo.toml
@@ -16,7 +16,7 @@ path = "src/lib.rs"
 dubp-common-doc = { path = "../common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../currency-params", version = "0.2.0" }
 dubp-user-docs = { path = "../user-docs", version = "0.14.0" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tools = { path = "../../tools/common-tools", version = "0.2.0" }
 failure = "0.1.5"
 json-pest-parser = { path = "../../tools/json-pest-parser", version = "0.2.0" }
diff --git a/lib/dubp/common-doc/Cargo.toml b/lib/dubp/common-doc/Cargo.toml
index 8a20f8fc..1108888c 100644
--- a/lib/dubp/common-doc/Cargo.toml
+++ b/lib/dubp/common-doc/Cargo.toml
@@ -13,7 +13,7 @@ edition = "2018"
 path = "src/lib.rs"
 
 [dependencies]
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tools = { path = "../../tools/common-tools", version = "0.2.0" }
 failure = "0.1.5"
 json-pest-parser = { path = "../../tools/json-pest-parser", version = "0.2.0" }
diff --git a/lib/dubp/indexes/Cargo.toml b/lib/dubp/indexes/Cargo.toml
index 16703d21..2355de81 100644
--- a/lib/dubp/indexes/Cargo.toml
+++ b/lib/dubp/indexes/Cargo.toml
@@ -16,7 +16,7 @@ path = "src/lib.rs"
 dubp-common-doc = { path = "../common-doc"} #, version = "0.1.0" }
 dubp-user-docs = { path = "../user-docs"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../currency-params", version = "0.2.0" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tools = { path = "../../tools/common-tools", version = "0.2.0" }
 failure = "0.1.5"
 log = "0.4.*"
diff --git a/lib/dubp/user-docs/Cargo.toml b/lib/dubp/user-docs/Cargo.toml
index d89db022..8d33fc1b 100644
--- a/lib/dubp/user-docs/Cargo.toml
+++ b/lib/dubp/user-docs/Cargo.toml
@@ -14,7 +14,7 @@ path = "src/lib.rs"
 
 [dependencies]
 dubp-common-doc = { path = "../common-doc"} #, version = "0.1.0" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tools = { path = "../../tools/common-tools", version = "0.2.0" }
 failure = "0.1.5"
 json-pest-parser = { path = "../../tools/json-pest-parser", version = "0.2.0" }
diff --git a/lib/dubp/user-docs/src/documents/certification/v10.rs b/lib/dubp/user-docs/src/documents/certification/v10.rs
index 35c964a8..1ca8c20d 100644
--- a/lib/dubp/user-docs/src/documents/certification/v10.rs
+++ b/lib/dubp/user-docs/src/documents/certification/v10.rs
@@ -345,8 +345,7 @@ mod tests {
         );
         let keypair = ed25519::KeyPairFromSeed32Generator::generate(seed);
         let pubkey = PubKey::Ed25519(keypair.public_key());
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
 
         let sig = Sig::Ed25519(unwrap!(ed25519::Signature::from_base64(
             "sYbaZp3pP9F/CveT1LPiJXECTBHlNurDXqmBo71N7JX/rvmHw6m/sid9bGdIa8cUq+vDD4DMB/F7r7As1p4rAg==",
@@ -389,7 +388,7 @@ mod tests {
             "Signatures = {:?}",
             builder
                 .build_and_sign(vec![SignatorEnum::Ed25519(
-                    keypair.generate_signator().expect("fail to gen signator")
+                    keypair.generate_signator()
                 )])
                 .signatures()
         );*/
diff --git a/lib/dubp/user-docs/src/documents/identity/v10.rs b/lib/dubp/user-docs/src/documents/identity/v10.rs
index 762ed89c..3bd20d5d 100644
--- a/lib/dubp/user-docs/src/documents/identity/v10.rs
+++ b/lib/dubp/user-docs/src/documents/identity/v10.rs
@@ -278,8 +278,7 @@ mod tests {
             "fail to build Seed32"
         ));
         let pubkey = PubKey::Ed25519(keypair.public_key());
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
 
         let sig = Sig::Ed25519(
             unwrap!(ed25519::Signature::from_base64(
diff --git a/lib/dubp/user-docs/src/documents/membership/v10.rs b/lib/dubp/user-docs/src/documents/membership/v10.rs
index 75356f46..eee47cb1 100644
--- a/lib/dubp/user-docs/src/documents/membership/v10.rs
+++ b/lib/dubp/user-docs/src/documents/membership/v10.rs
@@ -340,8 +340,7 @@ mod tests {
             "fail to build Seed32"
         ));
         let pubkey = PubKey::Ed25519(keypair.public_key());
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
 
         let sig = Sig::Ed25519(
             unwrap!(ed25519::Signature::from_base64(
@@ -370,7 +369,7 @@ mod tests {
             "Signatures = {:?}",
             builder
                 .build_and_sign(vec![SignatorEnum::Ed25519(
-                    keypair.generate_signator().expect("fail to gen signator")
+                    keypair.generate_signator()
                 )])
                 .signatures()
         );*/
diff --git a/lib/dubp/user-docs/src/documents/revocation/v10.rs b/lib/dubp/user-docs/src/documents/revocation/v10.rs
index 47ca62d9..665b9beb 100644
--- a/lib/dubp/user-docs/src/documents/revocation/v10.rs
+++ b/lib/dubp/user-docs/src/documents/revocation/v10.rs
@@ -309,8 +309,7 @@ mod tests {
             "fail to build Seed32"
         ));
         let pubkey = PubKey::Ed25519(keypair.public_key());
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
 
         let sig = Sig::Ed25519(unwrap!(ed25519::Signature::from_base64(
             "gBD2mCr7E/tW8u3wqVK7IWtQB6IKxddg13UMl9ypVsv/VhqhAFTBba9BwoK5t6H9eqF1d+4sCB3WY2eJ/yuUAg==",
@@ -338,9 +337,7 @@ mod tests {
         println!(
             "Signatures = {:?}",
             builder
-                .build_and_sign(vec![SignatorEnum::Ed25519(
-                    keypair.generate_signator().expect("fail to gen signator")
-                )])
+                .build_and_sign(vec![SignatorEnum::Ed25519(keypair.generate_signator())])
                 .signatures()
         );
 
diff --git a/lib/dubp/user-docs/src/documents/transaction.rs b/lib/dubp/user-docs/src/documents/transaction.rs
index 0606529c..b2f5837b 100644
--- a/lib/dubp/user-docs/src/documents/transaction.rs
+++ b/lib/dubp/user-docs/src/documents/transaction.rs
@@ -464,8 +464,7 @@ mod tests {
             "Fail to parse Seed32"
         ));
         let pubkey = PubKey::Ed25519(keypair.public_key());
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
 
         let sig = Sig::Ed25519(unwrap!(ed25519::Signature::from_base64(
             "cq86RugQlqAEyS8zFkB9o0PlWPSb+a6D/MEnLe8j+okyFYf/WzI6pFiBkQ9PSOVn5I0dwzVXg7Q4N1apMWeGAg==",
diff --git a/lib/dubp/user-docs/src/documents/transaction/v10.rs b/lib/dubp/user-docs/src/documents/transaction/v10.rs
index 5c9081a1..629f87dd 100644
--- a/lib/dubp/user-docs/src/documents/transaction/v10.rs
+++ b/lib/dubp/user-docs/src/documents/transaction/v10.rs
@@ -716,8 +716,7 @@ mod tests {
             "Fail to parse Seed32"
         ));
         let pubkey = PubKey::Ed25519(keypair.public_key());
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
 
         let sig = Sig::Ed25519(unwrap!(ed25519::Signature::from_base64(
             "cq86RugQlqAEyS8zFkB9o0PlWPSb+a6D/MEnLe8j+okyFYf/WzI6pFiBkQ9PSOVn5I0dwzVXg7Q4N1apMWeGAg==",
diff --git a/lib/dubp/wot/Cargo.toml b/lib/dubp/wot/Cargo.toml
index aa99c9b7..483a2fca 100644
--- a/lib/dubp/wot/Cargo.toml
+++ b/lib/dubp/wot/Cargo.toml
@@ -13,7 +13,7 @@ edition = "2018"
 path = "lib.rs"
 
 [dependencies]
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tools = { path = "../../tools/common-tools", version = "0.2.0" }
 log = "0.4.*"
 rayon = "1.3.0"
diff --git a/lib/dunp/network-documents/Cargo.toml b/lib/dunp/network-documents/Cargo.toml
index 0dbb4ce1..c40b14ca 100644
--- a/lib/dunp/network-documents/Cargo.toml
+++ b/lib/dunp/network-documents/Cargo.toml
@@ -15,7 +15,7 @@ path = "src/lib.rs"
 dubp-common-doc = { path = "../../dubp/common-doc" } #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-common-tests-tools = { path = "../../tests-tools/common-tests-tools" }
 durs-common-tools = { path = "../../tools/common-tools" }
 failure = "0.1.5"
diff --git a/lib/dunp/network-documents/src/network_head_v3.rs b/lib/dunp/network-documents/src/network_head_v3.rs
index 22e30574..2c1100de 100644
--- a/lib/dunp/network-documents/src/network_head_v3.rs
+++ b/lib/dunp/network-documents/src/network_head_v3.rs
@@ -275,8 +275,7 @@ mod tests {
     #[test]
     fn head_v3_sign_and_verify() {
         let keypair = keypair1();
-        let signator =
-            SignatorEnum::Ed25519(keypair.generate_signator().expect("Fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair.generate_signator());
         let mut head_v3 = NetworkHeadV3 {
             currency_name: CurrencyName("g1".to_owned()),
             api_outgoing_conf: 0u8,
diff --git a/lib/dunp/network-documents/src/network_peer.rs b/lib/dunp/network-documents/src/network_peer.rs
index 815341e7..101cf3a0 100644
--- a/lib/dunp/network-documents/src/network_peer.rs
+++ b/lib/dunp/network-documents/src/network_peer.rs
@@ -332,10 +332,7 @@ mod tests {
     #[test]
     fn peer_card_v11_sign_and_verify() {
         let keypair1 = keypair1();
-        let signator = SignatorEnum::Ed25519(unwrap!(
-            keypair1.generate_signator(),
-            "Fail to gen signator"
-        ));
+        let signator = SignatorEnum::Ed25519(keypair1.generate_signator());
         let mut peer_card_v11 = PeerCardV11 {
             currency_name: CurrencyName(String::from("g1")),
             issuer: PubKey::Ed25519(keypair1.public_key()),
diff --git a/lib/modules-lib/bc-db-reader/Cargo.toml b/lib/modules-lib/bc-db-reader/Cargo.toml
index 69ba1889..1e4f111f 100644
--- a/lib/modules-lib/bc-db-reader/Cargo.toml
+++ b/lib/modules-lib/bc-db-reader/Cargo.toml
@@ -13,7 +13,7 @@ path = "src/lib.rs"
 dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-indexes = { path = "../../dubp/indexes"} #, version = "0.1.0" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
 durs-conf = { path = "../../core/conf" }
diff --git a/lib/modules/blockchain/bc-db-writer/Cargo.toml b/lib/modules/blockchain/bc-db-writer/Cargo.toml
index 038fd31e..18214927 100644
--- a/lib/modules/blockchain/bc-db-writer/Cargo.toml
+++ b/lib/modules/blockchain/bc-db-writer/Cargo.toml
@@ -15,7 +15,7 @@ dubp-common-doc = { path = "../../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../../dubp/currency-params" }
 dubp-indexes = { path = "../../../dubp/indexes"} #, version = "0.1.0" }
 dubp-user-docs= { path = "../../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-bc-db-reader = { path = "../../../modules-lib/bc-db-reader" }
 durs-common-tools = { path = "../../../tools/common-tools" }
 durs-conf = { path = "../../../core/conf" }
diff --git a/lib/modules/blockchain/blockchain/Cargo.toml b/lib/modules/blockchain/blockchain/Cargo.toml
index 53407dd0..f5508f60 100644
--- a/lib/modules/blockchain/blockchain/Cargo.toml
+++ b/lib/modules/blockchain/blockchain/Cargo.toml
@@ -16,7 +16,7 @@ dubp-common-doc = { path = "../../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../../dubp/currency-params" }
 durs-bc-db-reader = { path = "../../../modules-lib/bc-db-reader" }
 durs-bc-db-writer = { path = "../bc-db-writer" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-user-docs= { path = "../../../dubp/user-docs" }
 durs-common-tools = { path = "../../../tools/common-tools" }
 durs-network-documents = { path = "../../../dunp/network-documents" }
diff --git a/lib/modules/blockchain/blockchain/tests/revert_blocks.rs b/lib/modules/blockchain/blockchain/tests/revert_blocks.rs
index 0ff7f983..c50ea8e6 100644
--- a/lib/modules/blockchain/blockchain/tests/revert_blocks.rs
+++ b/lib/modules/blockchain/blockchain/tests/revert_blocks.rs
@@ -67,8 +67,7 @@ fn test_revert_blocks_g1() {
     let signator = SignatorEnum::Ed25519(
         dup_crypto::keys::ed25519::Ed25519KeyPair::generate_random()
             .expect("unspecified rand error")
-            .generate_signator()
-            .expect("fail to generatye signator"),
+            .generate_signator(),
     );
     let mut fork_blocks = Vec::new();
     let mut previous_hash = block_61.hash().expect("block_61 have None hash").0;
@@ -141,8 +140,7 @@ fn test_revert_blocks_gt() {
     let signator = SignatorEnum::Ed25519(
         dup_crypto::keys::ed25519::Ed25519KeyPair::generate_random()
             .expect("unspecified rand error")
-            .generate_signator()
-            .expect("fail to generatye signator"),
+            .generate_signator(),
     );
     let mut fork_blocks = Vec::new();
     let mut previous_hash = block_546.hash().expect("block_546 have None hash").0;
diff --git a/lib/modules/gva/Cargo.toml b/lib/modules/gva/Cargo.toml
index 79501caa..4fb4b519 100644
--- a/lib/modules/gva/Cargo.toml
+++ b/lib/modules/gva/Cargo.toml
@@ -14,7 +14,7 @@ actix-cors = "0.2.0"
 actix-rt = "1.0.0"
 actix-web = "2.0.0"
 dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-bc-db-reader = { path = "../../modules-lib/bc-db-reader", features = ["client-indexer"] }
 durs-conf = { path = "../../core/conf" }
 durs-message =  { path = "../../core/message" }
diff --git a/lib/modules/skeleton/Cargo.toml b/lib/modules/skeleton/Cargo.toml
index dadf5c5d..77a934b5 100644
--- a/lib/modules/skeleton/Cargo.toml
+++ b/lib/modules/skeleton/Cargo.toml
@@ -15,7 +15,7 @@ durs-conf = { path = "../../core/conf" }
 durs-message =  { path = "../../core/message" }
 durs-module = { path = "../../core/module" }
 durs-network = { path = "../../core/network" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-currency-params = { path = "../../dubp/currency-params" }
 durs-common-tools = { path = "../../tools/common-tools" }
 failure = "0.1.5"
diff --git a/lib/modules/tui/Cargo.toml b/lib/modules/tui/Cargo.toml
index 940bccad..f28d30fe 100644
--- a/lib/modules/tui/Cargo.toml
+++ b/lib/modules/tui/Cargo.toml
@@ -11,7 +11,7 @@ path = "lib.rs"
 
 [dependencies]
 durs-conf = { path = "../../core/conf" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
 durs-common-tools = { path = "../../tools/common-tools" }
diff --git a/lib/modules/ws2p-v1-legacy/Cargo.toml b/lib/modules/ws2p-v1-legacy/Cargo.toml
index 1cae331d..71a390b9 100644
--- a/lib/modules/ws2p-v1-legacy/Cargo.toml
+++ b/lib/modules/ws2p-v1-legacy/Cargo.toml
@@ -15,7 +15,7 @@ dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs= { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-conf = { path = "../../core/conf" }
 durs-module = { path = "../../core/module" }
 durs-network = { path = "../../core/network" }
diff --git a/lib/modules/ws2p-v1-legacy/src/lib.rs b/lib/modules/ws2p-v1-legacy/src/lib.rs
index 4a2d6b41..43bdb6dc 100644
--- a/lib/modules/ws2p-v1-legacy/src/lib.rs
+++ b/lib/modules/ws2p-v1-legacy/src/lib.rs
@@ -290,11 +290,7 @@ impl WS2Pv1Module {
         key_pair: KeyPairEnum,
         router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>,
     ) -> WS2Pv1Module {
-        let my_signator = if let Ok(signator) = key_pair.generate_signator() {
-            signator
-        } else {
-            fatal_error!("Your key pair is corrupted, please recreate it !");
-        };
+        let my_signator = key_pair.generate_signator();
 
         WS2Pv1Module {
             router_sender,
diff --git a/lib/modules/ws2p-v1-legacy/src/ws_connections/handler.rs b/lib/modules/ws2p-v1-legacy/src/ws_connections/handler.rs
index 698fce42..3627c496 100644
--- a/lib/modules/ws2p-v1-legacy/src/ws_connections/handler.rs
+++ b/lib/modules/ws2p-v1-legacy/src/ws_connections/handler.rs
@@ -21,7 +21,6 @@ use super::states::WS2PConnectionState;
 use crate::constants::*;
 use crate::*;
 use dup_crypto::keys::*;
-use durs_common_tools::fatal_error;
 use std::sync::mpsc;
 #[allow(deprecated)]
 use ws::util::{Timeout, Token};
@@ -74,11 +73,7 @@ pub fn connect_to_ws2p_endpoint(
     // Connect to websocket
     ws::connect(ws_url, |ws| {
         // Generate signator
-        let signator = if let Ok(signator) = keypair.generate_signator() {
-            signator
-        } else {
-            fatal_error!("Your key pair is corrupted, please recreate it !");
-        };
+        let signator = keypair.generate_signator();
 
         // Generate connect message
         let connect_message =
diff --git a/lib/modules/ws2p/ws2p-messages/Cargo.toml b/lib/modules/ws2p/ws2p-messages/Cargo.toml
index 1df0e0d6..887b11f8 100644
--- a/lib/modules/ws2p/ws2p-messages/Cargo.toml
+++ b/lib/modules/ws2p/ws2p-messages/Cargo.toml
@@ -18,7 +18,7 @@ dubp-currency-params = { path = "../../../dubp/currency-params" }
 dubp-user-docs= { path = "../../../dubp/user-docs" }
 durs-network-documents = { path = "../../../dunp/network-documents" }
 durs-common-tools = { path = "../../../tools/common-tools" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 failure = "0.1.5"
 log = "0.4.*"
 serde = "1.0.*"
diff --git a/lib/modules/ws2p/ws2p-messages/lib.rs b/lib/modules/ws2p/ws2p-messages/lib.rs
index 661bdbbc..35e0123f 100644
--- a/lib/modules/ws2p/ws2p-messages/lib.rs
+++ b/lib/modules/ws2p/ws2p-messages/lib.rs
@@ -215,7 +215,7 @@ mod tests {
     pub fn create_peer_card_v11() -> PeerCardV11 {
         PeerCardV11 {
             currency_name: CurrencyName(String::from("g1")),
-            issuer: PubKey::Ed25519(keypair1().pubkey),
+            issuer: PubKey::Ed25519(keypair1().public_key()),
             node_id: NodeId(0),
             created_on: BlockNumber(50),
             endpoints: vec![create_endpoint_v11(), create_second_endpoint_v11()],
@@ -226,8 +226,7 @@ mod tests {
 
     pub fn test_ws2p_message(payload: WS2Pv2MessagePayload) {
         let keypair1 = keypair1();
-        let signator =
-            SignatorEnum::Ed25519(keypair1.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair1.generate_signator());
         let mut ws2p_message = WS2PMessage::V2(WS2Pv2Message {
             currency_name: CurrencyName(String::from("g1")),
             issuer_node_id: NodeId(0),
diff --git a/lib/modules/ws2p/ws2p-messages/v2/connect.rs b/lib/modules/ws2p/ws2p-messages/v2/connect.rs
index 04e05001..8286ea6e 100644
--- a/lib/modules/ws2p/ws2p-messages/v2/connect.rs
+++ b/lib/modules/ws2p/ws2p-messages/v2/connect.rs
@@ -188,8 +188,7 @@ mod tests {
     #[test]
     fn test_ws2p_message_connect() {
         let keypair1 = keypair1();
-        let signator =
-            SignatorEnum::Ed25519(keypair1.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair1.generate_signator());
         let mut peer = create_peer_card_v11();
         peer.sign(&signator).expect("Fail to sign peer card !");
         let connect_msg = WS2Pv2ConnectMsg {
diff --git a/lib/modules/ws2p/ws2p-messages/v2/mod.rs b/lib/modules/ws2p/ws2p-messages/v2/mod.rs
index 427a97bf..686582cf 100644
--- a/lib/modules/ws2p/ws2p-messages/v2/mod.rs
+++ b/lib/modules/ws2p/ws2p-messages/v2/mod.rs
@@ -98,8 +98,7 @@ mod tests {
     #[test]
     fn test_ws2p_message_peers() {
         let keypair1 = keypair1();
-        let signator =
-            SignatorEnum::Ed25519(keypair1.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair1.generate_signator());
         let mut peer = create_peer_card_v11();
         peer.sign(&signator).expect("Fail to sign peer card !");
         test_ws2p_message(WS2Pv2MessagePayload::Peers(vec![peer]));
diff --git a/lib/modules/ws2p/ws2p-messages/v2/secret_flags.rs b/lib/modules/ws2p/ws2p-messages/v2/secret_flags.rs
index 0e4a0c0b..56bffd38 100644
--- a/lib/modules/ws2p/ws2p-messages/v2/secret_flags.rs
+++ b/lib/modules/ws2p/ws2p-messages/v2/secret_flags.rs
@@ -71,8 +71,7 @@ mod tests {
     #[test]
     fn test_ws2p_message_secret_flags() {
         let keypair1 = keypair1();
-        let signator =
-            SignatorEnum::Ed25519(keypair1.generate_signator().expect("fail to gen signator"));
+        let signator = SignatorEnum::Ed25519(keypair1.generate_signator());
         let challenge = Hash::random().expect("unspecified rand error");
         let msg = WS2Pv2SecretFlagsMsg {
             secret_flags: WS2Pv2SecretFlags(vec![]),
diff --git a/lib/modules/ws2p/ws2p-protocol/Cargo.toml b/lib/modules/ws2p/ws2p-protocol/Cargo.toml
index 2317b01b..7b354846 100644
--- a/lib/modules/ws2p/ws2p-protocol/Cargo.toml
+++ b/lib/modules/ws2p/ws2p-protocol/Cargo.toml
@@ -14,7 +14,7 @@ dubp-common-doc = { path = "../../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../../dubp/currency-params" }
 dubp-user-docs= { path = "../../../dubp/user-docs" }
 durs-common-tools = { path = "../../../tools/common-tools" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-module = { path = "../../../core/module" }
 durs-network-documents = { path = "../../../dunp/network-documents" }
 durs-ws2p-messages = { path = "../ws2p-messages" }
diff --git a/lib/modules/ws2p/ws2p-protocol/src/controller/meta_datas.rs b/lib/modules/ws2p/ws2p-protocol/src/controller/meta_datas.rs
index bee84727..9797a68a 100644
--- a/lib/modules/ws2p/ws2p-protocol/src/controller/meta_datas.rs
+++ b/lib/modules/ws2p/ws2p-protocol/src/controller/meta_datas.rs
@@ -21,7 +21,6 @@ use dubp_common_doc::Blockstamp;
 use dubp_currency_params::CurrencyName;
 use dup_crypto::hashs::Hash;
 use dup_crypto::keys::{KeyPair, SignatorEnum};
-use durs_common_tools::fatal_error;
 use durs_network_documents::network_peer::PeerCardV11;
 use durs_network_documents::NodeFullId;
 use durs_ws2p_messages::v2::api_features::WS2PFeatures;
@@ -69,11 +68,7 @@ impl WS2PControllerMetaDatas {
         currency: CurrencyName,
         local_node: MySelfWs2pNode,
     ) -> Self {
-        let signator = if let Ok(signator) = local_node.my_key_pair.generate_signator() {
-            signator
-        } else {
-            fatal_error!("Your keypair is corrupted, please recreate it !");
-        };
+        let signator = local_node.my_key_pair.generate_signator();
 
         WS2PControllerMetaDatas {
             challenge,
diff --git a/lib/modules/ws2p/ws2p/Cargo.toml b/lib/modules/ws2p/ws2p/Cargo.toml
index 80a9a91f..323b1ce1 100644
--- a/lib/modules/ws2p/ws2p/Cargo.toml
+++ b/lib/modules/ws2p/ws2p/Cargo.toml
@@ -16,7 +16,7 @@ dubp-currency-params = { path = "../../../dubp/currency-params" }
 dubp-user-docs= { path = "../../../dubp/user-docs" }
 durs-network-documents = { path = "../../../dunp/network-documents" }
 durs-common-tools = { path = "../../../tools/common-tools" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-conf= { path = "../../../core/conf" }
 durs-ws2p-messages = { path = "../ws2p-messages" }
 durs-ws2p-protocol = { path = "../ws2p-protocol" }
diff --git a/lib/tests-tools/bc-db-tests-tools/Cargo.toml b/lib/tests-tools/bc-db-tests-tools/Cargo.toml
index 0f5bee85..39f24ac6 100644
--- a/lib/tests-tools/bc-db-tests-tools/Cargo.toml
+++ b/lib/tests-tools/bc-db-tests-tools/Cargo.toml
@@ -17,7 +17,7 @@ dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs = { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 durs-bc-db-reader = { path = "../../modules-lib/bc-db-reader" }
 durs-bc-db-writer = { path = "../../modules/blockchain/bc-db-writer" }
 dup-crypto-tests-tools = { path = "../crypto-tests-tools" }
diff --git a/lib/tests-tools/blocks-tests-tools/Cargo.toml b/lib/tests-tools/blocks-tests-tools/Cargo.toml
index 9ff64e0c..5079f950 100644
--- a/lib/tests-tools/blocks-tests-tools/Cargo.toml
+++ b/lib/tests-tools/blocks-tests-tools/Cargo.toml
@@ -17,7 +17,7 @@ dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs = { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dup-crypto-tests-tools = { path = "../crypto-tests-tools" }
 dubp-user-docs-tests-tools = { path = "../user-docs-tests-tools" }
 durs-common-tools = { path = "../../tools/common-tools" }
diff --git a/lib/tests-tools/crypto-tests-tools/Cargo.toml b/lib/tests-tools/crypto-tests-tools/Cargo.toml
index 4d8af56d..2f2f5d2d 100644
--- a/lib/tests-tools/crypto-tests-tools/Cargo.toml
+++ b/lib/tests-tools/crypto-tests-tools/Cargo.toml
@@ -13,6 +13,6 @@ edition = "2018"
 path = "src/lib.rs"
 
 [dependencies]
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 
 [dev-dependencies]
diff --git a/lib/tests-tools/user-docs-tests-tools/Cargo.toml b/lib/tests-tools/user-docs-tests-tools/Cargo.toml
index 02731d11..d9135878 100644
--- a/lib/tests-tools/user-docs-tests-tools/Cargo.toml
+++ b/lib/tests-tools/user-docs-tests-tools/Cargo.toml
@@ -17,7 +17,7 @@ dubp-block-doc = { path = "../../dubp/block-doc"} #, version = "0.1.0" }
 dubp-common-doc = { path = "../../dubp/common-doc"} #, version = "0.1.0" }
 dubp-currency-params = { path = "../../dubp/currency-params" }
 dubp-user-docs = { path = "../../dubp/user-docs" }
-dup-crypto = "0.8.4"
+dup-crypto = "0.15.0"
 dup-crypto-tests-tools = { path = "../crypto-tests-tools" }
 
 [dev-dependencies]
-- 
GitLab