diff --git a/Cargo.lock b/Cargo.lock
index 52a0be76f3087d7891868b5a1142c70058af2d97..0a0b3fbe5f79254f3e4fe837be805d64b0b42d8e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6,6 +6,15 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
 
+[[package]]
+name = "aead"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cf01b9b56e767bb57b94ebf91a58b338002963785cdd7013e21c0d4679471e4"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "aes"
 version = "0.3.2"
@@ -288,6 +297,18 @@ dependencies = [
  "subtle 1.0.0",
 ]
 
+[[package]]
+name = "crypto_box"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9bbe0776bec03ad00a033d6bf9a18458781a90df99486e558e78f0fd6b15c23"
+dependencies = [
+ "rand_core",
+ "salsa20",
+ "x25519-dalek",
+ "xsalsa20poly1305",
+]
+
 [[package]]
 name = "csv"
 version = "1.1.3"
@@ -343,6 +364,7 @@ dependencies = [
  "bs58",
  "byteorder",
  "criterion",
+ "crypto_box",
  "curve25519-dalek",
  "ring",
  "scrypt",
@@ -586,6 +608,15 @@ dependencies = [
  "web-sys",
 ]
 
+[[package]]
+name = "poly1305"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5829f50f48e9ddb79f3f7c3097029d0caee30f8286accb241416df603b080b8"
+dependencies = [
+ "universal-hash",
+]
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.8"
@@ -703,6 +734,16 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
 
+[[package]]
+name = "salsa20"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "becffecaad76c7ff25f0ba16387721b48e7cfe0b04cd290478d338f4203eff3c"
+dependencies = [
+ "stream-cipher",
+ "zeroize",
+]
+
 [[package]]
 name = "same-file"
 version = "1.0.6"
@@ -812,6 +853,15 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
+[[package]]
+name = "stream-cipher"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8131256a5896cabcf5eb04f4d6dacbe1aefda854b0d9896e09cb58829ec5638c"
+dependencies = [
+ "generic-array",
+]
+
 [[package]]
 name = "subtle"
 version = "1.0.0"
@@ -928,6 +978,16 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 
+[[package]]
+name = "universal-hash"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df0c900f2f9b4116803415878ff48b63da9edb268668e08cf9292d7503114a01"
+dependencies = [
+ "generic-array",
+ "subtle 2.2.2",
+]
+
 [[package]]
 name = "untrusted"
 version = "0.7.0"
@@ -1092,6 +1152,17 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "x25519-dalek"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "637ff90c9540fa3073bb577e65033069e4bae7c79d49d74aa3ffdf5342a53217"
+dependencies = [
+ "curve25519-dalek",
+ "rand_core",
+ "zeroize",
+]
+
 [[package]]
 name = "xattr"
 version = "0.2.2"
@@ -1101,6 +1172,18 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "xsalsa20poly1305"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e183e60a53b16cb71c90200f6dc3b9fdeef410a613d1e28c3fbcbda8180e82d4"
+dependencies = [
+ "aead",
+ "poly1305",
+ "salsa20",
+ "zeroize",
+]
+
 [[package]]
 name = "zeroize"
 version = "1.1.0"
diff --git a/Cargo.toml b/Cargo.toml
index 8cbf95ba7048ad63590d2183fb4edb0ff7effe3f..58a5a14298938811f0ca0fbd058d634e59bde995 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,6 +18,7 @@ arrayvec = { version = "0.5.1", features = ["array-sizes-33-128", "array-sizes-1
 base64 = "0.11.0"
 bs58 = "0.3.0"
 byteorder = "1.3.2"
+crypto_box = { version = "0.1.0", optional = true }
 curve25519-dalek = "2.0.0"
 ring = "0.16.9"
 scrypt = { version = "0.2", default-features = false }
@@ -43,7 +44,8 @@ default = ["dewif", "private_message", "rand", "ser"]
 
 aes256 = ["aes"]
 dewif = ["aes256", "arrayvec"]
-x25519 = []
+legacy_box_nacl = ["crypto_box"]
 private_message = ["arrayvec", "x25519", "rand"]
 rand = []
 ser = ["serde"]
+x25519 = []
diff --git a/src/keys/x25519.rs b/src/keys/x25519.rs
index 00d4d2244ff378c26a116977f7f360389f9e2dd6..f6de9326d0544454b461ef88223c7a789043c48b 100644
--- a/src/keys/x25519.rs
+++ b/src/keys/x25519.rs
@@ -29,6 +29,12 @@ use zeroize::Zeroize;
 #[derive(Clone, Copy, Debug)]
 pub(crate) struct X25519PublicKey(MontgomeryPoint);
 
+impl AsRef<[u8]> for X25519PublicKey {
+    fn as_ref(&self) -> &[u8] {
+        self.0.as_bytes()
+    }
+}
+
 impl From<&PublicKey> for X25519PublicKey {
     fn from(ed25519_public_key: &PublicKey) -> Self {
         let compressed_edwards_y = CompressedEdwardsY::from_slice(ed25519_public_key.as_ref());
@@ -43,6 +49,12 @@ impl From<&PublicKey> for X25519PublicKey {
 #[zeroize(drop)]
 pub(crate) struct X25519SecretKey([u8; 32]);
 
+impl AsRef<[u8]> for X25519SecretKey {
+    fn as_ref(&self) -> &[u8] {
+        &self.0
+    }
+}
+
 impl From<&Seed32> for X25519SecretKey {
     fn from(seed: &Seed32) -> Self {
         let mut hash = [0u8; 64];
diff --git a/src/private_message.rs b/src/private_message.rs
index 6161df9429a8937a4677697d8385c1268c5d5a75..b1e820e1b8b1cfb30cd93ba8107e0ed2d020120d 100644
--- a/src/private_message.rs
+++ b/src/private_message.rs
@@ -129,6 +129,8 @@
 //!
 
 mod authentication;
+#[cfg(feature = "legacy_box_nacl")]
+mod legacy_box_nacl;
 
 pub use self::authentication::AuthenticationPolicy;
 pub use ring::aead::Aad;
diff --git a/src/private_message/legacy_box_nacl.rs b/src/private_message/legacy_box_nacl.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ef49a1ebd0ee42cf912232c5492ee6e66cbc6940
--- /dev/null
+++ b/src/private_message/legacy_box_nacl.rs
@@ -0,0 +1,96 @@
+//  Copyright (C) 2020  Éloïs SANCHEZ.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+//! Legacy crypto_box used by NaCl
+
+use crate::keys::ed25519::{Ed25519KeyPair, PublicKey as Ed25519PublicKey};
+use crate::keys::x25519::{X25519PublicKey, X25519SecretKey};
+use crypto_box::aead::generic_array::{typenum::U24, GenericArray};
+use crypto_box::{
+    aead::{Aead, Buffer},
+    Box, PublicKey, SecretKey,
+};
+use ring::error::Unspecified;
+
+pub struct Nonce(GenericArray<u8, U24>);
+
+impl AsRef<[u8]> for Nonce {
+    fn as_ref(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+/// Encrypt message
+pub fn encrypt_in_place<M>(
+    sender_key_pair: &Ed25519KeyPair,
+    receiver_public_key: &Ed25519PublicKey,
+    message: &mut M,
+) -> Result<Nonce, Unspecified>
+where
+    M: Buffer,
+{
+    let nonce = generate_nonce(&ring::rand::SystemRandom::new())?;
+
+    let x25519_secret_key = X25519SecretKey::from(sender_key_pair.seed());
+    let mut sender_secret_key = [0u8; 32];
+    sender_secret_key.copy_from_slice(x25519_secret_key.as_ref());
+    let sender_secret_key = SecretKey::from(sender_secret_key);
+
+    let x25519_public_key = X25519PublicKey::from(receiver_public_key);
+    let mut receiver_public_key = [0u8; 32];
+    receiver_public_key.copy_from_slice(x25519_public_key.as_ref());
+    let receiver_public_key = PublicKey::from(receiver_public_key);
+
+    let salsa_box = Box::new(&receiver_public_key, &sender_secret_key);
+
+    salsa_box
+        .encrypt_in_place(&nonce, &[], message)
+        .map_err(|_| Unspecified)?;
+
+    Ok(Nonce(nonce))
+}
+
+fn generate_nonce<T>(csprng: &T) -> Result<GenericArray<u8, U24>, Unspecified>
+where
+    T: ring::rand::SecureRandom,
+{
+    let mut nonce = GenericArray::default();
+    csprng.fill(&mut nonce)?;
+    Ok(nonce)
+}
+
+/// Decrypt message
+pub fn decrypt_in_place<M: Buffer>(
+    receiver_key_pair: &Ed25519KeyPair,
+    sender_public_key: &Ed25519PublicKey,
+    message: &mut M,
+    nonce: Nonce,
+) -> Result<(), Unspecified> {
+    let x25519_secret_key = X25519SecretKey::from(receiver_key_pair.seed());
+    let mut receiver_secret_key = [0u8; 32];
+    receiver_secret_key.copy_from_slice(x25519_secret_key.as_ref());
+    let receiver_secret_key = SecretKey::from(receiver_secret_key);
+
+    let x25519_public_key = X25519PublicKey::from(sender_public_key);
+    let mut sender_public_key = [0u8; 32];
+    sender_public_key.copy_from_slice(x25519_public_key.as_ref());
+    let sender_public_key = PublicKey::from(sender_public_key);
+
+    let salsa_box = Box::new(&sender_public_key, &receiver_secret_key);
+
+    salsa_box
+        .decrypt_in_place(&nonce.0, &[], message)
+        .map_err(|_| Unspecified)
+}