Commit Graph

40 Commits

Author SHA1 Message Date
SomberNight d33212656f crypto.py: replace sys.exit with ImportError
not nice to call sys.exit from inside the library
(run_electrum can do it, but the library probably should not)
2026-03-27 15:30:34 +00:00
SomberNight 3e4601c61d base64.b64decode: always set validate=True
Notably verifymessage and decrypt(message) were silently ignoring trailing garbage
or inserted non-base64 characters present in signatures/ciphertext.
(both the CLI commands and in the GUI)
I think it is much cleaner and preferable to treat such signatures/ciphertext as invalid.

In fact I find it surprising that base64.b64decode(validate=False) is the default.
Perhaps we should create a helper function for it that set validate=True and use that.
2025-06-03 18:58:05 +00:00
ThomasV c58c4d7451 Make lntransport not require lnutil.
This will be useful if we decide to ship lntransport as a separate
package. It is also a conceptual cleanup.

Notes:
 - lntransport still requires crypto.py
 - parsing node id from a bolt11 invoice is not supported.
2024-10-22 09:26:36 +02:00
SomberNight ffdd45ee6f crypto: (trivial) add some type-hints 2024-10-12 03:51:59 +00:00
ThomasV 3721f04ac8 replace electrum/ecc with electrum_ecc package 2024-10-10 15:46:00 +00:00
ThomasV 2f3d89f415 prepare for separation of ecc module:
- move encrypt/sign functions elsewhere
- remove local dependencies in ecc.py, ecc_fast.py (except logging)
2024-06-17 13:05:57 +02:00
SomberNight 13e2949088 rm some legacy cruft for old python versions 2024-06-05 14:55:48 +00:00
SomberNight 235e28ce20 crypto: add some notes re considerations 2024-05-22 13:39:27 +00:00
SomberNight 76e547a084 followup: call super().__init__() for WalletFileException descendants
cases missed in 57bd291491
2024-01-17 14:42:19 +00:00
SomberNight 9f1b8613d0 swaps: code style clean-up, add type hints, force kwargs
no intended functional changes
2023-11-22 17:50:29 +00:00
SomberNight 312f2641e7 don't use bare except
use "except Exception", or if really needed explicitly "except BaseException"
2023-04-24 12:58:01 +00:00
SomberNight 28fe345b0b keystore.check_password: raise better exc if called on pwless ks
If keystore.check_password is called with some pw on a keystore that does not have a password set,
it now raises better exceptions: it should now always raise InvalidPassword, and with a nicer msg.
Previously the exc type would depend on the ks type.

Examples before change:

```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/keystore.py", line 580, in check_password
    xprv = pw_decode(self.xprv, password, version=self.pw_hash_version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 270, in pw_decode_bytes
    data_bytes = bytes(base64.b64decode(data))
  File "/usr/lib/python3.10/base64.py", line 87, in b64decode
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding
```

```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
    s = aes_decrypt_with_iv(secret, iv, e)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 157, in aes_decrypt_with_iv
    data = decryptor.update(data) + decryptor.finalize()
  File "/usr/lib/python3/dist-packages/cryptography/hazmat/primitives/ciphers/base.py", line 148, in finalize
    data = self._ctx.finalize()
  File "/usr/lib/python3/dist-packages/cryptography/hazmat/backends/openssl/ciphers.py", line 193, in finalize
    raise ValueError(
ValueError: The length of the provided data is not a multiple of the block length.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/user/wspace/electrum/electrum/gui/qt/console.py", line 254, in exec_command
    result = eval(command, self.namespace, self.namespace)
  File "<string>", line 1, in <module>
  File "/home/user/wspace/electrum/electrum/keystore.py", line 248, in check_password
    self.get_private_key(pubkey, password)
  File "/home/user/wspace/electrum/electrum/keystore.py", line 267, in get_private_key
    sec = pw_decode(self.keypairs[pubkey], password, version=self.pw_hash_version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 271, in pw_decode_bytes
    return _pw_decode_raw(data_bytes, password, version=version)
  File "/home/user/wspace/electrum/electrum/crypto.py", line 255, in _pw_decode_raw
    raise InvalidPassword() from e
electrum.util.InvalidPassword: Incorrect password
```

