diff --git a/keys/ed25519.rs b/keys/ed25519.rs
index 8bb13a9108dcc9a44544c50a8b522ca3fc5c2b78..cbf63730d19b174946661c6a5e90e3fb0d7afa00 100644
--- a/keys/ed25519.rs
+++ b/keys/ed25519.rs
@@ -211,6 +211,45 @@ impl super::PrivateKey for PrivateKey {
     }
 }
 
+/// Store a ed25519 cryptographic key pair (`PublicKey` + `PrivateKey`)
+#[derive(Debug, Copy, Clone)]
+pub struct KeyPair {
+    /// Store a Ed25519 public key.
+    pub pubkey:PublicKey,
+    /// Store a Ed25519 private key.
+    privkey:PrivateKey,
+}
+
+impl Display for KeyPair {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+        write!(f, "{}", self.pubkey.to_base58())
+    }
+}
+
+impl PartialEq<KeyPair> for KeyPair {
+    fn eq(&self, other: &KeyPair) -> bool {
+        self.pubkey.eq(&other.pubkey) && self.privkey.eq(&other.privkey)
+    }
+}
+
+impl Eq for KeyPair {}
+
+impl super::KeyPair for KeyPair {
+    type Signature = Signature;
+
+    fn new(password: &[u8], salt: &[u8]) -> KeyPair {
+        let generator = self::KeyPairGenerator::with_default_parameters();
+        let (privkey, pubkey) = generator.generate(password, salt);
+        KeyPair {
+            pubkey,
+            privkey
+        }
+    }
+    fn sign(&self, message: &[u8]) -> Signature {
+        Signature(crypto::ed25519::signature(message, &self.privkey.0))
+    }
+}
+
 /// Keypair generator with given parameters for `scrypt` keypair function.
 #[derive(Debug, Copy, Clone)]
 pub struct KeyPairGenerator {
@@ -264,7 +303,7 @@ impl KeyPairGenerator {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use {PrivateKey, PublicKey, Signature};
+    use {PrivateKey, PublicKey, Signature, KeyPair};
 
     #[test]
     fn base58_private_key() {
@@ -284,12 +323,12 @@ mod tests {
             super::PrivateKey::from_base58(private58).unwrap()
         );
 
-        assert_eq!(
-            super::PrivateKey::from_base58(
-                "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iA\
-                fZACm7djh",
-            ).unwrap_err(),
-            BaseConvertionError::InvalidKeyLendth(67, 64)
+        assert_eq!(
+            super::PrivateKey::from_base58(
+                "468Q1XtTq7h84NorZdWBZFJrGkB18CbmbHr9tkp9snt5GiERP7ySs3wM8myLccbAAGejgMRC9rqnXuW3iA\
+                fZACm7djh",
+            ).unwrap_err(),
+            BaseConvertionError::InvalidKeyLendth(67, 64)
         );
         assert_eq!(
             super::PrivateKey::from_base58(
@@ -381,12 +420,12 @@ mod tests {
              MMmQCRerlF/3pc4sAcsnexsxBseA/3lY03KlONqJBAg==",
         ).unwrap();
 
-        let message = "Version: 10
-Type: Identity
-Currency: duniter_unit_test_currency
-Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
-UniqueID: tic
-Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+        let message = "Version: 10
+Type: Identity
+Currency: duniter_unit_test_currency
+Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
+UniqueID: tic
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
 ";
 
         let sig = prikey.sign(message.as_bytes());
@@ -394,4 +433,20 @@ Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
         assert_eq!(sig, expected_signature);
         assert!(pubkey.verify(message.as_bytes(), &sig));
     }
+
+    #[test]
+    fn keypair_generate_sign_and_verify () {
+        let keypair = super::KeyPair::new("password".as_bytes(), "salt".as_bytes());
+
+        let message = "Version: 10
+Type: Identity
+Currency: duniter_unit_test_currency
+Issuer: DNann1Lh55eZMEDXeYt59bzHbA3NJR46DeQYCS2qQdLV
+UniqueID: tic
+Timestamp: 0-E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855
+";
+
+        let sig = keypair.sign(message.as_bytes());
+        assert!(keypair.pubkey.verify(message.as_bytes(), &sig));
+    }
 }
diff --git a/keys/lib.rs b/keys/lib.rs
index 49842a68658245ab861addd34c659bd00596a0ab..f765bc5795e02bfa3940a931e89e1abc92ab86ff 100644
--- a/keys/lib.rs
+++ b/keys/lib.rs
@@ -147,3 +147,15 @@ pub trait PrivateKey: Clone + Display + Debug + PartialEq + Eq + ToBase58 {
     /// Sign a message with this private key.
     fn sign(&self, message: &[u8]) -> Self::Signature;
 }
+
+/// Store a cryptographic key pair (`PublicKey` + `PrivateKey`)
+pub trait KeyPair: Clone + Display + Debug + PartialEq + Eq {
+    /// Signature type of associated cryptosystem.
+    type Signature: Signature;
+
+    /// Create a new KeyPair
+    fn new(password: &[u8], salt: &[u8]) -> Self;
+
+    /// Sign a message with privkey.
+    fn sign(&self, message: &[u8]) -> Self::Signature;
+}