diff --git a/duniterpy/helpers.py b/duniterpy/helpers.py
index 5e7f68b01605c2d4808ec56c8cf696fb5b7bb8b8..251a53f095f9838880836784e23d3066d93467ad 100644
--- a/duniterpy/helpers.py
+++ b/duniterpy/helpers.py
@@ -25,3 +25,17 @@ def ensure_str(data: Union[str, bytes]) -> str:
         return str(data, 'utf-8')
 
     return data
+
+
+def xor_bytes(b1: bytes, b2: bytes) -> bytearray:
+    """
+    Apply XOR operation on two bytes arguments
+
+    :param b1: First bytes argument
+    :param b2: Second bytes argument
+    :rtype bytearray:
+    """
+    result = bytearray()
+    for i1, i2 in zip(b1, b2):
+        result.append(i1 ^ i2)
+    return result
diff --git a/duniterpy/key/signing_key.py b/duniterpy/key/signing_key.py
index e2cfbe8a940a5b8da3884cf5a08b59f1dec925c6..cff0452bc209f6412042603b853d5016b1428494 100644
--- a/duniterpy/key/signing_key.py
+++ b/duniterpy/key/signing_key.py
@@ -7,10 +7,11 @@ from re import compile, MULTILINE, search
 from typing import Optional, Union, TypeVar, Type
 
 import libnacl.sign
+import pyaes
 from pylibscrypt import scrypt
 
 from .base58 import Base58Encoder
-from ..helpers import ensure_bytes
+from ..helpers import ensure_bytes, xor_bytes
 
 SEED_LENGTH = 32  # Length of the key
 crypto_sign_BYTES = 64
@@ -81,7 +82,7 @@ class SigningKey(libnacl.sign.Signer):
     @classmethod
     def from_wif_file(cls: Type[SigningKeyType], path: str) -> SigningKeyType:
         """
-        Return SigningKey instance from Duniter WIF v1 file
+        Return SigningKey instance from Duniter WIF file
 
         :param path: Path to WIF file
         """
@@ -113,17 +114,17 @@ class SigningKey(libnacl.sign.Signer):
 
         return cls(seed)
 
-    def save_wif(self, path: str) -> None:
+    def save_wif_file(self, path: str) -> None:
         """
-        Save a Wallet Import Format file (v1)
+        Save a Wallet Import Format file (WIF) v1
 
         :param path: Path to file
         """
         # Cesium v1
         version = 1
 
-        # add version to seed
-        seed_fi = version.to_bytes(version, 'little') + self.seed
+        # add format to seed (1=WIF,2=EWIF)
+        seed_fi = b"\x01" + self.seed
 
         # calculate checksum
         sha256_v1 = libnacl.crypto_hash_sha256(seed_fi)
