-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from micimize/master
Keystore updates & disabling
- Loading branch information
Showing
5 changed files
with
113 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,3 +87,6 @@ ENV/ | |
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# vim swap files | ||
.*.sw* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,87 @@ | ||
import gnupg | ||
import getpass | ||
import sys | ||
import sys, pickle | ||
from binascii import hexlify, unhexlify | ||
import gnupg, getpass | ||
from pypeerassets.kutil import Kutil | ||
|
||
mypg = None | ||
class GpgKeystore: | ||
""" | ||
Implements reading and writing from gpg encrypted file. | ||
python-gnupg is a wrapper around the gpg cli, which makes it inherently fragile | ||
Uses pickle because private keys are binary | ||
""" | ||
|
||
def __init__(self, Settings, keyfile): | ||
assert Settings.keystore == "gnupg" | ||
|
||
def read_keystore(Settings,keyfile) -> str: | ||
mykeys = "" | ||
self._key = Settings.gnupgkey | ||
self._keyfile = keyfile | ||
|
||
if Settings.keystore == "gnupg" and Settings.provider != "rpcnode": | ||
mypg = gnupg.GPG(binary='/usr/bin/gpg',homedir=Settings.gnupgdir,use_agent=bool(Settings.gnupgagent=="True"),keyring='pubring.gpg',secring='secring.gpg') | ||
self._init_settings = dict( | ||
homedir=Settings.gnupgdir, | ||
use_agent=bool(Settings.gnupgagent == "True"), | ||
keyring='pubring.gpg', | ||
secring='secring.gpg') | ||
self.gpg = gnupg.GPG(**self._init_settings) | ||
|
||
def read(self) -> dict: | ||
password = getpass.getpass("Input gpg key password:") | ||
fd = open(keyfile) | ||
data = fd.read() | ||
contents = open(self._keyfile, 'rb').read() | ||
|
||
if len(data)>0: | ||
mykeys = str(mypg.decrypt(data,passphrase=password)) | ||
fd.close() | ||
else: | ||
print("using rpcnode") | ||
if not len(contents): | ||
return {} | ||
|
||
return mykeys | ||
decrypted = self.gpg.decrypt(contents, passphrase=password) | ||
|
||
def write_keystore(Settings,keyfile,keys): | ||
assert decrypted.ok, decrypted.status | ||
return pickle.loads(unhexlify(str(decrypted).encode())) | ||
|
||
if mypg: | ||
data = str(mypg.encrypt(str(keys),Settings.gnupgkey)) | ||
fd = open(keyfile,"w") | ||
fd.write(data) | ||
fd.close() | ||
def write(self, data: dict) -> str: | ||
encrypted = self.gpg.encrypt(hexlify(pickle.dumps(data)).decode(), self._key) | ||
assert encrypted.ok, encrypted.status | ||
keyfile = open(self._keyfile, "w") | ||
keyfile.write(str(encrypted)) | ||
keyfile.close() | ||
|
||
class KeyedProvider: | ||
|
||
def as_local_key_provider(Provider): | ||
""" | ||
Keystore class | ||
factory for subclassing Providers, | ||
allowing for local key management and isinstance checks | ||
""" | ||
|
||
@classmethod | ||
def __init__(self, provider, keysJson: str=""): | ||
class LocalKeyProvider(Provider): | ||
|
||
""" | ||
: | ||
Wraps a provider, shadowing it's private key management and deferring other logic. | ||
Uses an in-memory store to handle | ||
importprivkey, getaddressesbyaccount, listaccounts, and dumpprivkeys | ||
""" | ||
self.provider = provider | ||
|
||
if keysJson != "": | ||
self.privkeys = eval(keysJson) | ||
else: | ||
self.privkeys = {} | ||
def __init__(self, keystore: GpgKeystore, **kwargs): | ||
super(Provider, self).__init__(**kwargs) | ||
self.keystore = keystore | ||
self.privkeys = keystore.read() | ||
|
||
def importprivkey(self, privkey: str, label: str) -> int: | ||
"""import <privkey> with <label>""" | ||
mykey = Kutil(network=self.network, wif=privkey) | ||
|
||
@classmethod | ||
def __getattr__(self, name): | ||
return getattr(self.provider, name) | ||
if label not in self.privkeys.keys(): | ||
self.privkeys[label] = [] | ||
|
||
@classmethod | ||
def importprivkey(self, privkey: str, label: str) -> int: | ||
"""import <privkey> with <label>""" | ||
mykey = Kutil(wif=privkey) | ||
if mykey.privkey not in [key['privkey'] for key in self.privkeys[label]]: | ||
self.privkeys[label].append({ "privkey": mykey.privkey, | ||
"address": mykey.address }) | ||
|
||
if label not in self.privkeys.keys(): | ||
self.privkeys[label] = [] | ||
def getaddressesbyaccount(self, label: str) -> list: | ||
if label in self.privkeys.keys(): | ||
return [key["address"] for key in self.privkeys[label]] | ||
|
||
if mykey._privkey not in [key['privkey'] for key in self.privkeys[label]]: | ||
self.privkeys[label].append({"privkey":mykey._privkey,"address":mykey.address}) | ||
def listaccounts(self) -> dict: | ||
return {key:0 for key in self.privkeys.keys()} | ||
|
||
@classmethod | ||
def getaddressesbyaccount(self, label: str) -> list: | ||
if label in self.privkeys.keys(): | ||
return [key["address"] for key in self.privkeys[label]] | ||
def dumpprivkeys(self) -> dict: | ||
return self.privkeys | ||
|
||
@classmethod | ||
def listaccounts(self) -> dict: | ||
return {key:0 for key in self.privkeys.keys()} | ||
return LocalKeyProvider | ||
|
||
@classmethod | ||
def dumpprivkeys(self) -> dict: | ||
return self.privkeys |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
pypeerassets>=0.1.1 | ||
pypeerassets>=0.2.1 | ||
terminaltables>=3.1.0 | ||
gnupg>=2.1 | ||
appdirs |