-----

Examples after change:
```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
    return binascii.a2b_base64(s)
binascii.Error: Incorrect padding

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "...\electrum\keystore.py", line 68, in wrapper
    return check_password_fn(self, password)
  File "...\electrum\keystore.py", line 605, in check_password
    xprv = pw_decode(self.xprv, password, version=self.pw_hash_version)
  File "...\electrum\crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "...\electrum\crypto.py", line 267, in pw_decode_bytes
    raise CiphertextFormatError("ciphertext not valid base64") from e
electrum.crypto.CiphertextFormatError: ciphertext not valid base64

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "...\electrum\gui\qt\console.py", line 254, in exec_command
    result = eval(command, self.namespace, self.namespace)
  File "<string>", line 1, in <module>
  File "...\electrum\keystore.py", line 76, in wrapper
    raise InvalidPassword("password given but keystore has no password") from e
electrum.util.InvalidPassword: password given but keystore has no password
```

```
>>> wallet.keystore.check_password("asd")
Traceback (most recent call last):
    s = aes_decrypt_with_iv(secret, iv, e)
  File "...\electrum\crypto.py", line 158, in aes_decrypt_with_iv
    data = cipher.decrypt(data)
  File "...\Python310\site-packages\Cryptodome\Cipher\_mode_cbc.py", line 246, in decrypt
    raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
ValueError: Data must be padded to 16 byte boundary in CBC mode

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "...\electrum\keystore.py", line 68, in wrapper
    return check_password_fn(self, password)
  File "...\electrum\keystore.py", line 272, in check_password
    self.get_private_key(pubkey, password)
  File "...\electrum\keystore.py", line 291, in get_private_key
    sec = pw_decode(self.keypairs[pubkey], password, version=self.pw_hash_version)
  File "...\electrum\crypto.py", line 311, in pw_decode
    plaintext_bytes = pw_decode_bytes(data, password, version=version)
  File "...\electrum\crypto.py", line 268, in pw_decode_bytes
    return _pw_decode_raw(data_bytes, password, version=version)
  File "...\electrum\crypto.py", line 249, in _pw_decode_raw
    raise InvalidPassword() from e
electrum.util.InvalidPassword: Incorrect password

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "...\electrum\gui\qt\console.py", line 254, in exec_command
    result = eval(command, self.namespace, self.namespace)
  File "<string>", line 1, in <module>
  File "...\electrum\keystore.py", line 76, in wrapper
    raise InvalidPassword("password given but keystore has no password") from e
electrum.util.InvalidPassword: password given but keystore has no password
```
2022-07-12 15:50:45 +02:00
SomberNight 79fec3417a crypto.py: rm {En,De}codeAES_base64. instead use {En,De}codeAES_bytes 2022-07-12 15:50:42 +02:00
SomberNight e47e0afa91 commands: add "version_info" cmd
example:
```
$ ./run_electrum -o version_info
{
    "aiohttp.version": "3.8.1",
    "aiorpcx.version": "0.22.1",
    "certifi.version": "2021.10.08",
    "cryptodome.version": null,
    "cryptography.path": "/home/user/.local/lib/python3.8/site-packages/cryptography",
    "cryptography.version": "3.4.6",
    "dnspython.version": "2.2.0",
    "electrum.path": "/home/user/wspace/electrum/electrum",
    "electrum.version": "4.2.1",
    "hidapi.version": "0.11.0.post2",
    "libsecp256k1.path": "/home/user/wspace/electrum/electrum/libsecp256k1.so.0",
    "libusb.path": "libusb-1.0.so",
    "libusb.version": "1.0.23.11397",
    "libzbar.path": "/home/user/wspace/electrum/electrum/libzbar.so.0",
    "pyaes.version": "1.3.0",
    "pyqt.path": "/usr/lib/python3/dist-packages/PyQt5",
    "pyqt.version": "5.14.1",
    "qt.version": "5.12.8"
}
```
2022-04-11 17:40:22 +02:00
Benoit Verret f731c38293 Minor style changes 2021-03-21 00:36:23 -04:00
SomberNight 707a58abf1 crypto: add comment about ripemd.py
related: https://github.com/spesmilo/electrum/issues/7093
2021-03-10 21:28:17 +01:00
SomberNight 151a45911f follow-up prev: too much copy-paste 2021-03-10 17:31:02 +01:00
SomberNight 9740744d70 crypto: add chacha20_decrypt; unused for now 2021-03-10 17:13:42 +01:00
SomberNight 9bc4182924 crypto: check version of pycryptodomex/cryptography at runtime
As these pkgs are often provided by the OS package manager (e.g. apt),
the version limits specified in requirements*.txt and setup.py will never
get applied.
2020-10-15 16:25:06 +02:00
SomberNight 7e534f4865 dependencies: rm pyaes from requirements
Since #6014, pyaes is not really needed anymore.

