Compare commits
No commits in common. "master" and "v16.1.0" have entirely different histories.
27 changed files with 122 additions and 170 deletions
|
|
@ -201,7 +201,7 @@ Donate:
|
|||
[R]: ../../wiki/Getting-Started-with-MMGen-Wallet#a_rbf
|
||||
[B]: ../../wiki/command-help-txbump
|
||||
[69]: https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki
|
||||
[O]: ../../wiki/XOR-Seed-Splitting-^-Theory-and-Practice
|
||||
[O]: ../../wiki/XOR-Seed-Splitting:-Theory-and-Practice
|
||||
[ms]: ../../wiki/command-help-seedsplit
|
||||
[ta]: ../../wiki/Tool-API
|
||||
[L]: ../../wiki/command-help-tool
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ dRrWK1eeHDwJ7AnLSfwxBGc=
|
|||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v1
|
||||
|
||||
mQSuBFqMFuERDACE4JN6sXMel/fc2YB7F1N4h6utfdcTBHKtx97eTfq0yH1laFa/
|
||||
IpkBrDZ5GOdxTDdW3NVB4q/Wx8fR0BVUktv3cXF/d8b/B/z4OSSWbRYgNw6+C9Ol
|
||||
|
|
@ -78,28 +79,20 @@ m+8wy4zDYefUQuF8ydgNcebBRWnTU6Tb3ujVMW22WIGRK1cbo8BfnlbFvSd1ka2T
|
|||
FKjiUgGypA7aLQKDt4s0QQ6fNnTn/BGcJj0tFwoZ28CRdruCG9cbdDVMKQQOERr+
|
||||
msnL7OOAKrwpLNZ3+g20lFbp8dTQZpJEiH1bog27M6U231/OUavo/6HyAH+rs5Lk
|
||||
MMdeJ3BYd6UszbJoAUWTcHgxN3HiEe+UmU8J1Spl6xQjCICVAKg87SOjjAQwTiWc
|
||||
77Q6VGhlIE1NR2VuIFByb2plY3QgKHJlcG9zaXRvcnkgc2lnbmluZyBrZXkpIDxt
|
||||
bWdlbkB0dXRhLmlvPoiQBBMRCAA4FiEEXITLRa7iJQ8xpqVwP4sYYeMrfaIFAl2t
|
||||
5dsCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQP4sYYeMrfaL3sAD9HvMy
|
||||
95DddVooCJud2r02urQ6O63239DkEn9Uqdv3fu8A/iwOzmOg7q21yUceJY8+xqgZ
|
||||
pYtctenGqYZKtBB/y/YNtCdNTUdlbiAoRFNBIHNpZ25pbmcga2V5KSA8bW1nZW5A
|
||||
dHV0YS5pbz6IegQTEQgAIgUCWowW4QIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC
|
||||
F4AACgkQP4sYYeMrfaJU/gD/RsvuslMa7IYvlhIwlGxHHyKq9YSm4ujbT8JbrwLr
|
||||
06YA/2tzQ4BxOwttP7HjBP7d3nywG4Kf18uXWKegejlcVlIQiQIcBBABAgAGBQJa
|
||||
jBd8AAoJEGLb6eUhLwW+V+YP/iGXddKJ0mN5Y1Uqz6qO05Kbcw4Iuqor0+6TNfUH
|
||||
3x7JaCIF3ZSwe/TJYAi7iV2mkiCklj/Y3Ke1ZM1miOag1+1z+dGfPcMg7OaWb70b
|
||||
rVN+wjG8S5CfpXGz2sMvMX/xfoKFppVAjjV3gLjAUGgp3G3qaabuZiBZxj8jMgCe
|
||||
NhaAL2wHBnG69diit+TzEVTTMH99NBBSOSJ2ldfjxnKjH7aX/Qo3biNumg0BBypF
|
||||
KR2CMv37kG5ivKnc+9ygkclgDhUj0uxxheHKJRlBAg7HbvYkijphyDUtvthe/xJT
|
||||
2n2vlqfEl9buZk1QsaIpQ9H5aqkWQbiSNKHolsJ3gojDrS9IKZCJc6L720MUkcG1
|
||||
mJTB5Ir+rNrOJ4tMgO6yq/YFfhZU61M+4EW4VjNdSQRtoH3XpCUWAT0gZZ3ENGAY
|
||||
cRV7qEBLfeZEA9owYntI3gD1HXxgITN9QL9lK7eJkgvpj+G8YjdpIQ3Cx/InmKmT
|
||||
/Um+FYus/u0tVGapXMG8/y4mmNMolOf7GzSvvK/dW94ejjh886gMaIL8/kzMvaie
|
||||
LcxE+/zz/NMKOV5tOd6J3znSs8BkZjgnfbmk8T2Cu+4XkD+1s+bTUJRbBFXNoFhJ
|
||||
0U7aFpEmPJ41bmzfTkuzz6kjwpgRwFj2OyMwpJFT7s7s3oA2XTv1RL3BF/qyGNOS
|
||||
VsHouDgEahCWthIKKwYBBAGXVQEFAQEHQNYXr/lI34GouI0536OljciggBQlgs0+
|
||||
IavFkpP6zVFkAwEIB4h4BBgRCAAgFiEEXITLRa7iJQ8xpqVwP4sYYeMrfaIFAmoQ
|
||||
lrYCGwwACgkQP4sYYeMrfaJB6AEAncaaUqjyqL0acGFoKdFTS+gi8jt5KvCEHtVR
|
||||
hWKP3XsBAKT/fsAIIbXDvu1+g3/HIRlfbZaMFQs45FNtzLOVu7vy
|
||||
=7u5V
|
||||
77QnTU1HZW4gKERTQSBzaWduaW5nIGtleSkgPG1tZ2VuQHR1dGEuaW8+iHoEExEI
|
||||
ACIFAlqMFuECGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJED+LGGHjK32i
|
||||
VP4A/0bL7rJTGuyGL5YSMJRsRx8iqvWEpuLo20/CW68C69OmAP9rc0OAcTsLbT+x
|
||||
4wT+3d58sBuCn9fLl1inoHo5XFZSEIkCHAQQAQIABgUCWowXfAAKCRBi2+nlIS8F
|
||||
vlfmD/4hl3XSidJjeWNVKs+qjtOSm3MOCLqqK9PukzX1B98eyWgiBd2UsHv0yWAI
|
||||
u4ldppIgpJY/2NyntWTNZojmoNftc/nRnz3DIOzmlm+9G61TfsIxvEuQn6Vxs9rD
|
||||
LzF/8X6ChaaVQI41d4C4wFBoKdxt6mmm7mYgWcY/IzIAnjYWgC9sBwZxuvXYorfk
|
||||
8xFU0zB/fTQQUjkidpXX48Zyox+2l/0KN24jbpoNAQcqRSkdgjL9+5BuYryp3Pvc
|
||||
oJHJYA4VI9LscYXhyiUZQQIOx272JIo6Ycg1Lb7YXv8SU9p9r5anxJfW7mZNULGi
|
||||
KUPR+WqpFkG4kjSh6JbCd4KIw60vSCmQiXOi+9tDFJHBtZiUweSK/qzazieLTIDu
|
||||
sqv2BX4WVOtTPuBFuFYzXUkEbaB916QlFgE9IGWdxDRgGHEVe6hAS33mRAPaMGJ7
|
||||
SN4A9R18YCEzfUC/ZSu3iZIL6Y/hvGI3aSENwsfyJ5ipk/1JvhWLrP7tLVRmqVzB
|
||||
vP8uJpjTKJTn+xs0r7yv3VveHo44fPOoDGiC/P5MzL2oni3MRPv88/zTCjlebTne
|
||||
id850rPAZGY4J325pPE9grvuF5A/tbPm01CUWwRVzaBYSdFO2haRJjyeNW5s305L
|
||||
s8+pI8KYEcBY9jsjMKSRU+7O7N6ANl079US9wRf6shjTklbB6A==
|
||||
=x3WZ
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
|
|
|||
|
|
@ -244,9 +244,8 @@ commands. It’s that simple!
|
|||
|
||||
Monero is fully supported by MMGen Wallet.
|
||||
|
||||
Make sure that [Monerod][M] is installed and running on your online machine and
|
||||
that `monero-wallet-rpc` is installed to your executable path on both online and
|
||||
offline machines.
|
||||
Make sure that [Monerod][M] is installed and running and that
|
||||
`monero-wallet-rpc` is located in your executable path.
|
||||
|
||||
<a id="a_xmr_req">Install the Python XMR requirements:</a>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@
|
|||
|
||||
### <a id="a_xor">XOR Seed Splitting: A Theoretical Introduction</a>
|
||||
|
||||
The bitwise exclusive-or operation (usually denoted as `XOR`, “![⊕]”, or “^” in
|
||||
programming languages), has interesting properties that make it very useful in
|
||||
cryptography.
|
||||
The bitwise exclusive-or operation (usually denoted as `XOR`, or “![⊕]”)
|
||||
has interesting properties that make it very useful in cryptography.
|
||||
|
||||
Suppose we have two bytes, *a* and *b*:
|
||||
|
||||
|
|
@ -428,19 +428,12 @@ PyMODINIT_FUNC PyInit_secp256k1(void) {
|
|||
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
|
||||
struct module_state *st = GETSTATE(module);
|
||||
|
||||
st->error = PyErr_NewException("secp256k1.Error", NULL, NULL);
|
||||
|
||||
if (st->error == NULL) {
|
||||
Py_DECREF(module);
|
||||
INITERROR;
|
||||
}
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED);
|
||||
#endif
|
||||
|
||||
return module;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ altcoin.util: various altcoin-related utilities
|
|||
|
||||
from ..util import die
|
||||
|
||||
def decrypt_keystore(cfg, data, passwd, *, mac_algo=None, mac_params={}):
|
||||
def decrypt_keystore(data, passwd, *, mac_algo=None, mac_params={}):
|
||||
"""
|
||||
Decrypt the encrypted data in a cross-chain keystore
|
||||
Returns the decrypted data as a bytestring
|
||||
|
|
@ -70,8 +70,12 @@ def decrypt_keystore(cfg, data, passwd, *, mac_algo=None, mac_params={}):
|
|||
die(1, 'incorrect password')
|
||||
|
||||
# Decrypt data:
|
||||
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']))
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class CoinAmt(Decimal, Hilite, InitErrors): # abstract class
|
|||
|
||||
def __sub__(self, other, *args, **kwargs):
|
||||
if type(other) is type(self):
|
||||
return type(self)(Decimal.__sub__(Decimal(self), Decimal(other), *args, **kwargs), from_decimal=True)
|
||||
return type(self)(Decimal.__sub__(self, other, *args, **kwargs), from_decimal=True)
|
||||
raise TypeError(
|
||||
f'operand {other} is of incorrect type ({type(other).__name__} != {type(self).__name__})')
|
||||
|
||||
|
|
|
|||
|
|
@ -401,10 +401,7 @@ class Autosign:
|
|||
cfg = self.cfg,
|
||||
prompt = f'Default wallet ‘{wf}’ found.\nUse default wallet for autosigning?',
|
||||
default_yes = True):
|
||||
ss_in = Wallet(Config({
|
||||
'test_suite': self.cfg.test_suite,
|
||||
'aes_backend': self.cfg.aes_backend
|
||||
}), fn=wf)
|
||||
ss_in = Wallet(Config(), fn=wf)
|
||||
else:
|
||||
ss_in = get_mn_wallet()
|
||||
|
||||
|
|
|
|||
68
mmgen/cfg.py
68
mmgen/cfg.py
|
|
@ -228,8 +228,6 @@ class Config(Lockable):
|
|||
enable_erigon = False
|
||||
autochg_ignore_labels = False
|
||||
autosign = False
|
||||
threaded_python = not sys._is_gil_enabled()
|
||||
aes_backend = 'cryptography'
|
||||
|
||||
# regtest:
|
||||
bob = False
|
||||
|
|
@ -334,52 +332,50 @@ class Config(Lockable):
|
|||
_env_opts = (
|
||||
'MMGEN_DEBUG_ALL', # special: there is no `debug_all` attribute
|
||||
|
||||
'MMGEN_AES_BACKEND',
|
||||
'MMGEN_BLACKLIST_DAEMONS',
|
||||
'MMGEN_BOGUS_SEND',
|
||||
'MMGEN_BOGUS_UNSPENT_DATA',
|
||||
'MMGEN_COLUMNS',
|
||||
'MMGEN_DAEMON_STATE_TIMEOUT',
|
||||
'MMGEN_DEBUG',
|
||||
'MMGEN_DEBUG_ADDRLIST',
|
||||
'MMGEN_DEBUG_DAEMON',
|
||||
'MMGEN_DEBUG_EVM',
|
||||
'MMGEN_DEBUG_OPTS',
|
||||
'MMGEN_DEBUG_RPC',
|
||||
'MMGEN_DEBUG_SUBSEED',
|
||||
'MMGEN_DEBUG_TW',
|
||||
'MMGEN_DEBUG_UTF8',
|
||||
'MMGEN_DEVTOOLS',
|
||||
'MMGEN_DISABLE_COLOR',
|
||||
'MMGEN_ENABLE_ERIGON',
|
||||
'MMGEN_EXEC_WRAPPER',
|
||||
'MMGEN_FORCE_256_COLOR',
|
||||
'MMGEN_HOLD_PROTECT_DISABLE',
|
||||
'MMGEN_HTTP_TIMEOUT',
|
||||
'MMGEN_IGNORE_DAEMON_VERSION',
|
||||
'MMGEN_IGNORE_TEST_PY_EXCEPTION',
|
||||
'MMGEN_NO_LICENSE',
|
||||
'MMGEN_QUIET',
|
||||
'MMGEN_REGTEST',
|
||||
'MMGEN_RPC_BACKEND',
|
||||
'MMGEN_RPC_FAIL_ON_COMMAND',
|
||||
'MMGEN_RPC_HOST',
|
||||
'MMGEN_TESTNET',
|
||||
'MMGEN_TEST_SUITE',
|
||||
'MMGEN_TEST_SUITE_AUTOSIGN_LED_SIMULATE',
|
||||
'MMGEN_TEST_SUITE_AUTOSIGN_THREADED',
|
||||
'MMGEN_TEST_SUITE_DEVNET_BLOCK_PERIOD',
|
||||
'MMGEN_TEST_SUITE_XMR_AUTOSIGN',
|
||||
'MMGEN_TEST_SUITE_CFGTEST',
|
||||
'MMGEN_TEST_SUITE_DETERMINISTIC',
|
||||
'MMGEN_TEST_SUITE_DEVNET_BLOCK_PERIOD',
|
||||
'MMGEN_TEST_SUITE_ENABLE_COLOR',
|
||||
'MMGEN_TEST_SUITE_PEXPECT',
|
||||
'MMGEN_TEST_SUITE_PEXPECT_TIMEOUT',
|
||||
'MMGEN_TEST_SUITE_POPEN_SPAWN',
|
||||
'MMGEN_TEST_SUITE_ROOT_PFX',
|
||||
'MMGEN_TEST_SUITE_XMR_AUTOSIGN',
|
||||
'MMGEN_THREADED_PYTHON',
|
||||
'MMGEN_TRACEBACK',
|
||||
'MMGEN_USE_STANDALONE_SCRYPT_MODULE')
|
||||
'MMGEN_BLACKLIST_DAEMONS',
|
||||
'MMGEN_BOGUS_SEND',
|
||||
'MMGEN_BOGUS_UNSPENT_DATA',
|
||||
'MMGEN_DAEMON_STATE_TIMEOUT',
|
||||
'MMGEN_DEBUG',
|
||||
'MMGEN_DEBUG_DAEMON',
|
||||
'MMGEN_DEBUG_EVM',
|
||||
'MMGEN_DEBUG_OPTS',
|
||||
'MMGEN_DEBUG_RPC',
|
||||
'MMGEN_DEBUG_ADDRLIST',
|
||||
'MMGEN_DEBUG_TW',
|
||||
'MMGEN_DEBUG_UTF8',
|
||||
'MMGEN_DEBUG_SUBSEED',
|
||||
'MMGEN_DEVTOOLS',
|
||||
'MMGEN_FORCE_256_COLOR',
|
||||
'MMGEN_HOLD_PROTECT_DISABLE',
|
||||
'MMGEN_HTTP_TIMEOUT',
|
||||
'MMGEN_QUIET',
|
||||
'MMGEN_NO_LICENSE',
|
||||
'MMGEN_RPC_HOST',
|
||||
'MMGEN_RPC_FAIL_ON_COMMAND',
|
||||
'MMGEN_TESTNET',
|
||||
'MMGEN_REGTEST',
|
||||
'MMGEN_EXEC_WRAPPER',
|
||||
'MMGEN_IGNORE_TEST_PY_EXCEPTION',
|
||||
'MMGEN_RPC_BACKEND',
|
||||
'MMGEN_IGNORE_DAEMON_VERSION',
|
||||
'MMGEN_USE_STANDALONE_SCRYPT_MODULE',
|
||||
'MMGEN_ENABLE_ERIGON',
|
||||
'MMGEN_DISABLE_COLOR')
|
||||
|
||||
_infile_opts = (
|
||||
'keys_from_file',
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class Crypto:
|
|||
mmenc_ext = 'mmenc'
|
||||
scramble_hash_rounds = 10
|
||||
|
||||
salt_len = 16
|
||||
aesctr_iv_len = 16
|
||||
aesctr_dfl_iv = int.to_bytes(1, aesctr_iv_len, 'big')
|
||||
hincog_chk_len = 8
|
||||
|
|
@ -67,29 +68,6 @@ class Crypto:
|
|||
def __init__(self, cfg):
|
||||
self.cfg = cfg
|
||||
self.util = cfg._util
|
||||
if cfg.test_suite and self.cfg.aes_backend == 'pyaes':
|
||||
self.get_aes_ctr = self.get_aes_ctr_pyaes
|
||||
self.encrypt_aes_ctr = self.encrypt_aes_ctr_pyaes
|
||||
|
||||
@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()
|
||||
|
||||
@staticmethod
|
||||
def get_aes_ctr_pyaes(key, iv):
|
||||
import pyaes
|
||||
class MyAES(pyaes.AESModeOfOperationCTR):
|
||||
update = pyaes.AESModeOfOperationCTR.encrypt
|
||||
return MyAES(key, pyaes.Counter(int.from_bytes(iv)))
|
||||
|
||||
def encrypt_aes_ctr_pyaes(self, key, iv, data):
|
||||
return self.get_aes_ctr_pyaes(key, iv).encrypt(data)
|
||||
|
||||
def get_hash_params(self, hash_preset):
|
||||
if hash_preset in self.hash_presets:
|
||||
|
|
@ -149,14 +127,20 @@ 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}')
|
||||
|
||||
enc_data = self.encrypt_aes_ctr(key, iv, data)
|
||||
c = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend())
|
||||
encryptor = c.encryptor()
|
||||
enc_data = encryptor.update(data) + encryptor.finalize()
|
||||
|
||||
if verify:
|
||||
self.util.vmsg_r(f'Performing a test decryption of the {desc}...')
|
||||
if self.encrypt_aes_ctr(key, iv, enc_data) != data:
|
||||
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:
|
||||
die(2, f'ERROR.\nDecrypted {desc} doesn’t match original {desc}')
|
||||
if not silent:
|
||||
self.util.vmsg('done')
|
||||
|
|
@ -171,9 +155,12 @@ 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...')
|
||||
|
||||
return self.encrypt_aes_ctr(key, iv, enc_data)
|
||||
c = Cipher(algorithms.AES(key), modes.CTR(iv), backend=default_backend())
|
||||
encryptor = c.encryptor()
|
||||
return encryptor.update(enc_data) + encryptor.finalize()
|
||||
|
||||
def scrypt_hash_passphrase(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
16.2.dev1
|
||||
16.1.0
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ 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())
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class tool_cmd(tool_cmd_base):
|
|||
os.close(f)
|
||||
return True
|
||||
|
||||
def rand2file(self, outfile: str, nbytes: str, *, silent=False):
|
||||
def rand2file(self, outfile: str, nbytes: str, *, threads=4, silent=False):
|
||||
"""
|
||||
write ‘nbytes’ bytes of random data to specified file (dd-style byte specifiers supported)
|
||||
|
||||
|
|
@ -94,12 +94,15 @@ 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():
|
||||
encryptor = Crypto(self.cfg).get_aes_ctr(key, os.urandom(Crypto.aesctr_iv_len))
|
||||
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()
|
||||
while True:
|
||||
q2.put(encryptor.update(q1.get()))
|
||||
q1.task_done()
|
||||
|
|
@ -118,12 +121,7 @@ class tool_cmd(tool_cmd_base):
|
|||
key = Crypto(self.cfg).get_random(32)
|
||||
q1, q2 = (Queue(), Queue())
|
||||
|
||||
try:
|
||||
threads = os.process_cpu_count() # Python 3.13
|
||||
except AttributeError:
|
||||
threads = os.cpu_count()
|
||||
|
||||
for i in range(max(1, threads - 1)):
|
||||
for i in range(max(1, threads-2)):
|
||||
t = Thread(target=encrypt_worker)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
|
@ -163,7 +161,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(self.cfg, data[0]['keystore'], passwd)
|
||||
ret = decrypt_keystore(data[0]['keystore'], passwd)
|
||||
return ret.hex() if output_hex else ret
|
||||
|
||||
def decrypt_geth_keystore(self, wallet_file: str, *, check_addr=True):
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class wallet(wallet):
|
|||
d.passwd = self._get_new_passphrase()
|
||||
|
||||
from hashlib import sha256
|
||||
d.salt = sha256(self.crypto.get_random(128)).digest()[:self.salt_len]
|
||||
d.salt = sha256(self.crypto.get_random(128)).digest()[:self.crypto.salt_len]
|
||||
key = self.crypto.make_key(d.passwd, d.salt, d.hash_preset)
|
||||
d.key_id = make_chksum_8(key)
|
||||
d.enc_seed = self.crypto.encrypt_seed(self.seed.data, key)
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ from .enc import wallet
|
|||
|
||||
class wallet(wallet):
|
||||
|
||||
salt_len = 16
|
||||
|
||||
_msg = {
|
||||
'check_incog_id': """
|
||||
Check the generated Incog ID above against your records. If it doesn't
|
||||
|
|
@ -38,7 +36,7 @@ class wallet(wallet):
|
|||
def _get_incog_data_len(self, seed_len):
|
||||
return (
|
||||
self.crypto.aesctr_iv_len
|
||||
+ self.salt_len
|
||||
+ self.crypto.salt_len
|
||||
+ (0 if self.cfg.old_incog_fmt else self.crypto.hincog_chk_len)
|
||||
+ seed_len//8)
|
||||
|
||||
|
|
@ -73,7 +71,7 @@ class wallet(wallet):
|
|||
self.cfg._util.qmsg('Make a record of this value')
|
||||
self.cfg._util.vmsg('\n ' + self.msg['record_incog_id'].strip()+'\n')
|
||||
|
||||
d.salt = crypto.get_random(self.salt_len)
|
||||
d.salt = crypto.get_random(crypto.salt_len)
|
||||
seed_key = crypto.make_key(
|
||||
passwd = d.passwd,
|
||||
salt = d.salt,
|
||||
|
|
@ -169,8 +167,8 @@ class wallet(wallet):
|
|||
iv = d.iv,
|
||||
desc = 'incog data')
|
||||
|
||||
d.salt = dd[0:self.salt_len]
|
||||
d.enc_seed = dd[self.salt_len:]
|
||||
d.salt = dd[0:crypto.salt_len]
|
||||
d.enc_seed = dd[crypto.salt_len:]
|
||||
|
||||
seed_key = crypto.make_key(
|
||||
passwd = d.passwd,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ from .enc import wallet
|
|||
class wallet(wallet):
|
||||
|
||||
desc = 'MMGen wallet'
|
||||
salt_len = 32
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if self.cfg.label:
|
||||
|
|
|
|||
|
|
@ -54,6 +54,5 @@ rec {
|
|||
# pydantic = pydantic; # eth-keys
|
||||
# pure-protobuf = pure-protobuf; # THORChain
|
||||
# bip-utils = bip-utils; # bip_hd
|
||||
# pyaes = pyaes; # developer testing
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,8 +122,6 @@ opts_data = {
|
|||
-x, --debug-pexpect Produce debugging output for pexpect calls
|
||||
--, --demo Add extra delay after each send to make input visible.
|
||||
Implies --exact-output --pexpect-spawn --buf-keypress
|
||||
--, --dev-mode Run spawned scripts in Python Development Mode
|
||||
(PYTHONDEVMODE=1 PYTHONTRACEMALLOC=10)
|
||||
-d, --deps-only Run a command or command subgroup’s dependencies without
|
||||
running the command or command group itself.
|
||||
-D, --no-daemon-stop Don't stop auto-started daemons after running tests
|
||||
|
|
|
|||
|
|
@ -95,21 +95,21 @@ class CmdTestBase:
|
|||
except:
|
||||
msg(f'{fn}: file does not exist or could not be deleted')
|
||||
|
||||
def skip_on_condition(self, condition, message, extra_msg):
|
||||
if condition:
|
||||
msg(gray('Skipping test {!r} {}{}'.format(
|
||||
def skip_for_platform(self, name, extra_msg=None):
|
||||
if gc.platform == name:
|
||||
msg(gray('Skipping test {!r} for {} platform{}'.format(
|
||||
self.test_name,
|
||||
message,
|
||||
name,
|
||||
f' ({extra_msg})' if extra_msg else "")))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def skip_for_mac(self, extra_msg=None):
|
||||
return self.skip_on_condition(gc.platform=='darwin', 'for macOS platform', extra_msg)
|
||||
return self.skip_for_platform('darwin', extra_msg)
|
||||
|
||||
def skip_for_win(self, extra_msg=None):
|
||||
return self.skip_on_condition(gc.platform=='win32', 'for win32 platform', extra_msg)
|
||||
return self.skip_for_platform('win32', extra_msg)
|
||||
|
||||
def spawn_chk(self, *args, **kwargs):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -67,8 +67,7 @@ class CmdTestPexpect:
|
|||
timeout = int(
|
||||
timeout
|
||||
or cfg.pexpect_timeout
|
||||
or cfg.test_suite_pexpect_timeout) or (
|
||||
5 if cfg.debug_pexpect else 180 if cfg.dev_mode else 60)
|
||||
or cfg.test_suite_pexpect_timeout) or (60, 5)[bool(cfg.debug_pexpect)]
|
||||
if pexpect_spawn:
|
||||
self.p = pexpect.spawn(args[0], args[1:], encoding='utf8', timeout=timeout, env=spawn_env)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -105,19 +105,14 @@ class CmdTestRunner:
|
|||
def set_spawn_env(self):
|
||||
|
||||
self.spawn_env = dict(os.environ)
|
||||
|
||||
self.spawn_env.update({
|
||||
'MMGEN_NO_LICENSE': '1',
|
||||
'MMGEN_BOGUS_SEND': '1',
|
||||
'MMGEN_TEST_SUITE_PEXPECT': '1',
|
||||
'EXEC_WRAPPER_DO_RUNTIME_MSG':'1',
|
||||
# if cmdtest.py itself is running under exec_wrapper, disable writing of traceback file for spawned script
|
||||
'EXEC_WRAPPER_TRACEBACK': '' if os.getenv('MMGEN_EXEC_WRAPPER') else '1'})
|
||||
|
||||
if self.cfg.dev_mode:
|
||||
self.spawn_env.update({
|
||||
'PYTHONDEVMODE': '1',
|
||||
'PYTHONTRACEMALLOC': '10'})
|
||||
'EXEC_WRAPPER_TRACEBACK': '' if os.getenv('MMGEN_EXEC_WRAPPER') else '1',
|
||||
})
|
||||
|
||||
if self.cfg.exact_output:
|
||||
from mmgen.term import get_terminal_size
|
||||
|
|
|
|||
|
|
@ -106,15 +106,6 @@ class CmdTestInput(CmdTestBase):
|
|||
)
|
||||
}
|
||||
|
||||
def skip_no_readline_insert(self, extra_msg=None):
|
||||
return self.skip_on_condition(
|
||||
gc.platform == 'darwin' or self.cfg.threaded_python,
|
||||
' (no readline insert support)',
|
||||
extra_msg)
|
||||
|
||||
def skip_no_readline_edit(self, extra_msg=None):
|
||||
return self.skip_on_condition(self.cfg.threaded_python, ' (no readline edit support)', extra_msg)
|
||||
|
||||
def get_seed_from_stdin(self):
|
||||
self.spawn(msg_only=True)
|
||||
from subprocess import run, PIPE
|
||||
|
|
@ -345,7 +336,7 @@ class CmdTestInput(CmdTestBase):
|
|||
False)
|
||||
|
||||
def line_input_insert_term1(self):
|
||||
if self.skip_no_readline_insert():
|
||||
if self.skip_for_mac('readline text buffer issues'):
|
||||
return 'skip'
|
||||
return self._line_input(
|
||||
['prompt> ', True, 'foo', True],
|
||||
|
|
@ -355,7 +346,7 @@ class CmdTestInput(CmdTestBase):
|
|||
hold_protect_delay)
|
||||
|
||||
def line_input_insert_term2(self):
|
||||
if self.skip_no_readline_insert():
|
||||
if self.skip_for_mac('readline text buffer issues'):
|
||||
return 'skip'
|
||||
return self._line_input(
|
||||
['prompt> ', True, 'foo', False],
|
||||
|
|
@ -364,8 +355,6 @@ class CmdTestInput(CmdTestBase):
|
|||
True)
|
||||
|
||||
def line_input_edit_term(self):
|
||||
if self.skip_no_readline_edit():
|
||||
return 'skip'
|
||||
return self._line_input(
|
||||
['prompt> ', True, '', True],
|
||||
'\b\bφυφυ\b\bβαρ',
|
||||
|
|
@ -374,7 +363,7 @@ class CmdTestInput(CmdTestBase):
|
|||
hold_protect_delay)
|
||||
|
||||
def line_input_edit_term_insert(self):
|
||||
if self.skip_no_readline_edit() or self.skip_no_readline_insert():
|
||||
if self.skip_for_mac('readline text buffer issues'):
|
||||
return 'skip'
|
||||
return self._line_input(
|
||||
['prompt> ', True, 'φυφυ', True],
|
||||
|
|
@ -384,7 +373,7 @@ class CmdTestInput(CmdTestBase):
|
|||
hold_protect_delay)
|
||||
|
||||
def line_input_erase_term(self):
|
||||
if self.skip_no_readline_insert():
|
||||
if self.skip_for_mac('readline text buffer issues'):
|
||||
return 'skip'
|
||||
return self._line_input(
|
||||
['prompt> ', True, 'foobarbaz', True],
|
||||
|
|
|
|||
|
|
@ -53,12 +53,13 @@ class CmdTestWalletConv(CmdTestBase, CmdTestShared):
|
|||
'hic_wallet_old': '1378FC64-B55E9958-D85FF20C[192,1].incog-old.offset123',
|
||||
},
|
||||
'256': {
|
||||
'ref_wallet': '98831F3A-F825E2A0[256,1].mmdat',
|
||||
'ref_wallet': '98831F3A-27F2BF93[256,1].mmdat',
|
||||
'ic_wallet': '98831F3A-5482381C-18460FB1[256,1].mmincog',
|
||||
'ic_wallet_hex': '98831F3A-1630A9F2-870376A9[256,1].mmincox',
|
||||
|
||||
'hic_wallet': '98831F3A-F59B07A0-559CEF19[256,1].incog.offset123',
|
||||
'hic_wallet_old': '98831F3A-F59B07A0-848535F3[256,1].incog-old.offset123',
|
||||
|
||||
},
|
||||
}
|
||||
cmd_group = (
|
||||
|
|
|
|||
|
|
@ -74,9 +74,12 @@ class unit_tests:
|
|||
msg('Is the ‘pysocks’ package installed?')
|
||||
return False
|
||||
|
||||
def aes(self, name, ut):
|
||||
from mmgen.crypto import Crypto
|
||||
Crypto(cfg).encrypt_aes_ctr(b'deadbeef' * 4, b'deadbeef' * 2, b'foo')
|
||||
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()
|
||||
return True
|
||||
|
||||
def ecdsa(self, name, ut):
|
||||
|
|
|
|||
6
test/ref/98831F3A-27F2BF93[256,1].mmdat
Normal file
6
test/ref/98831F3A-27F2BF93[256,1].mmdat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
cd828f
|
||||
"#$%&()*+,- ./0123456789:;<=>?@AIZ[\]^_`aiz{|}~'
|
||||
98831f3a 27f2bf93 256 NE 20150405_075000
|
||||
1: 12 8 1
|
||||
9440eb NBDH bKqG a23q FtYi nRo1 kk
|
||||
7a2f32 5nZf LqjP R9bj vgzc sMGr WPtu PR7S 6NpZ pgGd fc4e QCKt
|
||||
6
test/ref/98831F3A-E2687906[256,1].mmdat
Normal file
6
test/ref/98831F3A-E2687906[256,1].mmdat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
9cc19b
|
||||
test.py ref. wallet (pw 'abc', seed len 256)
|
||||
98831f3a e2687906 256 NE 20161110_135346
|
||||
1: 12 8 1
|
||||
70413d 74ev zjeq Zw2g DspF RKpE 7H
|
||||
7c26e6 1otd mVTn 5MCR cDTF sZqY uNKA rsAm mjTw EJmS yzwX ZPJd
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
42f7d8
|
||||
"#$%&()*+,- ./0123456789:;<=>?@AIZ[\]^_`aiz{|}~'
|
||||
98831f3a f825e2a0 256 NE 20260520_074802
|
||||
1: 12 8 1
|
||||
384094 8MgZ HHVn QTmH RbiQ hufm obJw 9FkX 7Uv5 AbtK k4yU hqba
|
||||
2a4856 8kQ7 JVwg zDQq isws f4g1 7oWi pKS7 gcvq siCX VX3i BeP7
|
||||
Loading…
Add table
Add a link
Reference in a new issue