Merge branch 'torba-encryption'
This commit is contained in:
commit
202a957a1a
3 changed files with 67 additions and 63 deletions
|
@ -175,7 +175,7 @@ class DHTHasContacts(RequiredCondition):
|
||||||
return len(component.contacts) > 0
|
return len(component.contacts) > 0
|
||||||
|
|
||||||
|
|
||||||
class WalletIsLocked(RequiredCondition):
|
class WalletIsUnlocked(RequiredCondition):
|
||||||
name = WALLET_IS_UNLOCKED
|
name = WALLET_IS_UNLOCKED
|
||||||
component = WALLET_COMPONENT
|
component = WALLET_COMPONENT
|
||||||
message = "your wallet is locked"
|
message = "your wallet is locked"
|
||||||
|
@ -1361,64 +1361,77 @@ class Daemon(AuthJSONRPCServer):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT)
|
@requires(WALLET_COMPONENT)
|
||||||
@defer.inlineCallbacks
|
def jsonrpc_account_unlock(self, password, account_id=None):
|
||||||
def jsonrpc_account_unlock(self, password):
|
|
||||||
"""
|
"""
|
||||||
Unlock an encrypted account
|
Unlock an encrypted account
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
account_unlock (<password> | --password=<password>)
|
account_unlock (<password> | --password=<password>) [<account_id> | --account_id=<account_id>]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--password=<password> : (str) password for unlocking wallet
|
--account_id=<account_id> : (str) id for the account to unlock
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if account is unlocked, otherwise false
|
(bool) true if account is unlocked, otherwise false
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# the check_locked() in the if statement is needed because that is what sets
|
return self.wallet_manager.unlock_account(
|
||||||
# the wallet_unlocked_d deferred ¯\_(ツ)_/¯
|
password, self.get_account_or_default(account_id, lbc_only=False)
|
||||||
if not self.wallet_manager.check_locked():
|
)
|
||||||
d = self.wallet_manager.wallet_unlocked_d
|
|
||||||
d.callback(password)
|
@requires(WALLET_COMPONENT)
|
||||||
result = yield d
|
def jsonrpc_account_lock(self, account_id=None):
|
||||||
else:
|
"""
|
||||||
result = True
|
Lock an unlocked account
|
||||||
response = yield self._render_response(result)
|
|
||||||
defer.returnValue(response)
|
Usage:
|
||||||
|
account_lock [<account_id> | --account_id=<account_id>]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--account_id=<account_id> : (str) id for the account to lock
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(bool) true if account is locked, otherwise false
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.wallet_manager.lock_account(self.get_account_or_default(account_id, lbc_only=False))
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
def jsonrpc_account_decrypt(self):
|
def jsonrpc_account_decrypt(self, account_id=None):
|
||||||
"""
|
"""
|
||||||
Decrypt an encrypted account, this will remove the wallet password
|
Decrypt an encrypted account, this will remove the wallet password
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
account_decrypt
|
account_decrypt [<account_id> | --account_id=<account_id>]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
None
|
--account_id=<account_id> : (str) id for the account to decrypt
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if wallet is decrypted, otherwise false
|
(bool) true if wallet is decrypted, otherwise false
|
||||||
"""
|
"""
|
||||||
return self.wallet_manager.decrypt_wallet()
|
|
||||||
|
return self.wallet_manager.decrypt_account(self.get_account_or_default(account_id, lbc_only=False))
|
||||||
|
|
||||||
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
@requires(WALLET_COMPONENT, conditions=[WALLET_IS_UNLOCKED])
|
||||||
def jsonrpc_account_encrypt(self, new_password):
|
def jsonrpc_account_encrypt(self, new_password, account_id=None):
|
||||||
"""
|
"""
|
||||||
Encrypt a wallet with a password, if the wallet is already encrypted this will update
|
Encrypt an unencrypted account with a password
|
||||||
the password
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
wallet_encrypt (<new_password> | --new_password=<new_password>)
|
wallet_encrypt (<new_password> | --new_password=<new_password>) [<account_id> | --account_id=<account_id>]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--new_password=<new_password> : (str) password string to be used for encrypting wallet
|
--account_id=<account_id> : (str) id for the account to encrypt
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(bool) true if wallet is decrypted, otherwise false
|
(bool) true if wallet is decrypted, otherwise false
|
||||||
"""
|
"""
|
||||||
return self.wallet_manager.encrypt_wallet(new_password)
|
|
||||||
|
return self.wallet_manager.encrypt_account(
|
||||||
|
new_password,
|
||||||
|
self.get_account_or_default(account_id, lbc_only=False)
|
||||||
|
)
|
||||||
|
|
||||||
@requires("wallet")
|
@requires("wallet")
|
||||||
def jsonrpc_account_max_address_gap(self, account_id):
|
def jsonrpc_account_max_address_gap(self, account_id):
|
||||||
|
|
|
@ -12,6 +12,7 @@ from .account import generate_certificate
|
||||||
from .transaction import Transaction
|
from .transaction import Transaction
|
||||||
from .database import WalletDatabase
|
from .database import WalletDatabase
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,8 +55,7 @@ class LbryWalletManager(BaseWalletManager):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def use_encryption(self):
|
def use_encryption(self):
|
||||||
# TODO: implement this
|
return self.default_account.serialize_encrypted
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_first_run(self):
|
def is_first_run(self):
|
||||||
|
@ -63,10 +63,35 @@ class LbryWalletManager(BaseWalletManager):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_wallet_unlocked(self):
|
def is_wallet_unlocked(self):
|
||||||
return True
|
return not self.default_account.encrypted
|
||||||
|
|
||||||
def check_locked(self):
|
def check_locked(self):
|
||||||
return defer.succeed(False)
|
return defer.succeed(self.default_account.encrypted)
|
||||||
|
|
||||||
|
def decrypt_account(self, account):
|
||||||
|
assert account.password is not None, "account is not unlocked"
|
||||||
|
assert not account.encrypted, "account is not unlocked"
|
||||||
|
account.serialize_encrypted = False
|
||||||
|
self.save()
|
||||||
|
return not account.encrypted and not account.serialize_encrypted
|
||||||
|
|
||||||
|
def encrypt_account(self, password, account):
|
||||||
|
assert not account.encrypted, "account is already encrypted"
|
||||||
|
account.encrypt(password)
|
||||||
|
account.serialize_encrypted = True
|
||||||
|
self.save()
|
||||||
|
return account.encrypted and account.serialize_encrypted
|
||||||
|
|
||||||
|
def unlock_account(self, password, account):
|
||||||
|
assert account.encrypted, "account is not locked"
|
||||||
|
account.decrypt(password)
|
||||||
|
return not account.encrypted
|
||||||
|
|
||||||
|
def lock_account(self, account):
|
||||||
|
assert account.password is not None, "account is already locked"
|
||||||
|
assert not account.encrypted and account.serialize_encrypted, "account is not encrypted"
|
||||||
|
account.encrypt(account.password)
|
||||||
|
return account.encrypted
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def migrate_lbryum_to_torba(path):
|
def migrate_lbryum_to_torba(path):
|
||||||
|
|
|
@ -247,37 +247,3 @@ class WalletTest(unittest.TestCase):
|
||||||
self.assertFailure(d, InsufficientFundsError)
|
self.assertFailure(d, InsufficientFundsError)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
||||||
class WalletEncryptionTests(unittest.TestCase):
|
|
||||||
skip = "Needs to be ported to the new wallet."
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
user_dir = tempfile.mkdtemp()
|
|
||||||
self.wallet = MocLbryumWallet(user_dir)
|
|
||||||
return self.wallet.setup(password="password")
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
return self.wallet.stop()
|
|
||||||
|
|
||||||
def test_unlock_wallet(self):
|
|
||||||
self.wallet._cmd_runner = Commands(
|
|
||||||
self.wallet.config, self.wallet.wallet, self.wallet.network, None, "password")
|
|
||||||
cmd_runner = self.wallet.get_cmd_runner()
|
|
||||||
cmd_runner.unlock_wallet("password")
|
|
||||||
self.assertIsNone(cmd_runner.new_password)
|
|
||||||
self.assertEqual(cmd_runner._password, "password")
|
|
||||||
|
|
||||||
def test_encrypt_decrypt_wallet(self):
|
|
||||||
self.wallet._cmd_runner = Commands(
|
|
||||||
self.wallet.config, self.wallet.wallet, self.wallet.network, None, "password")
|
|
||||||
self.wallet.encrypt_wallet("secret2", False)
|
|
||||||
self.wallet.decrypt_wallet()
|
|
||||||
|
|
||||||
def test_update_password_keyring_off(self):
|
|
||||||
self.wallet.config.use_keyring = False
|
|
||||||
self.wallet._cmd_runner = Commands(
|
|
||||||
self.wallet.config, self.wallet.wallet, self.wallet.network, None, "password")
|
|
||||||
|
|
||||||
# no keyring available, so ValueError is expected
|
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
self.wallet.encrypt_wallet("secret2", True)
|
|
||||||
|
|
Loading…
Reference in a new issue