As we currently require either one of pycryptodomex or cryptography,
even if pyaes is available, it will not be used.
We could strip it out completely from crypto.py...

In any case, pyaes is still pulled in by some hw wallet dependencies indirectly;
but the core library no longer depends on it.
2020-09-08 16:44:20 +02:00
SomberNight e1a2299f0c channel backup versions: trivial clean-up 2020-06-18 15:03:16 +02:00
ThomasV f9788a5d90 channel backups: add MAC 2020-06-18 15:03:16 +02:00
ThomasV 26ae6d68a3 add encryption version to channel backups 2020-06-18 15:03:16 +02:00
SomberNight 725b6f1564 crypto: chacha20-methods: make associated_data param optional 2020-06-17 17:32:51 +02:00
JeremyRand 62ca53cdf4 Fix "backed" typo in crypto.py 2020-05-03 03:08:28 +00:00
SomberNight 1ea89af012 crypto.pw_decode: fix one case of raising incorrect exception 2020-04-08 12:49:50 +02:00
SomberNight 789b78cab5 crypto: trivial clean-up of pw_encode/pw_decode functions 2020-04-08 12:38:38 +02:00
ThomasV c8f602c9d7 pw_decode, pw_encode: separate bytes functions 2020-04-03 12:29:55 +02:00
SomberNight 74a3faf803 crypto: add 'cryptography' as alt dependency for 'pycryptodomex' 2020-03-04 18:54:20 +01:00
SomberNight 18f3a37032 crypto: move LN-related chacha20/poly1305 code into crypto.py 2020-03-04 17:58:43 +01:00
ThomasV 5666188e9e update lnbase after crypto refactoring 2019-08-20 09:03:09 +02:00
ThomasV 6ba846bff0 fix hash in make_offered_htlc 2019-08-20 09:03:09 +02:00
SomberNight 8f5f0e46aa keystore: fail sooner if unsupported version
follow-up #4937
2018-12-18 19:57:58 +01:00
SomberNight 0c9a03ac54 keystore: revert KDF change from #4838
making the KDF expensive is blocked on #4909
2018-12-18 15:37:29 +01:00
ThomasV 2484c52611 Merge pull request #4838 from SomberNight/keystore_pw_hash2b
keystore: stronger pbkdf for encryption
2018-11-30 11:48:03 +01:00
SomberNight f04e5fbed6 crypto: fix pkcs7 padding check
related: ricmoo/pyaes#22

in practice, the only strings we would incorrectly accept are
(certain length of) all zero bytes
2018-11-22 18:21:19 +01:00
SomberNight 48b0de7871 keystore: stronger pbkdf for encryption 2018-11-10 16:36:41 +01:00
SomberNight aceb022f9d crypto: more type annotations 2018-11-10 13:30:34 +01:00
SomberNight 082a83dd85 rename crypto.Hash to sha256d 2018-10-25 22:28:24 +02:00
Janus 097ac144d9 file reorganization with top-level module 2018-07-13 14:01:37 +02:00