From 3d8e98f31ed71c10fbf87488b4b85dfdae83e6b5 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Thu, 21 May 2026 12:09:33 +0000 Subject: [PATCH] crypto.Crypto: new `encrypt_aes_ctr()` method --- mmgen/altcoin/util.py | 16 ++++++---------- mmgen/crypto.py | 29 +++++++++++++++-------------- mmgen/proto/eth/util.py | 1 + mmgen/tool/fileutil.py | 9 +++------ test/modtest_d/dep.py | 7 ++----- 5 files changed, 27 insertions(+), 35 deletions(-) diff --git a/mmgen/altcoin/util.py b/mmgen/altcoin/util.py index 89dd185a..d2811be2 100755 --- a/mmgen/altcoin/util.py +++ b/mmgen/altcoin/util.py @@ -14,7 +14,7 @@ altcoin.util: various altcoin-related utilities from ..util import die -def decrypt_keystore(data, passwd, *, mac_algo=None, mac_params={}): +def decrypt_keystore(cfg, data, passwd, *, mac_algo=None, mac_params={}): """ Decrypt the encrypted data in a cross-chain keystore Returns the decrypted data as a bytestring @@ -70,12 +70,8 @@ def decrypt_keystore(data, passwd, *, mac_algo=None, mac_params={}): die(1, 'incorrect password') # Decrypt data: - from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes - from cryptography.hazmat.backends import default_backend - cipher_len = int(cipher.split('-')[1]) // 8 - c = Cipher( - algorithms.AES(hashed_pw[:cipher_len]), - modes.CTR(bytes.fromhex(cdata['cipherparams']['iv'])), - backend = default_backend()) - encryptor = c.encryptor() - return encryptor.update(bytes.fromhex(cdata['ciphertext'])) + encryptor.finalize() + from ..crypto import Crypto + return Crypto(cfg).encrypt_aes_ctr( + hashed_pw[:int(cipher.split('-')[1]) // 8], + bytes.fromhex(cdata['cipherparams']['iv']), + bytes.fromhex(cdata['ciphertext'])) diff --git a/mmgen/crypto.py b/mmgen/crypto.py index 5c7e5630..4caa45cd 100755 --- a/mmgen/crypto.py +++ b/mmgen/crypto.py @@ -68,6 +68,16 @@ class Crypto: self.cfg = cfg self.util = cfg._util + @staticmethod + def get_aes_ctr(key, iv): + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + from cryptography.hazmat.backends import default_backend + return Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend()).encryptor() + + def encrypt_aes_ctr(self, key, iv, data): + encryptor = self.get_aes_ctr(key, iv) + return encryptor.update(data) + encryptor.finalize() + def get_hash_params(self, hash_preset): if hash_preset in self.hash_presets: return self.hash_presets[hash_preset] # N, r, p @@ -126,20 +136,14 @@ class Crypto: verify = True, silent = False): - from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes - from cryptography.hazmat.backends import default_backend if not silent: self.util.vmsg(f'Encrypting {desc}') - c = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend()) - encryptor = c.encryptor() - enc_data = encryptor.update(data) + encryptor.finalize() + + enc_data = self.encrypt_aes_ctr(key, iv, data) if verify: self.util.vmsg_r(f'Performing a test decryption of the {desc}...') - c = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend()) - encryptor = c.encryptor() - dec_data = encryptor.update(enc_data) + encryptor.finalize() - if dec_data != data: + if self.encrypt_aes_ctr(key, iv, enc_data) != data: die(2, f'ERROR.\nDecrypted {desc} doesn’t match original {desc}') if not silent: self.util.vmsg('done') @@ -154,12 +158,9 @@ class Crypto: iv = aesctr_dfl_iv, desc = 'data'): - from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes - from cryptography.hazmat.backends import default_backend self.util.vmsg_r(f'Decrypting {desc} with key...') - c = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend()) - encryptor = c.encryptor() - return encryptor.update(enc_data) + encryptor.finalize() + + return self.encrypt_aes_ctr(key, iv, enc_data) def scrypt_hash_passphrase( self, diff --git a/mmgen/proto/eth/util.py b/mmgen/proto/eth/util.py index e5edec09..3a59928e 100755 --- a/mmgen/proto/eth/util.py +++ b/mmgen/proto/eth/util.py @@ -27,6 +27,7 @@ def decrypt_geth_keystore(cfg, wallet_fn, passwd, *, check_addr=True): from ...altcoin.util import decrypt_keystore key = decrypt_keystore( + cfg, wallet_data, passwd, mac_algo = get_keccak()) diff --git a/mmgen/tool/fileutil.py b/mmgen/tool/fileutil.py index 6330af93..b6fe0283 100755 --- a/mmgen/tool/fileutil.py +++ b/mmgen/tool/fileutil.py @@ -94,15 +94,12 @@ class tool_cmd(tool_cmd_base): """ from threading import Thread from queue import Queue - from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes - from cryptography.hazmat.backends import default_backend from ..util2 import parse_bytespec + from ..crypto import Crypto def encrypt_worker(): - ctr_init_val = os.urandom(Crypto.aesctr_iv_len) - c = Cipher(algorithms.AES(key), modes.CTR(ctr_init_val), backend=default_backend()) - encryptor = c.encryptor() + encryptor = Crypto(self.cfg).get_aes_ctr(key, os.urandom(Crypto.aesctr_iv_len)) while True: q2.put(encryptor.update(q1.get())) q1.task_done() @@ -161,7 +158,7 @@ class tool_cmd(tool_cmd_base): with open(wallet_file) as fh: data = json.loads(fh.read()) from ..altcoin.util import decrypt_keystore - ret = decrypt_keystore(data[0]['keystore'], passwd) + ret = decrypt_keystore(self.cfg, data[0]['keystore'], passwd) return ret.hex() if output_hex else ret def decrypt_geth_keystore(self, wallet_file: str, *, check_addr=True): diff --git a/test/modtest_d/dep.py b/test/modtest_d/dep.py index 411b198a..29afda48 100755 --- a/test/modtest_d/dep.py +++ b/test/modtest_d/dep.py @@ -75,11 +75,8 @@ class unit_tests: return False def cryptography(self, name, ut): - from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes - from cryptography.hazmat.backends import default_backend - c = Cipher(algorithms.AES(b'deadbeef'*4), modes.CTR(b'deadbeef'*2), backend=default_backend()) - encryptor = c.encryptor() - encryptor.update(b'foo') + encryptor.finalize() + from mmgen.crypto import Crypto + Crypto(cfg).encrypt_aes_ctr(b'deadbeef' * 4, b'deadbeef' * 2, b'foo') return True def ecdsa(self, name, ut):