enc.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2024 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. wallet.enc: encrypted wallet base class
  12. """
  13. from ..cfg import gc
  14. from ..util import msg,make_chksum_8,die
  15. from .base import wallet
  16. class wallet(wallet):
  17. def __init__(self,*args,**kwargs):
  18. from ..crypto import Crypto
  19. self.crypto = Crypto(self.cfg)
  20. super().__init__(*args,**kwargs)
  21. def _decrypt_retry(self):
  22. while True:
  23. if self._decrypt():
  24. break
  25. if self.passwd_file:
  26. die(2,'Passphrase from password file, so exiting')
  27. msg('Trying again...')
  28. def _get_hash_preset_from_user(self,old_preset,add_desc=''):
  29. prompt = 'Enter {}hash preset for {}{}{},\nor hit ENTER to {} value ({!r}): '.format(
  30. ('old ' if self.op=='pwchg_old' else 'new ' if self.op=='pwchg_new' else ''),
  31. ('','new ')[self.op=='new'],
  32. self.desc,
  33. ('',' '+add_desc)[bool(add_desc)],
  34. ('accept the default','reuse the old')[self.op=='pwchg_new'],
  35. old_preset )
  36. return self.crypto.get_hash_preset_from_user( old_preset=old_preset, prompt=prompt )
  37. def _get_hash_preset(self,add_desc=''):
  38. if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'):
  39. old_hp = self.ss_in.ssdata.hash_preset
  40. if self.cfg.keep_hash_preset:
  41. hp = old_hp
  42. self.cfg._util.qmsg(f'Reusing hash preset {hp!r} at user request')
  43. elif self.cfg.hash_preset:
  44. hp = self.cfg.hash_preset
  45. self.cfg._util.qmsg(f'Using user-configured hash preset {hp!r}')
  46. else: # Prompt, using old value as default
  47. hp = self._get_hash_preset_from_user( old_preset=old_hp, add_desc=add_desc )
  48. if (not self.cfg.keep_hash_preset) and self.op == 'pwchg_new':
  49. self.cfg._util.qmsg('Hash preset {}'.format(
  50. 'unchanged' if hp == old_hp else f'changed to {hp!r}'))
  51. elif self.cfg.hash_preset:
  52. hp = self.cfg.hash_preset
  53. self.cfg._util.qmsg(f'Using user-configured hash preset {hp!r}')
  54. else:
  55. hp = self._get_hash_preset_from_user(
  56. old_preset = gc.dfl_hash_preset,
  57. add_desc = add_desc )
  58. self.ssdata.hash_preset = hp
  59. def _get_new_passphrase(self):
  60. return self.crypto.get_new_passphrase(
  61. data_desc = ('new ' if self.op in ('new','conv') else '') + self.desc,
  62. hash_preset = self.ssdata.hash_preset,
  63. passwd_file = self.passwd_file,
  64. pw_desc = ('new ' if self.op=='pwchg_new' else '') + 'passphrase' )
  65. def _get_passphrase(self,add_desc=''):
  66. return self.crypto.get_passphrase(
  67. data_desc = self.desc + (f' {add_desc}' if add_desc else ''),
  68. passwd_file = self.passwd_file,
  69. pw_desc = ('old ' if self.op == 'pwchg_old' else '') + 'passphrase' )
  70. def _get_first_pw_and_hp_and_encrypt_seed(self):
  71. d = self.ssdata
  72. self._get_hash_preset()
  73. if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'passwd'):
  74. old_pw = self.ss_in.ssdata.passwd
  75. if self.cfg.keep_passphrase:
  76. d.passwd = old_pw
  77. self.cfg._util.qmsg('Reusing passphrase at user request')
  78. else:
  79. d.passwd = self._get_new_passphrase()
  80. if self.op == 'pwchg_new':
  81. self.cfg._util.qmsg('Passphrase {}'.format( 'unchanged' if d.passwd == old_pw else 'changed' ))
  82. else:
  83. d.passwd = self._get_new_passphrase()
  84. from hashlib import sha256
  85. d.salt = sha256( self.crypto.get_random(128) ).digest()[:self.crypto.salt_len]
  86. key = self.crypto.make_key( d.passwd, d.salt, d.hash_preset )
  87. d.key_id = make_chksum_8(key)
  88. d.enc_seed = self.crypto.encrypt_seed( self.seed.data, key )