diff --git a/duniterpy/key/signing_key.py b/duniterpy/key/signing_key.py
index cff0452bc209f6412042603b853d5016b1428494..780d27efd662d9f927f874905bafa77e1fed7568 100644
--- a/duniterpy/key/signing_key.py
+++ b/duniterpy/key/signing_key.py
@@ -79,6 +79,60 @@ class SigningKey(libnacl.sign.Signer):
         curve25519_secret_key = libnacl.crypto_sign_ed25519_sk_to_curve25519(self.sk)
         return libnacl.crypto_box_seal_open(message, curve25519_public_key, curve25519_secret_key).decode('utf-8')
 
+    @classmethod
+    def from_pubsec_file(cls: Type[SigningKeyType], path: str) -> SigningKeyType:
+        """
+        Return SigningKey instance from Duniter WIF file
+
+        :param path: Path to WIF file
+        """
+        with open(path, 'r') as fh:
+            pubsec_content = fh.read()
+
+        # line patterns
+        regex_pubkey = compile("pub: ([1-9A-HJ-NP-Za-km-z]+)", MULTILINE)
+        regex_signkey = compile("sec: ([1-9A-HJ-NP-Za-km-z]+)", MULTILINE)
+
+        # check public key field
+        match = search(regex_pubkey, pubsec_content)
+        if not match:
+            raise Exception('Error: Bad format PubSec v1 file, missing public key')
+
+        # check signkey field
+        match = search(regex_signkey, pubsec_content)
+        if not match:
+            raise Exception('Error: Bad format PubSec v1 file, missing sec key')
+
+        # capture signkey
+        signkey_hex = match.groups()[0]
+
+        # extract seed from signkey
+        seed = bytes(Base58Encoder.decode(signkey_hex)[0:32])
+
+        return cls(seed)
+
+    def save_pubsec_file(self, path: str) -> None:
+            """
+            Save a Duniter PubSec file (PubSec) v1
+
+            :param path: Path to file
+            """
+            # version
+            version = 1
+
+            # base58 encode keys
+            base58_signing_key = Base58Encoder.encode(self.sk)
+            base58_public_key = self.pubkey
+
+            # save file
+            with open(path, 'w') as fh:
+                fh.write(
+                    """Type: PubSec
+Version: {version}
+pub: {pubkey}
+sec: {signkey}""".format(version=version, pubkey=base58_public_key, signkey=base58_signing_key)
+                )
+
     @classmethod
     def from_wif_file(cls: Type[SigningKeyType], path: str) -> SigningKeyType:
         """
@@ -89,23 +143,27 @@ class SigningKey(libnacl.sign.Signer):
         with open(path, 'r') as fh:
             wif_content = fh.read()
 
+        # check data field
         regex = compile('Data: ([1-9A-HJ-NP-Za-km-z]+)', MULTILINE)
         match = search(regex, wif_content)
         if not match:
             raise Exception('Error: Bad format WIF v1 file')
 
+        # capture hexa wif key
         wif_hex = match.groups()[0]
         wif_bytes = Base58Encoder.decode(wif_hex)
         if len(wif_bytes) != 35:
             raise Exception("Error: the size of WIF is invalid")
 
+        # extract data
         checksum_from_wif = wif_bytes[-2:]
         fi = wif_bytes[0:1]
         seed = wif_bytes[1:-2]
         seed_fi = wif_bytes[0:-2]
 
+        # check WIF format flag
         if fi != b"\x01":
-            raise Exception("Error: bad WIF version")
+            raise Exception("Error: bad format version, not WIF")
 
         # checksum control
         checksum = libnacl.crypto_hash_sha256(libnacl.crypto_hash_sha256(seed_fi))[0:2]
@@ -120,7 +178,7 @@ class SigningKey(libnacl.sign.Signer):
 
         :param path: Path to file
         """
-        # Cesium v1
+        # version
         version = 1
 
         # add format to seed (1=WIF,2=EWIF)
@@ -131,6 +189,7 @@ class SigningKey(libnacl.sign.Signer):
         sha256_v2 = libnacl.crypto_hash_sha256(sha256_v1)
         checksum = sha256_v2[0:2]
 
+        # base58 encode key and checksum
         wif_key = Base58Encoder.encode(seed_fi + checksum)
 
         with open(path, 'w') as fh:
@@ -151,16 +210,19 @@ Data: {data}""".format(version=version, data=wif_key)
         with open(path, 'r') as fh:
             wif_content = fh.read()
 
+        # check data field
         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')
 
+        # capture ewif key
         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")
 
+        # extract data
         fi = ewif_bytes[0:1]
         checksum_from_ewif = ewif_bytes[-2:]
         ewif_no_checksum = ewif_bytes[0:-2]
@@ -168,8 +230,9 @@ Data: {data}""".format(version=version, data=wif_key)
         encryptedhalf1 = ewif_bytes[5:21]
         encryptedhalf2 = ewif_bytes[21:37]
 
+        # check format flag
         if fi != b"\x02":
-            raise Exception("Error: bad EWIF version")
+            raise Exception("Error: bad format version, not EWIF")
 
         # checksum control
         checksum = libnacl.crypto_hash_sha256(libnacl.crypto_hash_sha256(ewif_no_checksum))[0:2]
@@ -209,7 +272,7 @@ Data: {data}""".format(version=version, data=wif_key)
         :param path: Path to file
         :param password:
         """
-        # WIF Format version
+        # version
         version = 1
 
         # add version to seed
diff --git a/examples/save_and_load_private_key_file_pubsec.py b/examples/save_and_load_private_key_file_pubsec.py
new file mode 100644
index 0000000000000000000000000000000000000000..6447756e9e16872bf47c45f7a35d87390651f6de
--- /dev/null
+++ b/examples/save_and_load_private_key_file_pubsec.py
@@ -0,0 +1,58 @@
+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_pubsec_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)
+
+# save private key in a file (PubSec v1 format)
+signer.save_pubsec_file(PRIVATE_KEY_FILE_PATH)
+
+# 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_pubsec_file(PRIVATE_KEY_FILE_PATH)
+
+    # 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)