diff --git a/Pipfile b/Pipfile index 1f702da2550e18f9226fa71d7b7a715fb65e5387..2683ed8235ef94b5dd4097a23d1821b1c4fe81bc 100644 --- a/Pipfile +++ b/Pipfile @@ -7,8 +7,6 @@ name = "pypi" commandlines = "*" ipaddress = "*" tabulate = "*" -scrypt = "*" -pyaes = "*" PyNaCl = "*" "e1839a8" = {path = ".", editable = true} duniterpy = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 787e259103d47a3d4d3fdcf5b6bde950dc2912eb..0139803abc63d598202218b9acc4dc9a609a6516 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "326def4889200eb4c485b5c4e8d633c1987e9f9fdeaefc233ac44f9f7af2d332" + "sha256": "2e209d428ac040de3bbcb1d6166f6ee0e1e20741913b75f8b01bc703469b9e9b" }, "pipfile-spec": 6, "requires": { @@ -203,7 +203,6 @@ "hashes": [ "sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f" ], - "index": "pypi", "version": "==1.6.1" }, "pycparser": { @@ -255,24 +254,6 @@ ], "version": "==0.14.9" }, - "scrypt": { - "hashes": [ - "sha256:18ccbc63d87c6f89b753194194bb37aeaf1abc517e4b989461d115c1d93ce128", - "sha256:232acdbc3434d2de55def8d5dbf1bc4b9bfc50da7c5741df2a6eebc4e18d3720", - "sha256:475ac80239b3d788ae71a09c3019ca915e149aaa339adcdd1c9eef121293dc88", - "sha256:4ad7188f2e42dbee2ff1cd72e3da40b170ba41847effbf0d726444f62ae60f3a", - "sha256:85919f023148cd9fb01d75ad4e3e061928c298fa6249a0cd6cd469c4b947595e", - "sha256:971db040d3963ebe4b919a203fe10d7d6659951d3644066314330983dc175ed4", - "sha256:a124719c686f2b5957e392465147fb3fd6077e7c643e9538cab1ee631eb01dde", - "sha256:a343c302b3e99dcb7fcbe57aa7919ed761f1568f854291ccebe1b5e6e2c9e509", - "sha256:bc131f74a688fa09993c518ca666a2ebd4268b207e039cbab03a034228140d3e", - "sha256:c23daecee405cb036845917295c76f8d747fc890158df40cb304b4b3c3640079", - "sha256:dc40f0e1a357a49ca62f30f2fc09e92e02c062a656f27949b436b2ba8002d9e1", - "sha256:f8239b2d47fa1d40bc27efd231dc7083695d10c1c2ac51a99380360741e0362d" - ], - "index": "pypi", - "version": "==0.8.6" - }, "six": { "hashes": [ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", diff --git a/README.md b/README.md index 30a424422af9f9fc9d17b0a4183ab2d88caca4ef..b093a0542e90851fd31d98bdd3b8a72b9179229e 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,6 @@ Silkaj is based on Python dependencies: - [Tabulate](https://bitbucket.org/astanin/python-tabulate/overview): to display charts. - [Commandlines](https://github.com/chrissimpkins/commandlines): to parse command and sub-commands. - [PyNaCl](https://github.com/pyca/pynacl/): Cryptography (NaCl) library. -- [scrypt](https://bitbucket.org/mhallin/py-scrypt): scrypt key derivation function. -- [pyaes](https://github.com/ricmoo/pyaes): Pure-Python implementation of AES ### Names I wanted to call that program: diff --git a/setup.py b/setup.py index 7b3b895d84e4c76b4483e358d4c2de84b389a799..dc283cea4857d1745b852a1756d72d225310aecc 100644 --- a/setup.py +++ b/setup.py @@ -28,8 +28,6 @@ setuptools.setup( "ipaddress", "tabulate", "pynacl", - "scrypt", - "pyaes", ], scripts=["bin/silkaj"], ) diff --git a/silkaj/auth.py b/silkaj/auth.py index 92cde61a2034cff8c0d44a9c49031bc0f57b30e9..d65da3a5388b861d78a974112ffef7bbf6388e6e 100644 --- a/silkaj/auth.py +++ b/silkaj/auth.py @@ -15,16 +15,14 @@ You should have received a copy of the GNU Affero General Public License along with Silkaj. If not, see <https://www.gnu.org/licenses/>. """ -from silkaj.crypto_tools import get_publickey_from_seed, b58_decode, xor_bytes +from silkaj.crypto_tools import get_publickey_from_seed, b58_decode from silkaj.tools import message_exit from nacl import encoding import nacl.hash -from scrypt import hash -import pyaes from getpass import getpass from os import path from re import compile, search - +from duniterpy.key import SigningKey def auth_method(cli_args): if cli_args.contains_switches("auth-seed"): @@ -115,109 +113,17 @@ def auth_by_scrypt(cli_args): def auth_by_wif(): - wif = input("Please enter your WIF or Encrypted WIF address: ") - - regex = compile("^[1-9A-HJ-NP-Za-km-z]*$") - if not search(regex, wif): - message_exit("Error: the format of WIF is invalid") - - wif_bytes = b58_decode(wif) - fi = wif_bytes[0:1] - - if fi == b"\x01": - return get_seed_from_wifv1(wif) - elif fi == b"\x02": - password = getpass("Please enter the " + "password of WIF (masked): ") - return get_seed_from_ewifv1(wif, password) - - message_exit("Error: the format of WIF is invalid or unknown") + wif_hex = getpass("Enter your WIF or Encrypted WIF address (masked): ") + password = getpass( + "(Leave empty in case WIF format) Enter the Encrypted WIF password (masked): " + ) + try: + return SigningKey.from_wif_or_ewif_hex(wif_hex, password) + except Exception as error: + message_exit(error) def get_seed_from_scrypt(salt, password, N=4096, r=16, p=1): seed = hash(password, salt, N, r, p, 32) seedhex = encoding.HexEncoder.encode(seed).decode("utf-8") return seedhex - - -def get_seed_from_wifv1(wif): - regex = compile("^[1-9A-HJ-NP-Za-km-z]*$") - if not search(regex, wif): - message_exit("Error: the format of WIF is invalid") - - wif_bytes = b58_decode(wif) - if len(wif_bytes) != 35: - message_exit("Error: the size of WIF is invalid") - - checksum_from_wif = wif_bytes[-2:] - fi = wif_bytes[0:1] - seed = wif_bytes[1:-2] - seed_fi = wif_bytes[0:-2] - - if fi != b"\x01": - message_exit("Error: It's not a WIF format") - - # checksum control - checksum = nacl.hash.sha256( - nacl.hash.sha256(seed_fi, encoding.RawEncoder), encoding.RawEncoder - )[0:2] - if checksum_from_wif != checksum: - message_exit("Error: bad checksum of the WIF") - - seedhex = encoding.HexEncoder.encode(seed).decode("utf-8") - return seedhex - - -def get_seed_from_ewifv1(ewif, password): - regex = compile("^[1-9A-HJ-NP-Za-km-z]*$") - if not search(regex, ewif): - message_exit("Error: the format of EWIF is invalid") - - wif_bytes = b58_decode(ewif) - if len(wif_bytes) != 39: - message_exit("Error: the size of EWIF is invalid") - - wif_no_checksum = wif_bytes[0:-2] - checksum_from_ewif = wif_bytes[-2:] - fi = wif_bytes[0:1] - salt = wif_bytes[1:5] - encryptedhalf1 = wif_bytes[5:21] - encryptedhalf2 = wif_bytes[21:37] - - if fi != b"\x02": - message_exit("Error: It's not a EWIF format") - - # Checksum Control - checksum = nacl.hash.sha256( - nacl.hash.sha256(wif_no_checksum, encoding.RawEncoder), encoding.RawEncoder - )[0:2] - if checksum_from_ewif != checksum: - message_exit("Error: bad checksum of EWIF address") - - # SCRYPT - password = password.encode("utf-8") - scrypt_seed = hash(password, 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 = seed1 + seed2 - seedhex = encoding.HexEncoder.encode(seed).decode("utf-8") - - # Password Control - salt_from_seed = nacl.hash.sha256( - nacl.hash.sha256( - b58_decode(get_publickey_from_seed(seedhex)), encoding.RawEncoder - ), - encoding.RawEncoder, - )[0:4] - if salt_from_seed != salt: - message_exit("Error: bad Password of EWIF address") - - return seedhex diff --git a/silkaj/crypto_tools.py b/silkaj/crypto_tools.py index f04e1e46bd6237e704a0975a680b472a94d271bd..19378c7dd373a575133c11c621d7103750b0d223 100644 --- a/silkaj/crypto_tools.py +++ b/silkaj/crypto_tools.py @@ -112,10 +112,3 @@ def b58_decode(s): else: break return b"\x00" * pad + res - - -def xor_bytes(b1, b2): - result = bytearray() - for b1, b2 in zip(b1, b2): - result.append(b1 ^ b2) - return result