Wallet encryption #14

Merged
akinwale merged 2 commits from wallet-encryption into master 2017-12-20 17:10:30 +01:00
3 changed files with 69 additions and 8 deletions
Showing only changes of commit d9ea73d66f - Show all commits

View file

@ -36,7 +36,7 @@ version = 0.1
# (list) Application requirements # (list) Application requirements
# comma seperated e.g. requirements = sqlite3,kivy # comma seperated e.g. requirements = sqlite3,kivy
requirements = openssl, sqlite3, hostpython2, pycrypto==2.6.1, android, pyjnius, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pycrypto==2.6.1, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, txrequests==0.9.5, seccure==0.3.1.3, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, git+https://github.com/lbryio/lbryschema.git@v0.0.12rc1#egg=lbryschema, git+https://github.com/lbryio/lbryum.git@v3.1.9rc2#egg=lbryum, git+https://github.com/lbryio/lbry.git#egg=lbrynet, asn1crypto, cryptography==2.0.3, funcsigs, mock, pbr, unqlite requirements = openssl, sqlite3, hostpython2, pycrypto==2.6.1, android, pyjnius, constantly, incremental, functools32, miniupnpc==1.9, gmpy==1.17, twisted==16.6.0, appdirs==1.4.3, argparse==1.2.1, docopt==0.6.2, base58==0.2.2, colorama==0.3.7, dnspython==1.12.0, ecdsa==0.13, envparse==0.2.0, jsonrpc==1.2, jsonrpclib==0.1.7, jsonschema==2.5.1, pbkdf2==1.3, pycrypto==2.6.1, pyyaml==3.12, qrcode==5.2.2, requests==2.9.1, txrequests==0.9.5, seccure==0.3.1.3, service_identity==16.0.0, six==1.9.0, slowaes==0.1a1, txJSON-RPC==0.5, wsgiref==0.1.2, zope.interface==4.3.3, protobuf==3.2.0, keyring==10.4.0, git+https://github.com/lbryio/lbryschema.git@v0.0.12rc1#egg=lbryschema, git+https://github.com/akinwale/lbryum.git@wallet-encryption#egg=lbryum, git+https://github.com/akinwale/lbry.git@wallet-encryption#egg=lbrynet, asn1crypto, cryptography==2.0.3, funcsigs, mock, pbr, unqlite
# (str) Custom source folders for requirements # (str) Custom source folders for requirements
# Sets custom source for any requirements with recipes # Sets custom source for any requirements with recipes

View file

@ -122,6 +122,49 @@ public final class Utils {
return null; return null;
} }
public static void setPassword(String serviceName, String username, String password, Context context, KeyStore keyStore) {
try {
String encryptedUsername = String.format("u_%s_%s", serviceName, encrypt(username.getBytes(), context, keyStore));
String encryptedPassword = encrypt(password.getBytes(), context, keyStore);
SharedPreferences pref = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString(encryptedUsername, encryptedPassword);
editor.commit();
} catch (Exception ex) {
Log.e(TAG, "lbrynetservice - Could not set a password", ex);
}
}
public static String getPassword(String serviceName, String username, Context context, KeyStore keyStore) {
try {
String encryptedUsername = String.format("u_%s_%s", serviceName, encrypt(username.getBytes(), context, keyStore));
SharedPreferences pref = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
String encryptedPassword = pref.getString(encryptedUsername, null);
if (encryptedPassword == null || encryptedPassword.trim().length() == 0) {
return null;
}
byte[] decoded = Base64.decode(encryptedPassword, Base64.DEFAULT);
return new String(decrypt(decoded, context, keyStore), Charset.forName("UTF8"));
} catch (Exception ex) {
Log.e(TAG, "lbrynetservice - could not decrypt password for user", ex);
}
return null;
}
public static void deletePassword(String serviceName, String username, Context context, KeyStore keyStore) {
try {
String encryptedUsername = String.format("u_%s_%s", serviceName, encrypt(username.getBytes(), context, keyStore));
SharedPreferences pref = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.remove(encryptedUsername);
editor.commit();
} catch (Exception ex) {
Log.e(TAG, "lbrynetservice - Could not delete a password", ex);
}
}
public static String encrypt(byte[] input, Context context, KeyStore keyStore) throws Exception { public static String encrypt(byte[] input, Context context, KeyStore keyStore) throws Exception {
Cipher c = Cipher.getInstance(AES_MODE, "BC"); Cipher c = Cipher.getInstance(AES_MODE, "BC");
c.init(Cipher.ENCRYPT_MODE, getSecretKey(context, keyStore)); c.init(Cipher.ENCRYPT_MODE, getSecretKey(context, keyStore));

View file

@ -1,3 +1,4 @@
import keyring.backend
import platform import platform
import ssl import ssl
@ -35,12 +36,12 @@ def save_api_keys(keys, path):
if key_name in keys: if key_name in keys:
secret = keys[key_name].secret secret = keys[key_name].secret
# TODO: For testing. Normally, this should not be displayed. # TODO: For testing. Normally, this should not be displayed.
log.info('Saving API Secret: %s', secret); log.info('Saving API Secret: %s', secret)
context = service.getApplicationContext(); context = service.getApplicationContext()
lbrynet_utils.saveApiSecret(secret, context, ks) lbrynet_utils.saveApiSecret(secret, context, ks)
def initialize_api_key_file(key_path): def initialize_api_key_file(key_path):
context = service.getApplicationContext(); context = service.getApplicationContext()
secret = lbrynet_utils.loadApiSecret(context, ks) secret = lbrynet_utils.loadApiSecret(context, ks)
if secret is None: if secret is None:
keys = {} keys = {}
@ -53,9 +54,26 @@ lbrynet.daemon.auth.util.load_api_keys = load_api_keys
lbrynet.daemon.auth.util.save_api_keys = save_api_keys lbrynet.daemon.auth.util.save_api_keys = save_api_keys
lbrynet.daemon.auth.util.initialize_api_key_file = initialize_api_key_file lbrynet.daemon.auth.util.initialize_api_key_file = initialize_api_key_file
# Keyring backend
class LbryAndroidKeyring(keyring.backend.KeyringBackend):
priority = 1
def set_password(self, servicename, username, password):
context = service.getApplicationContext()
lbrynet_utils.setPassword(servicename, username, password, context, ks)
def get_password(self, servicename, username):
context = service.getApplicationContext()
return lbrynet_utils.getPassword(servicename, username, context, ks)
def delete_password(self, servicename, username):
context = service.getApplicationContext()
lbrynet_utils.deletePassword(servicename, username, context, ks)
# set the keyring backend
keyring.set_keyring(LbryAndroidKeyring())
import logging.handlers import logging.handlers
if __name__ == '__main__':
ServiceApp().run()
from lbrynet.core import log_support from lbrynet.core import log_support
from twisted.internet import defer, reactor from twisted.internet import defer, reactor
from jsonrpc.proxy import JSONRPCProxy from jsonrpc.proxy import JSONRPCProxy
@ -111,7 +129,7 @@ def start():
if test_internet_connection(): if test_internet_connection():
analytics_manager = analytics.Manager.new_instance() analytics_manager = analytics.Manager.new_instance()
start_server_and_listen(True, analytics_manager) start_server_and_listen(False, analytics_manager)
reactor.run() reactor.run()
else: else:
log.info("Not connected to internet, unable to start") log.info("Not connected to internet, unable to start")