diff --git a/Cargo.lock b/Cargo.lock
index 3bdb2b4b74fa9161aaf6c5ee57f927d60a4f6fa1..34cd5f77fb4a932b5e279c4b79986544f307114b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -844,11 +844,10 @@ dependencies = [
  "bincode 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "unwrap 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2720,6 +2719,24 @@ dependencies = [
  "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "thiserror"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "thread_local"
 version = "0.3.6"
@@ -3344,6 +3361,8 @@ dependencies = [
 "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
 "checksum termion 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "818ef3700c2a7b447dca1a1dd28341fe635e6ee103c806c636bb9c929991b2cd"
 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+"checksum thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db"
+"checksum thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4"
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
 "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
diff --git a/lib/crypto/Cargo.toml b/lib/crypto/Cargo.toml
index 6b6d1212370c54d3936a90f54baa3dd51fa8a6b7..63fd11e8e7209a7edad8999e3ca54a9a59477f5a 100644
--- a/lib/crypto/Cargo.toml
+++ b/lib/crypto/Cargo.toml
@@ -16,11 +16,10 @@ path = "src/lib.rs"
 base64 = "0.11.0"
 bs58 = "0.3.0"
 byteorder = "1.3.2"
-failure = "0.1.5"
 ring = "0.16.9"
 scrypt = { version = "0.2", default-features = false }
-serde = "1.0.*"
-serde_derive = "1.0.*"
+serde = { version = "1.0.*", features = ["derive"] }
+thiserror = "1.0.11"
 unwrap = "1.2.1"
 zeroize = { version = "1.1.0", features = ["zeroize_derive"] }
 
diff --git a/lib/crypto/src/bases/mod.rs b/lib/crypto/src/bases/mod.rs
index 4bb0dc9f75b197aa65c1433a088387e7496c5988..961006443ab75d3e6fe3b6980f12ff4d2fa4070f 100644
--- a/lib/crypto/src/bases/mod.rs
+++ b/lib/crypto/src/bases/mod.rs
@@ -15,6 +15,8 @@
 
 //! Provide base convertion tools
 
+use thiserror::Error;
+
 /// Base16 conversion tools
 pub mod b16;
 
@@ -25,12 +27,9 @@ pub mod b58;
 pub mod b64;
 
 /// Errors enumeration for Base58/64 strings convertion.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Fail)]
+#[derive(Clone, Copy, Debug, Error, Eq, PartialEq)]
 pub enum BaseConvertionError {
-    #[fail(
-        display = "Data have invalid key length : expected {}, found {}.",
-        expected, found
-    )]
+    #[error("Data have invalid key length : expected {expected:?}, found {found:?}.")]
     /// Data have invalid length.
     InvalidLength {
         /// Expected length
@@ -38,7 +37,7 @@ pub enum BaseConvertionError {
         /// Actual length
         found: usize,
     },
-    #[fail(display = "Invalid character '{}' at offset {}.", character, offset)]
+    #[error("Invalid character '{character:?}' at offset {offset:?}.")]
     /// Base58/64 have an invalid character.
     InvalidCharacter {
         /// Character
@@ -46,10 +45,10 @@ pub enum BaseConvertionError {
         /// Offset (=position)
         offset: usize,
     },
-    #[fail(display = "Invalid base converter length.")]
+    #[error("Invalid base converter length.")]
     /// Base58/64 have invalid lendth
     InvalidBaseConverterLength,
-    #[fail(display = "Invalid last symbol '{}' at offset {}.", symbol, offset)]
+    #[error("Invalid last symbol '{symbol:?}' at offset {offset:?}.")]
     /// Base64 have invalid last symbol (symbol, offset)
     InvalidLastSymbol {
         /// Symbol
@@ -58,7 +57,7 @@ pub enum BaseConvertionError {
         offset: usize,
     },
     /// Unknown error
-    #[fail(display = "Unknown error.")]
+    #[error("Unknown error.")]
     UnknownError,
 }
 
diff --git a/lib/crypto/src/errors.rs b/lib/crypto/src/errors.rs
deleted file mode 100644
index c7cd399bb40a8cf28bbec3fb53ec38f0b71529e7..0000000000000000000000000000000000000000
--- a/lib/crypto/src/errors.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-//  Copyright (C) 2017-2019  The AXIOM TEAM Association.
-//
-// 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/>.
-
-//! Manage cryptographic errors.
-
-/// An error with absolutely no details.
-///
-/// *dup-crypto* uses this unit type as the error type in most of its results
-/// because (a) usually the specific reasons for a failure are obvious or are
-/// not useful to know, and/or (b) providing more details about a failure might
-/// provide a dangerous side channel, and/or (c) it greatly simplifies the
-/// error handling logic.
-///
-/// Experience with using and implementing other crypto libraries like has
-/// shown that sophisticated error reporting facilities often cause significant
-/// bugs themselves, both within the crypto library and within users of the
-/// crypto library. This approach attempts to minimize complexity in the hopes
-/// of avoiding such problems. In some cases, this approach may be too extreme,
-/// and it may be important for an operation to provide some details about the
-/// cause of a failure. Users of *dup-crypto* are encouraged to report such cases so
-/// that they can be addressed individually.
-pub type Unspecified = ring::error::Unspecified;
diff --git a/lib/crypto/src/hashs/mod.rs b/lib/crypto/src/hashs/mod.rs
index c12b43a03fed6d84b9a8cf26ef8fb69767bf9173..c844978abc9003eaa3c86eedb40932afb94c471d 100644
--- a/lib/crypto/src/hashs/mod.rs
+++ b/lib/crypto/src/hashs/mod.rs
@@ -16,7 +16,9 @@
 //! Provide wrappers for cryptographic hashs
 
 use crate::bases::*;
+use crate::rand::UnspecifiedRandError;
 use ring::{digest, rand};
+use serde::{Deserialize, Serialize};
 use std::fmt::{Debug, Display, Error, Formatter};
 
 /// A hash wrapper.
@@ -49,8 +51,9 @@ impl Hash {
 
     /// Generate a random Hash
     #[inline]
-    pub fn random() -> Result<Self, crate::errors::Unspecified> {
-        let random_bytes = rand::generate::<[u8; 32]>(&rand::SystemRandom::new())?;
+    pub fn random() -> Result<Self, UnspecifiedRandError> {
+        let random_bytes = rand::generate::<[u8; 32]>(&rand::SystemRandom::new())
+            .map_err(|_| UnspecifiedRandError)?;
         Ok(Hash(random_bytes.expose()))
     }
 
diff --git a/lib/crypto/src/keys/bin_signable.rs b/lib/crypto/src/keys/bin_signable.rs
index 7ae96fb108f110564b45cc299a3610e5cfd2135d..3693d40329c11ac44759c147c4159cb651053ce1 100644
--- a/lib/crypto/src/keys/bin_signable.rs
+++ b/lib/crypto/src/keys/bin_signable.rs
@@ -20,6 +20,9 @@ use serde::{Deserialize, Serialize};
 
 /// Signatureable in binary format
 pub trait BinSignable<'de>: Serialize + Deserialize<'de> {
+    /// Error when serialize self into binary
+    type SerdeError: std::error::Error;
+
     /// Return entity issuer pubkey
     fn issuer_pubkey(&self) -> PubKey;
     /// Return signature
@@ -27,7 +30,7 @@ pub trait BinSignable<'de>: Serialize + Deserialize<'de> {
     /// Change signature
     fn set_signature(&mut self, _signature: Sig);
     /// Get binary datas without signature
-    fn get_bin_without_sig(&self) -> Result<Vec<u8>, failure::Error>;
+    fn get_bin_without_sig(&self) -> Result<Vec<u8>, Self::SerdeError>;
     /// Add signature to bin datas
     fn add_sig_to_bin_datas(&self, bin_datas: &mut Vec<u8>);
     /// Sign entity with a signator
@@ -90,13 +93,15 @@ mod tests {
     }
 
     impl BinSignable<'_> for BinSignableTestImpl {
+        type SerdeError = bincode::Error;
+
         #[inline]
         fn add_sig_to_bin_datas(&self, bin_datas: &mut Vec<u8>) {
             bin_datas
                 .extend_from_slice(&bincode::serialize(&self.sig).expect("Fail to binarize sig !"));
         }
         #[inline]
-        fn get_bin_without_sig(&self) -> Result<Vec<u8>, failure::Error> {
+        fn get_bin_without_sig(&self) -> Result<Vec<u8>, bincode::Error> {
             let mut bin_msg = bincode::serialize(&self)?;
             let sig_size = bincode::serialized_size(&self.signature())?;
             let bin_msg_len = bin_msg.len();
diff --git a/lib/crypto/src/keys/ed25519.rs b/lib/crypto/src/keys/ed25519.rs
index a9abfe0afc81451dc982f96155f3223c19344c77..33f22e445acfba3e4e001129f61085302d84cfd7 100644
--- a/lib/crypto/src/keys/ed25519.rs
+++ b/lib/crypto/src/keys/ed25519.rs
@@ -23,11 +23,13 @@ use super::PublicKey as PublicKeyMethods;
 use super::{PubkeyFromBytesError, SigError};
 use crate::bases::b58::{bytes_to_str_base58, ToBase58};
 use crate::bases::*;
+use crate::rand::UnspecifiedRandError;
 use crate::seeds::Seed32;
 use base64;
 use ring::signature::{Ed25519KeyPair as RingKeyPair, KeyPair, UnparsedPublicKey, ED25519};
-use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
-use serde::ser::{Serialize, SerializeTuple, Serializer};
+use serde::de::{Deserializer, Error, SeqAccess, Visitor};
+use serde::ser::{SerializeTuple, Serializer};
+use serde::{Deserialize, Serialize};
 use std::convert::TryFrom;
 use std::fmt;
 use std::fmt::{Debug, Display, Formatter};
@@ -309,7 +311,7 @@ impl super::KeyPair for Ed25519KeyPair {
 
 impl Ed25519KeyPair {
     /// Generate random keypair
-    pub fn generate_random() -> Result<Self, crate::errors::Unspecified> {
+    pub fn generate_random() -> Result<Self, UnspecifiedRandError> {
         Ok(KeyPairFromSeed32Generator::generate(Seed32::random()?))
     }
 }
diff --git a/lib/crypto/src/keys/mod.rs b/lib/crypto/src/keys/mod.rs
index b28b431d9072e25a694dc256883cfbe0c499626e..79573f4aa9348524289cc16d35b7b20c3f3b3fd5 100644
--- a/lib/crypto/src/keys/mod.rs
+++ b/lib/crypto/src/keys/mod.rs
@@ -56,7 +56,7 @@ pub use crate::seeds::Seed32;
 
 use crate::bases::b58::ToBase58;
 use crate::bases::BaseConvertionError;
-use failure::Fail;
+use serde::{Deserialize, Serialize};
 use std::convert::TryFrom;
 use std::fmt::Debug;
 use std::fmt::Display;
@@ -64,6 +64,7 @@ use std::fmt::Error;
 use std::fmt::Formatter;
 use std::hash::Hash;
 use std::str::FromStr;
+use thiserror::Error;
 
 /// Cryptographic keys algorithms list
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
@@ -81,39 +82,39 @@ pub trait GetKeysAlgo: Clone + Debug + PartialEq + Eq {
 }
 
 /// Errors enumeration for signature verification.
-#[derive(Debug, Eq, Fail, PartialEq)]
+#[derive(Debug, Eq, Error, PartialEq)]
 pub enum SigError {
     /// Signature and pubkey are not the same algo
-    #[fail(display = "Signature and pubkey are not the same algo.")]
+    #[error("Signature and pubkey are not the same algo.")]
     NotSameAlgo,
     /// Invalid signature
-    #[fail(display = "Invalid signature.")]
+    #[error("Invalid signature.")]
     InvalidSig,
     /// Absence of signature
-    #[fail(display = "Absence of signature.")]
+    #[error("Absence of signature.")]
     NotSig,
     /// Serialization error
-    #[fail(display = "Serialization error: {}", _0)]
+    #[error("Serialization error: {0}")]
     SerdeError(String),
 }
 
 /// SignError
-#[derive(Debug, Eq, Fail, PartialEq)]
+#[derive(Debug, Eq, Error, PartialEq)]
 pub enum SignError {
     /// Corrupted key pair
-    #[fail(display = "Corrupted key pair.")]
+    #[error("Corrupted key pair.")]
     CorruptedKeyPair,
     /// WrongAlgo
-    #[fail(display = "Wrong algo.")]
+    #[error("Wrong algo.")]
     WrongAlgo,
     /// WrongPrivkey
-    #[fail(display = "Wrong private key.")]
+    #[error("Wrong private key.")]
     WrongPrivkey,
     /// AlreadySign
-    #[fail(display = "Already signed.")]
+    #[error("Already signed.")]
     AlreadySign,
     /// Serialization error
-    #[fail(display = "Serialization error: {}", _0)]
+    #[error("Serialization error: {0}")]
     SerdeError(String),
 }
 
@@ -596,14 +597,13 @@ mod tests {
     }
 
     #[test]
-    #[should_panic(
-        expected = "Try to verify a signature with key pair of a different algorithm !\n\
-                    Signature=Schnorr\nKeyPair=(4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS, hidden)"
-    )]
     fn key_pair_verify_wrong_sig_algo() {
         let false_key_pair_ed25519 = false_key_pair_ed25519();
         let false_key_pair = KeyPairEnum::Ed25519(false_key_pair_ed25519);
-        let _ = false_key_pair.verify(b"message", &Sig::Schnorr());
+        assert_eq!(
+            Err(SigError::NotSameAlgo),
+            false_key_pair.verify(b"message", &Sig::Schnorr()),
+        );
     }
 
     #[test]
@@ -656,13 +656,12 @@ mod tests {
     }
 
     #[test]
-    #[should_panic(
-        expected = "Try to verify a signature with public key of a different algorithm !\n\
-        Signature=Schnorr\nPublickey=Ed25519(PublicKey { 11111111111111111111111111111111 })"
-    )]
     fn pubkey_verify_sig_wrong_algo() {
         let pubkey = PubKey::default();
-        let _ = pubkey.verify(b"message", &Sig::Schnorr());
+        assert_eq!(
+            Err(SigError::NotSameAlgo),
+            pubkey.verify(b"message", &Sig::Schnorr()),
+        );
     }
 
     #[test]
diff --git a/lib/crypto/src/lib.rs b/lib/crypto/src/lib.rs
index ebc1f0aa222bc8e8e943dc7aa7509b022277aa1b..4c36431b691ce4533866f4d9716c21a975d0adc1 100644
--- a/lib/crypto/src/lib.rs
+++ b/lib/crypto/src/lib.rs
@@ -29,13 +29,7 @@
 )]
 #![allow(non_camel_case_types)]
 
-#[macro_use]
-extern crate failure;
-#[macro_use]
-extern crate serde_derive;
-
 pub mod bases;
-pub mod errors;
 pub mod hashs;
 pub mod keys;
 pub mod rand;
diff --git a/lib/crypto/src/rand.rs b/lib/crypto/src/rand.rs
index a0f82b6274c43483f1e1f5081a39c624bd7da04b..1b6f1024d61691b53377082b0843b7ace12ea232 100644
--- a/lib/crypto/src/rand.rs
+++ b/lib/crypto/src/rand.rs
@@ -18,11 +18,30 @@
 use byteorder::ByteOrder;
 use ring::rand;
 
+/// An error with absolutely no details.
+///
+/// *dup-crypto* uses this unit type as the error type in most of its results
+/// because (a) usually the specific reasons for a failure are obvious or are
+/// not useful to know, and/or (b) providing more details about a failure might
+/// provide a dangerous side channel, and/or (c) it greatly simplifies the
+/// error handling logic.
+///
+/// Experience with using and implementing other crypto libraries like has
+/// shown that sophisticated error reporting facilities often cause significant
+/// bugs themselves, both within the crypto library and within users of the
+/// crypto library. This approach attempts to minimize complexity in the hopes
+/// of avoiding such problems. In some cases, this approach may be too extreme,
+/// and it may be important for an operation to provide some details about the
+/// cause of a failure. Users of *dup-crypto* are encouraged to report such cases so
+/// that they can be addressed individually.
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub struct UnspecifiedRandError;
+
 #[inline]
 /// Generate random u32
-pub fn gen_u32() -> Result<u32, crate::errors::Unspecified> {
+pub fn gen_u32() -> Result<u32, UnspecifiedRandError> {
     let rng = rand::SystemRandom::new();
-    let random_bytes = rand::generate::<[u8; 4]>(&rng)?;
+    let random_bytes = rand::generate::<[u8; 4]>(&rng).map_err(|_| UnspecifiedRandError)?;
     Ok(byteorder::BigEndian::read_u32(&random_bytes.expose()))
 }
 
diff --git a/lib/crypto/src/seeds.rs b/lib/crypto/src/seeds.rs
index c35865ac586554a0a575a2bdc441a158b8916463..57b6873bc797164cc32f45f40aee41d33347d6ae 100644
--- a/lib/crypto/src/seeds.rs
+++ b/lib/crypto/src/seeds.rs
@@ -17,7 +17,9 @@
 
 use crate::bases::b58::{bytes_to_str_base58, ToBase58};
 use crate::bases::*;
+use crate::rand::UnspecifiedRandError;
 use ring::rand;
+use serde::{Deserialize, Serialize};
 use std::fmt::{self, Debug, Display, Formatter};
 use zeroize::Zeroize;
 
@@ -63,8 +65,9 @@ impl Seed32 {
     }
     #[inline]
     /// Generate random seed
-    pub fn random() -> Result<Seed32, crate::errors::Unspecified> {
-        let random_bytes = rand::generate::<[u8; 32]>(&rand::SystemRandom::new())?;
+    pub fn random() -> Result<Seed32, UnspecifiedRandError> {
+        let random_bytes = rand::generate::<[u8; 32]>(&rand::SystemRandom::new())
+            .map_err(|_| UnspecifiedRandError)?;
         Ok(Seed32::new(random_bytes.expose()))
     }
 }
diff --git a/lib/modules/ws2p/ws2p-messages/lib.rs b/lib/modules/ws2p/ws2p-messages/lib.rs
index 3ca06a2196989091aaa5d111f0cc3d7f834d08b3..661bdbbcf28b158a1fe86d43509f74f6b940a204 100644
--- a/lib/modules/ws2p/ws2p-messages/lib.rs
+++ b/lib/modules/ws2p/ws2p-messages/lib.rs
@@ -116,6 +116,8 @@ impl WS2PMessage {
 }
 
 impl<'de> BinSignable<'de> for WS2PMessage {
+    type SerdeError = bincode::Error;
+
     #[inline]
     fn add_sig_to_bin_datas(&self, bin_datas: &mut Vec<u8>) {
         bin_datas.extend_from_slice(
@@ -123,7 +125,7 @@ impl<'de> BinSignable<'de> for WS2PMessage {
         );
     }
     #[inline]
-    fn get_bin_without_sig(&self) -> Result<Vec<u8>, failure::Error> {
+    fn get_bin_without_sig(&self) -> Result<Vec<u8>, bincode::Error> {
         let mut bin_msg = bincode::serialize(&self)?;
         let sig_size = bincode::serialized_size(&self.signature())?;
         let bin_msg_len = bin_msg.len();