diff --git a/LICENSE b/LICENSE index 29254c4..265bd42 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Zaman +Copyright (c) 2023 Zaman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4b555df..aeaf5d0 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,109 @@ # wdpass + WD Passport Ultra Complete Utilities for Linux. Thanks to: + - [Dan Lenski](https://github.com/dlenski) for [py_sg](https://pypi.org/project/py_sg/) (Python2) - [0-duke](https://github.com/0-duke) and [derekhe](https://github.com/derekhe) for [wdpassport-utils](https://github.com/derekhe/wdpassport-utils) (Python2) -- [crypto-universe](https://github.com/crypto-universe/) for Python3 migration of [py_sg](https://github.com/crypto-universe/py3_sg) and [wdpassport-utils](https://github.com/crypto-universe/wdpassport-utils) +- [tvladyslav](https://github.com/tvladyslav/) for Python3 migration of [py_sg](https://github.com/tvladyslav/py3_sg) and [wdpassport-utils](https://github.com/tvladyslav/wdpassport-utils) ## Intro -This script let you unlock, change password and erase Western Digital Passport devices on Linux platform. +This script let you unlock, change password and erase Western Digital Passport devices on Linux platform. + +## Requirements + +- Install `lsscsi` package or any package that provides `lsscsi` command in your linux distro. ## Install +### Install the latest version from PyPi + +```shell +sudo python3 -m pip install wdpass +``` + ### Install the latest version manually -- Install `lsscsi` package or any package that provides `lsscsi` command. - Provide `` header file by installing Python Developer Package. (usually `python3-dev` or `python3-devel`) -- Install the latest py3_sg from [py3_sg](https://github.com/crypto-universe/py3_sg) +- Install the latest py3_sg from [py3_sg](https://github.com/tvladyslav/py3_sg) - And finally install `wdpass` from this repository. For example on Ubuntu: ```shell sudo apt install lsscsi python3-dev -sudo python3 -m pip install https://github.com/crypto-universe/py3_sg/archive/master.zip +sudo python3 -m pip install https://github.com/tvladyslav/py3_sg/archive/master.zip sudo python3 -m pip install https://github.com/7aman/wdpass/archive/master.zip ``` -### Install an old version from PyPi - -PyPi package is not based on the latest version but it works for most cases. - -```shell -# install v0.0.3 -sudo python3 -m pip install wdpass -``` - ## Usage -Run script as root. +Run `wdpass` as root. There are few options: -``` + +```shell -h, --help show this help message and exit ``` + Lists all possible arguments. -``` +```shell -s, --status Check device status and encryption type ``` + Get device encryption status and cipher suites used. -``` + +```shell -u, --unlock Unlock ``` + You will be asked to enter the unlock password. If everything is fine device will be unlocked. -``` +```shell -us, --unlock_with_saved_passwd Unlock with the password saved ``` + Unlock using the saved password. If everything is fine device will be unlocked. -``` +```shell -sp, --save_passwd Save password ``` + When unlock password, it will save user password to passwd.bin, so you can use "-us" for next time to auto unlock. -``` +```shell -m, --mount Enable mount point for an unlocked device ``` -After unlock, your operating system still thinks that your device is a strange thing attached to his usb port and he don't know how to manage. You need this option to force the O.S. to rescan the device and handle it as a normal external usb harddrive. -``` +After unlock, your operating system still thinks that your device is a strange thing attached to his usb port and he don't know how to manage. You need this option to force the O.S. to re-scan the device and handle it as a normal external usb hard drive. + +```shell -c, --change_passwd Change (or disable) password ``` + This option let you to encrypt your device, remove password protection and change your current password. If device is "without lock" and you want it to be password protect leave the "OLD password" field empty and choose insert the new password. -If the device is password protected and you want to be as a normal unencrypted device, inser the old password and leave the "NEW password" field empty. +If the device is password protected and you want to be as a normal unencrypted device, insert the old password and leave the "NEW password" field empty. If you only want to change password do it as usual. -``` +```shell -e, --erase Secure erase device ``` + "Erase" the device. This will remove the internal key associated to you password and all your data will be unaccessible. You will also lose your partition table and you will need to create a new one (you can use fdisk and mkfs). -``` +```shell -d DEVICE, --device DEVICE Force device path (ex. /dev/sdb). Usually you don't need this option. ``` + The script will try to auto detect the current device path of your WD Passport device. If something is wrong or you want to manually specify the device path yourself you can use this option. ## Disclaimer + I'm in no way sponsored by or connected with Western Digital. Use any of the information contained in this repository at your own risk. I accept no responsibility. diff --git a/cspell.json b/cspell.json new file mode 100644 index 0000000..838265d --- /dev/null +++ b/cspell.json @@ -0,0 +1,26 @@ +{ + "version": "0.2", + "ignorePaths": [], + "dictionaryDefinitions": [], + "dictionaries": [], + "words": [ + "derekhe", + "devel", + "distro", + "fdisk", + "geteuid", + "htonl", + "htons", + "pwblen", + "tvladyslav", + "Unlocker", + "urandom", + "wdpass", + "wdpassport", + "Zaman" + ], + "ignoreWords": [ + "Lenski" + ], + "import": [] +} diff --git a/setup.py b/setup.py index 712c7f6..07fd0cd 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ entry_points={ 'console_scripts': ['wdpass=wdpass:main'], }, - install_requires=["py_sg >= 0.14"], + install_requires=["py3_sg >= 0.16"], python_requires='>=3.6', zip_safe=False, keywords='HDD WD MyPassport Unlocker WesternDigital', diff --git a/wdpass/__init__.py b/wdpass/__init__.py index 8afa0be..c8a8e4b 100644 --- a/wdpass/__init__.py +++ b/wdpass/__init__.py @@ -10,15 +10,14 @@ import subprocess try: - import py_sg + import py3_sg except ImportError as e: print(e) - print("You need to install the 'py_sg' module.") - print("More info: https://github.com/crypto-universe/py3_sg") + print("You need to install the 'py3_sg' module.") + print("More info: https://github.com/tvladyslav/py3_sg") sys.exit(1) BLOCK_SIZE = 512 -HANDSTORESECURITYBLOCK = 1 dev = None @@ -163,7 +162,7 @@ def read_handy_store(page): for c in htonl(page): cdb[i] = c i += 1 - return py_sg.read_as_bin_str(dev, _scsi_pack_cdb(cdb), BLOCK_SIZE) + return py3_sg.read_as_bin_str(dev, _scsi_pack_cdb(cdb), BLOCK_SIZE) def hsb_checksum(data): @@ -186,7 +185,7 @@ def get_encryption_status(): 0x02 => Unlocked 0x06 => Locked, unlock blocked 0x07 => No keys - CurrentChiperID + CurrentCipherID 0x10 => AES_128_ECB 0x12 => AES_128_CBC 0x18 => AES_128_XTS @@ -197,11 +196,11 @@ def get_encryption_status(): KeyResetEnabler (4 bytes that change every time) ''' cdb = [0xC0, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00] - data = py_sg.read_as_bin_str(dev, _scsi_pack_cdb(cdb), BLOCK_SIZE) + data = py3_sg.read_as_bin_str(dev, _scsi_pack_cdb(cdb), BLOCK_SIZE) if data[0] != 0x45: fail(f"Wrong encryption status signature {data[0]:#x}") sys.exit(1) - # (SecurityStatus, CurrentChiperID, KeyResetEnabler) + # (SecurityStatus, CurrentCipherID, KeyResetEnabler) return (data[3], data[4], data[8:12]) @@ -293,7 +292,7 @@ def unlock(save_passwd, unlock_with_saved_passwd): cdb[8] = pwblen + 8 try: - py_sg.write(dev, _scsi_pack_cdb(cdb), + py3_sg.write(dev, _scsi_pack_cdb(cdb), _scsi_pack_cdb(pw_block) + pwd_hashed) success("Device unlocked.") except: @@ -364,7 +363,7 @@ def change_password(): cdb[8] = 8 + 2 * pwblen try: - py_sg.write(dev, _scsi_pack_cdb(cdb), _scsi_pack_cdb( + py3_sg.write(dev, _scsi_pack_cdb(cdb), _scsi_pack_cdb( pw_block) + old_passwd_hashed + new_passwd_hashed) success("Password changed.") except: @@ -398,13 +397,13 @@ def secure_erase(cipher_id=0): fail(f"Unsupported cipher {cipher_id:#x}") sys.exit(1) - # Set the actual lenght of pw_block (8 bytes + pwblen pseudorandom data) + # Set the actual length of pw_block (8 bytes + pwblen pseudorandom data) cdb[8] = pwblen + 8 # Fill pw_block with random data for rand_byte in os.urandom(pwblen): pw_block.append(rand_byte) - # key_reset needs to be retrieved immidiatly before the reset request + # key_reset needs to be retrieved immediately before the reset request key_reset = get_encryption_status()[2] i = 2 for c in key_reset: @@ -412,7 +411,7 @@ def secure_erase(cipher_id=0): i += 1 try: - py_sg.write(dev, _scsi_pack_cdb(cdb), _scsi_pack_cdb(pw_block)) + py3_sg.write(dev, _scsi_pack_cdb(cdb), _scsi_pack_cdb(pw_block)) success( "Device erased. You need to create a new partition on the device (Hint: fdisk and mkfs)") except: @@ -479,7 +478,7 @@ def enable_mount(device): ) success( - "Now depending on your system you can mount your device or it will be automagically mounted.") + "Now depending on your system you can mount your device or it will be automatically mounted.") else: fail("Device needs to be unlocked in order to mount it.") @@ -495,7 +494,7 @@ def get_device(device): stdout=subprocess.PIPE) if int(p.stdout.read().rstrip()) > 1: - fail("Multiple occurences of 'My Passport' detected.") + fail("Multiple occurrences of 'My Passport' detected.") fail("You should specify a device manually (with -d option).") sys.exit(1) diff --git a/wdpass/version.py b/wdpass/version.py index eead319..b794fd4 100644 --- a/wdpass/version.py +++ b/wdpass/version.py @@ -1 +1 @@ -__version__ = '0.0.5' +__version__ = '0.1.0'