@@ -136,5 +137,116 @@ class SigningKey(libnacl.sign.Signer):
             fh.write(
                 """Type: WIF
 Version: {version}
-Data: {data}""".format(version=1, data=wif_key)
+Data: {data}""".format(version=version, data=wif_key)
+            )
+
+    @classmethod
+    def from_ewif_file(cls: Type[SigningKeyType], path: str, password: str) -> SigningKeyType:
+        """
+        Return SigningKey instance from Duniter EWIF file
+
+        :param path: Path to WIF file
+        :param password: Password of the encrypted seed
+        """
+        with open(path, 'r') as fh:
+            wif_content = fh.read()
+
+        regex = compile('Data: ([1-9A-HJ-NP-Za-km-z]+)', MULTILINE)
+        match = search(regex, wif_content)
+        if not match:
+            raise Exception('Error: Bad format EWIF v1 file')
+
+        ewif_hex = match.groups()[0]
+        ewif_bytes = Base58Encoder.decode(ewif_hex)
+        if len(ewif_bytes) != 39:
+            raise Exception("Error: the size of EWIF is invalid")
+
+        fi = ewif_bytes[0:1]
+        checksum_from_ewif = ewif_bytes[-2:]
+        ewif_no_checksum = ewif_bytes[0:-2]
+        salt = ewif_bytes[1:5]
+        encryptedhalf1 = ewif_bytes[5:21]
+        encryptedhalf2 = ewif_bytes[21:37]
+
+        if fi != b"\x02":
+            raise Exception("Error: bad EWIF version")
+
+        # checksum control
+        checksum = libnacl.crypto_hash_sha256(libnacl.crypto_hash_sha256(ewif_no_checksum))[0:2]
+        if checksum_from_ewif != checksum:
+            raise Exception("Error: bad checksum of the EWIF")
+
+        # SCRYPT
+        password_bytes = password.encode("utf-8")
+        scrypt_seed = scrypt(password_bytes, salt, 16384, 8, 8, 64)
+        derivedhalf1 = scrypt_seed[0:32]
+        derivedhalf2 = scrypt_seed[32:64]
+
+        # AES
+        aes = pyaes.AESModeOfOperationECB(derivedhalf2)
+        decryptedhalf1 = aes.decrypt(encryptedhalf1)
+        decryptedhalf2 = aes.decrypt(encryptedhalf2)
+
+        # XOR
+        seed1 = xor_bytes(decryptedhalf1, derivedhalf1[0:16])
+        seed2 = xor_bytes(decryptedhalf2, derivedhalf1[16:32])
+        seed = bytes(seed1 + seed2)
+
+        # Password Control
+        signer = SigningKey(seed)
+        salt_from_seed = libnacl.crypto_hash_sha256(
+            libnacl.crypto_hash_sha256(
+                Base58Encoder.decode(signer.pubkey)))[0:4]
+        if salt_from_seed != salt:
+            raise Exception("Error: bad Password of EWIF address")
+
+        return cls(seed)
+
+    def save_ewif_file(self, path: str, password: str) -> None:
+        """
+        Save an Encrypted Wallet Import Format file (WIF v2)
+
+        :param path: Path to file
+        :param password:
+        """
+        # WIF Format version
+        version = 1
+
+        # add version to seed
+        salt = libnacl.crypto_hash_sha256(
+            libnacl.crypto_hash_sha256(
+                Base58Encoder.decode(self.pubkey)))[0:4]
+
+        # SCRYPT
+        password_bytes = password.encode("utf-8")
+        scrypt_seed = scrypt(password_bytes, salt, 16384, 8, 8, 64)
+        derivedhalf1 = scrypt_seed[0:32]
+        derivedhalf2 = scrypt_seed[32:64]
+
+        # XOR
+        seed1_xor_derivedhalf1_1 = bytes(xor_bytes(self.seed[0:16], derivedhalf1[0:16]))
+        seed2_xor_derivedhalf1_2 = bytes(xor_bytes(self.seed[16:32], derivedhalf1[16:32]))
+
+        # AES
+        aes = pyaes.AESModeOfOperationECB(derivedhalf2)
+        encryptedhalf1 = aes.encrypt(seed1_xor_derivedhalf1_1)
+        encryptedhalf2 = aes.encrypt(seed2_xor_derivedhalf1_2)
+
+        # add format to final seed (1=WIF,2=EWIF)
+        seed_bytes = b'\x02' + salt + encryptedhalf1 + encryptedhalf2
+
+        # calculate checksum
+        sha256_v1 = libnacl.crypto_hash_sha256(seed_bytes)
+        sha256_v2 = libnacl.crypto_hash_sha256(sha256_v1)
+        checksum = sha256_v2[0:2]
+
+        # B58 encode final key string
+        ewif_key = Base58Encoder.encode(seed_bytes + checksum)
+
+        # save file
+        with open(path, 'w') as fh:
+            fh.write(
+                """Type: EWIF
+Version: {version}
+Data: {data}""".format(version=version, data=ewif_key)
             )
diff --git a/examples/save_and_load_private_key_file_ewif.py b/examples/save_and_load_private_key_file_ewif.py
new file mode 100644
index 0000000000000000000000000000000000000000..6fe0a68208dd6b19eac2a71b79e44c0db92031c4
--- /dev/null
+++ b/examples/save_and_load_private_key_file_ewif.py
@@ -0,0 +1,61 @@
+from duniterpy.key import SigningKey
+import getpass
+import os
+
+if "XDG_CONFIG_HOME" in os.environ:
+    home_path = os.environ["XDG_CONFIG_HOME"]
+elif "HOME" in os.environ:
+    home_path = os.environ["HOME"]
+elif "APPDATA" in os.environ:
+    home_path = os.environ["APPDATA"]
+else:
+    home_path = os.path.dirname(__file__)
+
+# CONFIG #######################################
+
+# WARNING : Hide this file in a safe and secure place
+# If one day you forget your credentials,
+# you'll have to use one of your private keys instead
+PRIVATE_KEY_FILE_PATH = os.path.join(home_path, ".duniter_account_ewif_v1.duniterkey")
+
+################################################
+
+# prompt hidden user entry
+salt = getpass.getpass("Enter your passphrase (salt): ")
+
+# prompt hidden user entry
+password = getpass.getpass("Enter your password: ")
+
+# prompt public key
+pubkey = input("Enter your public key: ")
+
+# init signer instance
+signer = SigningKey.from_credentials(salt, password)
+
+# check public key
+if signer.pubkey != pubkey:
+    print("Bad credentials!")
+    exit(1)
+
+# prompt hidden user entry
+ewif_password = getpass.getpass("Enter an encryption password: ")
+
+# save private key in a file (EWIF v1 format)
+signer.save_ewif_file(PRIVATE_KEY_FILE_PATH, ewif_password)
+
+# document saved
+print("Private key for public key %s saved in %s" % (signer.pubkey, PRIVATE_KEY_FILE_PATH))
+
+try:
+    # load private keys from file
+    loaded_signer = SigningKey.from_ewif_file(PRIVATE_KEY_FILE_PATH, ewif_password)
+
+    # check public key from file
+    print("Public key %s loaded from file %s" % (loaded_signer.pubkey, PRIVATE_KEY_FILE_PATH))
+
+except Exception as e:
+    print(e)
+    exit(1)
+
+
+exit(0)
diff --git a/examples/save_and_load_private_key_file_wif.py b/examples/save_and_load_private_key_file_wif.py
index 944269adaabe2881acaeba318c87caded6d40275..568b9a4157b2bf3b5199b8b9534d8dc32dd6120a 100644
--- a/examples/save_and_load_private_key_file_wif.py
+++ b/examples/save_and_load_private_key_file_wif.py
@@ -1,5 +1,4 @@
 from duniterpy.key import SigningKey
-from libnacl.utils import load_key
 import getpass
 import os
 
@@ -39,7 +38,7 @@ if signer.pubkey != pubkey:
     exit(1)
 
 # save private key in a file (WIF v1 format)
-signer.save_wif(PRIVATE_KEY_FILE_PATH)
+signer.save_wif_file(PRIVATE_KEY_FILE_PATH)
 
 # document saved
 print("Private key for public key %s saved in %s" % (signer.pubkey, PRIVATE_KEY_FILE_PATH))
diff --git a/requirements.txt b/requirements.txt
index 38c71ad378007086211cfe5d8f4fde06629f5fb5..91829112429a6ad57982cc59bb4553216d7ff504 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ base58 >= 1.0.0
 jsonschema >= 2.6.0
 pypeg2 >= 2.15.2
 attr >= 0.3.1
+pyaes >= 1.6.1
\ No newline at end of file