diff --git a/Cargo.lock b/Cargo.lock
index a5834ffc9984ee27ff69fcddc4201fa4a6f7d5e5..8e35fc861776771821ebacd5f337cf572e7f35e4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -586,6 +586,7 @@ dependencies = [
 name = "durs-core"
 version = "0.3.0-dev"
 dependencies = [
+ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "dubp-currency-params 0.2.0",
  "dup-crypto 0.7.0",
diff --git a/lib/core/conf/src/keys.rs b/lib/core/conf/src/keys.rs
index 6d58de07e01422e847d99712a2e0215198682b0c..8f12e74d354804ffab9ef461cc558372c750a90e 100644
--- a/lib/core/conf/src/keys.rs
+++ b/lib/core/conf/src/keys.rs
@@ -42,25 +42,25 @@ impl From<std::io::Error> for WizardError {
 
 /// Modify network keys command
 pub fn modify_network_keys(
-    salt: &str,
-    password: &str,
+    salt: String,
+    password: String,
     mut key_pairs: DuniterKeyPairs,
 ) -> DuniterKeyPairs {
     let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters();
     key_pairs.network_keypair =
-        KeyPairEnum::Ed25519(generator.generate(salt.as_bytes(), password.as_bytes()));
+        KeyPairEnum::Ed25519(generator.generate(ed25519::SaltedPassword::new(salt, password)));
     key_pairs
 }
 
 /// Modify member keys command
 pub fn modify_member_keys(
-    salt: &str,
-    password: &str,
+    salt: String,
+    password: String,
     mut key_pairs: DuniterKeyPairs,
 ) -> DuniterKeyPairs {
     let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters();
     key_pairs.member_keypair = Some(KeyPairEnum::Ed25519(
-        generator.generate(salt.as_bytes(), password.as_bytes()),
+        generator.generate(ed25519::SaltedPassword::new(salt, password)),
     ));
     key_pairs
 }
@@ -129,10 +129,9 @@ fn salt_password_prompt() -> Result<KeyPairEnum, WizardError> {
         let password = rpassword::prompt_password_stdout("Password: ")?;
         if !password.is_empty() {
             let generator = ed25519::KeyPairFromSaltedPasswordGenerator::with_default_parameters();
-            let key_pairs = KeyPairEnum::Ed25519(generator.generate(
-                salt.into_bytes().as_slice(),
-                password.into_bytes().as_slice(),
-            ));
+            let key_pairs = KeyPairEnum::Ed25519(
+                generator.generate(ed25519::SaltedPassword::new(salt, password)),
+            );
             Ok(key_pairs)
         } else {
             Err(WizardError::BadInput)
@@ -191,7 +190,8 @@ mod tests {
             }),
             member_keypair: None,
         };
-        let result_key_pairs = modify_member_keys(SALT_TEST, PASSWORD_TEST, key_pairs);
+        let result_key_pairs =
+            modify_member_keys(SALT_TEST.to_owned(), PASSWORD_TEST.to_owned(), key_pairs);
         // We expect network key not to change
         assert_eq!(
             result_key_pairs.network_keypair.public_key(),
@@ -239,7 +239,8 @@ mod tests {
             }),
             member_keypair: None,
         };
-        let result_key_pairs = modify_network_keys(SALT_TEST, PASSWORD_TEST, key_pairs);
+        let result_key_pairs =
+            modify_network_keys(SALT_TEST.to_owned(), PASSWORD_TEST.to_owned(), key_pairs);
         // We expect network key to update
         assert_eq!(
             result_key_pairs.network_keypair.public_key(),
diff --git a/lib/core/core/Cargo.toml b/lib/core/core/Cargo.toml
index 4f947dc4a0328b3dd3d377eaa8c44f54ca6a8c4c..86f6c5440444365360dc5eab1f16746cf6c25d84 100644
--- a/lib/core/core/Cargo.toml
+++ b/lib/core/core/Cargo.toml
@@ -10,6 +10,7 @@ edition = "2018"
 path = "src/lib.rs"
 
 [dependencies]
+clear_on_drop = "0.2.3"
 dirs = "1.0.2"
 durs-blockchain = { path = "../../modules/blockchain/blockchain" }
 durs-common-tools = { path = "../../tools/common-tools" }
diff --git a/lib/core/core/src/commands/keys.rs b/lib/core/core/src/commands/keys.rs
index b950aeb60910c529124f191dcf9c6da96836ce7d..7190c1c9b422ccc920aba712adebfd2e602df348 100644
--- a/lib/core/core/src/commands/keys.rs
+++ b/lib/core/core/src/commands/keys.rs
@@ -18,6 +18,7 @@
 use crate::commands::DursExecutableCoreCommand;
 use crate::errors::DursCoreError;
 use crate::DursCore;
+use clear_on_drop::clear::Clear;
 use durs_conf::keys::*;
 use durs_conf::DuRsConf;
 
@@ -124,6 +125,14 @@ pub struct SaltPasswordOpt {
     pub password: String,
 }
 
+impl Drop for SaltPasswordOpt {
+    #[inline]
+    fn drop(&mut self) {
+        <String as Clear>::clear(&mut self.salt);
+        <String as Clear>::clear(&mut self.password);
+    }
+}
+
 #[derive(StructOpt, Debug, Copy, Clone)]
 /// WizardOpt
 pub struct WizardOpt {}
@@ -146,14 +155,20 @@ impl DursExecutableCoreCommand for KeysOpt {
             }
             KeysSubCommand::Modify(modify_opt) => match modify_opt.subcommand {
                 ModifySubCommand::NetworkSaltPassword(network_opt) => {
-                    let new_keypairs =
-                        modify_network_keys(&network_opt.salt, &network_opt.password, keypairs);
+                    let new_keypairs = modify_network_keys(
+                        network_opt.salt.clone(),
+                        network_opt.password.clone(),
+                        keypairs,
+                    );
                     save_keypairs(profile_path, &keypairs_file, new_keypairs)
                         .map_err(DursCoreError::FailWriteKeypairsFile)
                 }
                 ModifySubCommand::MemberSaltPassword(member_opt) => {
-                    let new_keypairs =
-                        modify_member_keys(&member_opt.salt, &member_opt.password, keypairs);
+                    let new_keypairs = modify_member_keys(
+                        member_opt.salt.clone(),
+                        member_opt.password.clone(),
+                        keypairs,
+                    );
                     save_keypairs(profile_path, &keypairs_file, new_keypairs)
                         .map_err(DursCoreError::FailWriteKeypairsFile)
                 }
diff --git a/lib/crypto/src/encryption.rs b/lib/crypto/src/encryption.rs
index 881d1e5842c8e717d468e74ed1b0092ec1cfb72b..33a0eb74fe4387a3f49146a8e271ab3f588d591a 100644
--- a/lib/crypto/src/encryption.rs
+++ b/lib/crypto/src/encryption.rs
@@ -17,11 +17,12 @@
 
 use crate::errors::CryptoError;
 use crate::seeds::Seed48;
+use clear_on_drop::clear::Clear;
 use std::io::Read;
 
 const CHACHA20_TAG_SIZE: usize = 16;
 
-#[derive(Clone, Copy, Default)]
+#[derive(Clone, Default)]
 /// Secret key used for encryption algo
 pub struct SecretKey {
     key: [u8; 32],
@@ -29,6 +30,15 @@ pub struct SecretKey {
     aad: [u8; 4],
 }
 
+impl Drop for SecretKey {
+    #[inline]
+    fn drop(&mut self) {
+        self.key.clear();
+        self.nonce.clear();
+        self.aad.clear();
+    }
+}
+
 impl SecretKey {
     /// Create new secret key
     pub fn new(seed: &Seed48) -> SecretKey {
diff --git a/lib/crypto/src/keys/ed25519.rs b/lib/crypto/src/keys/ed25519.rs
index ec63172a04b9e28939f29f8445e3c13f523021b3..c6bc8ef72d0695e1fa5a7587a4990bdcdae68484 100644
--- a/lib/crypto/src/keys/ed25519.rs
+++ b/lib/crypto/src/keys/ed25519.rs
@@ -221,13 +221,6 @@ pub struct Ed25519KeyPair {
     pub seed: Seed32,
 }
 
-impl Drop for Ed25519KeyPair {
-    #[inline]
-    fn drop(&mut self) {
-        self.seed.clear();
-    }
-}
-
 impl Display for Ed25519KeyPair {
     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
         write!(f, "({}, hidden)", self.pubkey.to_base58())
@@ -293,6 +286,27 @@ impl KeyPairFromSeed32Generator {
     }
 }
 
+/// Salted password
+pub struct SaltedPassword {
+    salt: String,
+    password: String,
+}
+
+impl SaltedPassword {
+    /// Create new salted password
+    pub fn new(salt: String, password: String) -> SaltedPassword {
+        SaltedPassword { salt, password }
+    }
+}
+
+impl Drop for SaltedPassword {
+    #[inline]
+    fn drop(&mut self) {
+        <String as Clear>::clear(&mut self.salt);
+        <String as Clear>::clear(&mut self.password);
+    }
+}
+
 /// Keypair generator with given parameters for `scrypt` keypair function.
 #[derive(Copy, Clone)]
 pub struct KeyPairFromSaltedPasswordGenerator {
@@ -329,7 +343,7 @@ impl KeyPairFromSaltedPasswordGenerator {
     pub fn generate_seed(&self, password: &[u8], salt: &[u8]) -> Seed32 {
         let mut seed = [0u8; 32];
 
-        scrypt::scrypt(salt, password, &self.scrypt_params, &mut seed)
+        scrypt::scrypt(password, salt, &self.scrypt_params, &mut seed)
             .expect("dev error: invalid seed len");
 
         Seed32::new(seed)
@@ -339,9 +353,12 @@ impl KeyPairFromSaltedPasswordGenerator {
     ///
     /// The [`PublicKey`](struct.PublicKey.html) will be able to verify messaged signed with
     /// the [`PrivateKey`](struct.PrivateKey.html).
-    pub fn generate(&self, password: &[u8], salt: &[u8]) -> Ed25519KeyPair {
+    pub fn generate(&self, salted_password: SaltedPassword) -> Ed25519KeyPair {
         // Generate seed from tuple (password + salt)
-        let seed = self.generate_seed(password, salt);
+        let seed = self.generate_seed(
+            salted_password.password.as_bytes(),
+            salted_password.salt.as_bytes(),
+        );
         // Generate keypair from seed
         KeyPairFromSeed32Generator::generate(seed)
     }
@@ -599,8 +616,10 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
     #[test]
     fn keypair_generate() {
         let key_pair1 = KeyPairFromSaltedPasswordGenerator::with_default_parameters().generate(
-            "JhxtHB7UcsDbA9wMSyMKXUzBZUQvqVyB32KwzS9SWoLkjrUhHV".as_bytes(),
-            "JhxtHB7UcsDbA9wMSyMKXUzBZUQvqVyB32KwzS9SWoLkjrUhHV_".as_bytes(),
+            SaltedPassword::new(
+                "JhxtHB7UcsDbA9wMSyMKXUzBZUQvqVyB32KwzS9SWoLkjrUhHV".to_owned(),
+                "JhxtHB7UcsDbA9wMSyMKXUzBZUQvqVyB32KwzS9SWoLkjrUhHV_".to_owned(),
+            ),
         );
 
         assert_eq!(
@@ -610,7 +629,7 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
 
         let key_pair2 = KeyPairFromSaltedPasswordGenerator::with_parameters(12u8, 16, 1)
             .expect("fail to create KeyPairFromSaltedPasswordGenerator: invalid scrypt params.")
-            .generate(b"toto", b"toto");
+            .generate(SaltedPassword::new("toto".to_owned(), "toto".to_owned()));
 
         // Test signature display and debug
         assert_eq!(
@@ -630,8 +649,9 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
 
     #[test]
     fn keypair_generate_sign_and_verify() {
-        let keypair = KeyPairFromSaltedPasswordGenerator::with_default_parameters()
-            .generate("password".as_bytes(), "salt".as_bytes());
+        let keypair = KeyPairFromSaltedPasswordGenerator::with_default_parameters().generate(
+            SaltedPassword::new("password".to_owned(), "salt".to_owned()),
+        );
 
         let message = "Version: 10
 Type: Identity
diff --git a/lib/crypto/src/keys/mod.rs b/lib/crypto/src/keys/mod.rs
index 05016379c7d2d245b99813d1ec68aac7ce745cef..34096c08ad3be06d9995edc648c10dee0b13dbcc 100644
--- a/lib/crypto/src/keys/mod.rs
+++ b/lib/crypto/src/keys/mod.rs
@@ -22,14 +22,14 @@
 //!
 //! ```
 //! use dup_crypto::keys::{KeyPair, PublicKey, Signator, Signature};
-//! use dup_crypto::keys::ed25519::KeyPairFromSaltedPasswordGenerator;
+//! use dup_crypto::keys::ed25519::{KeyPairFromSaltedPasswordGenerator, SaltedPassword};
 //!
 //! let generator = KeyPairFromSaltedPasswordGenerator::with_default_parameters();
 //!
-//! let keypair = generator.generate(
-//!     b"password",
-//!     b"salt"
-//! );
+//! let keypair = generator.generate(SaltedPassword::new(
+//!     "salt".to_owned(),
+//!     "password".to_owned(),
+//! ));
 //!
 //! let signator = keypair.generate_signator().expect("keypair corrupted");
 //!
diff --git a/lib/crypto/src/seeds.rs b/lib/crypto/src/seeds.rs
index 2d26bb200e99f1cb65e0c3b391db9c55d83bff79..0dcca5eeaebb95f513c821981317d1fcd61af849 100644
--- a/lib/crypto/src/seeds.rs
+++ b/lib/crypto/src/seeds.rs
@@ -17,24 +17,34 @@
 
 use crate::bases::*;
 use base58::ToBase58;
+use clear_on_drop::clear::Clear;
 use durs_common_tools::fatal_error;
 use log::error;
 use ring::rand;
 use std::fmt::{self, Debug, Display, Formatter};
 
 /// Store a 48 bytes seed used to generate keys.
-#[derive(Clone, Copy)]
-pub struct Seed48([u8; 48]);
+#[derive(Default)]
+pub struct Seed48(InnerSeed48);
+
+struct InnerSeed48([u8; 48]);
+
+impl Default for InnerSeed48 {
+    fn default() -> Self {
+        InnerSeed48([0u8; 48])
+    }
+}
 
 impl AsRef<[u8]> for Seed48 {
     fn as_ref(&self) -> &[u8] {
-        &self.0
+        &(self.0).0
     }
 }
 
-impl Default for Seed48 {
-    fn default() -> Self {
-        Seed48([0u8; 48])
+impl Drop for Seed48 {
+    #[inline]
+    fn drop(&mut self) {
+        <InnerSeed48 as Clear>::clear(&mut self.0);
     }
 }
 
@@ -42,7 +52,7 @@ impl Seed48 {
     #[inline]
     /// Create new seed
     pub fn new(seed_bytes: [u8; 48]) -> Seed48 {
-        Seed48(seed_bytes)
+        Seed48(InnerSeed48(seed_bytes))
     }
     #[inline]
     /// Generate random seed
@@ -56,7 +66,7 @@ impl Seed48 {
 }
 
 /// Store a 32 bytes seed used to generate keys.
-#[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq, Hash, Serialize)]
+#[derive(Clone, Default, Deserialize, PartialEq, Eq, Hash, Serialize)]
 pub struct Seed32([u8; 32]);
 
 impl AsRef<[u8]> for Seed32 {
@@ -71,16 +81,22 @@ impl ToBase58 for Seed32 {
     }
 }
 
+impl Debug for Seed32 {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
+        write!(f, "Seed32 {{ {} }}", self)
+    }
+}
+
 impl Display for Seed32 {
     fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
         write!(f, "{}", self.to_base58())
     }
 }
 
-impl Debug for Seed32 {
-    // Seed32 { DNann1L... }
-    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
-        write!(f, "Seed32 {{ {} }}", self)
+impl Drop for Seed32 {
+    #[inline]
+    fn drop(&mut self) {
+        <[u8; 32] as Clear>::clear(&mut self.0);
     }
 }