Skip to content

Commit

Permalink
Version 2.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Crypto-Python committed Jan 31, 2023
1 parent 6801f7c commit b9557b3
Show file tree
Hide file tree
Showing 10 changed files with 770 additions and 563 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
`Unreleased <https://github.com/Cryptnox-Software/cryptnoxpro/compare/v2.7.0...HEAD>`_
--------------------------------------------------------------------------------------

`2.8.0 <https://github.com/Cryptnox-Software/cryptnoxpro/compare/v2.7.0...v2.8.0>`_ - 2022-01-31
------------------------------------------------------------------------------------------------

Added
^^^^^

- Option to start a server and access the card remotely

`2.7.0 <https://github.com/Cryptnox-Software/cryptnoxpro/compare/v2.6.0...v2.7.0>`_ - 2022-11-28
------------------------------------------------------------------------------------------------

Expand Down
1,027 changes: 549 additions & 478 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cryptnoxpro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-

__version__ = "2.7.0"
__version__ = "2.8.0"
1 change: 1 addition & 0 deletions cryptnoxpro/command/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def command(data: Namespace, cards: Cards = None) -> Command:
from .initialize import Initialize # pylint: disable=unused-import
from .seed import Seed # pylint: disable=unused-import
from .cards import Cards # pylint: disable=unused-import
from .server import Server # pylint: disable=unused-import
from .reset import Reset # pylint: disable=unused-import
from .unlock_pin import UnlockPin # pylint: disable=unused-import
from .user_key import UserKey # pylint: disable=unused-import
Expand Down
10 changes: 10 additions & 0 deletions cryptnoxpro/command/options/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ def add(parser, interactive: bool = False):
_seed_options(subparsers, interactive)
_reset_options(subparsers, interactive)

_server_options(subparsers, interactive)

if interactive:
use_sub_parser = subparsers.add_parser("use", help="Change card to be used by default")
use_sub_parser.add_argument("serial_index", type=int, nargs="?",
Expand Down Expand Up @@ -148,6 +150,14 @@ def _list_options(subparsers, _: bool):
subparsers.add_parser(enums.Command.CARD.value, help="List all cards")


def _server_options(subparsers, _: bool):
sub_parser = subparsers.add_parser(enums.Command.SERVER.value,
help="Create a server or establish connection to server")
sub_parser.add_argument('--port', nargs='?', type=int, default=5050,
help='Define port to server port, default 5050')
sub_parser.add_argument('--host', nargs='?', type=str, default='0.0.0.0',
help='Define port to server host, default 0.0.0.0')

def _reset_options(subparsers, _: bool):
subparsers.add_parser(enums.Command.RESET.value, help="Reset card")

Expand Down
116 changes: 116 additions & 0 deletions cryptnoxpro/command/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import pickle
import selectors
import types
import socket

import cryptnoxpy

from .command import Command

try:
import enums
except ImportError:
from .. import enums


class Server(Command):
_name = enums.Command.SERVER.value
_HEADER_SIZE = 64
_ENCODING = 'utf-8'

def _execute(self, card: cryptnoxpy) -> int:
self.sel = selectors.DefaultSelector()
self.card = card
self._start(self.data.host, self.data.port)

return 0

def _start(self, host, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen()
print(f"Listening on {(host, port)}")
sock.setblocking(False)
self.sel.register(sock, selectors.EVENT_READ, data=None)

try:
self._loop()
except KeyboardInterrupt:
print("Caught keyboard interrupt, exiting")
finally:
self.sel.close()

def _loop(self):
while True:
events = self.sel.select(timeout=0.1)
self._process_events(events)

def _process_events(self, events):
for key, mask in events:
if key.data is None:
self._accept_wrapper(key.fileobj)
else:
self._service_connection(key, mask)

def _accept_wrapper(self, sock):
conn, addr = sock.accept() # Should be ready to read
print(f"Accepted connection from {addr}")
conn.setblocking(False)
data = types.SimpleNamespace(addr=addr, outb=b"")
events = selectors.EVENT_READ | selectors.EVENT_WRITE
self.sel.register(conn, events, data=data)

def _service_connection(self, key, mask):
sock = key.fileobj
data = key.data
if mask & selectors.EVENT_READ:
data.outb += self._receive(sock, data.addr)

if mask & selectors.EVENT_WRITE and data.outb:
print(f"Echoing {data.outb!r} to {data.addr}")
sent = sock.send(data.outb) # Should be ready to write
data.outb = data.outb[sent:]

def _close(self, sock, address):
print(f"Closing connection to {address}")
self.sel.unregister(sock)
sock.close()

def _receive(self, sock, address) -> bytes:
print(f'Receiving command')
message = sock.recv(Server._HEADER_SIZE)
if not message:
self._close(sock, address)

try:
message_length = int(message.decode(Server._ENCODING))
except ValueError:
return b''

pickled_data = sock.recv(message_length)
if not pickled_data:
self._close(sock, address)
return b''

return self._process_in_card(pickled_data)

def _process_in_card(self, pickled_data: str) -> bytes:
print(f'Transmitting APDU command to card')
try:
command = pickle.loads(pickled_data)
except pickle.UnpicklingError:
return b''

try:
response = self.card.connection._reader.send(command)
except cryptnoxpy.CryptnoxException as error:
print(f'Error with card: {error}')
return b''

print(f'Responding back to server')
pickled_response = pickle.dumps(response)
msg_length = len(pickled_response)
send_length = str(msg_length).encode(Server._ENCODING)
send_length += (' ' * (Server._HEADER_SIZE - len(send_length))).encode(Server._ENCODING)

return send_length + pickled_response
1 change: 1 addition & 0 deletions cryptnoxpro/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Command(Enum):
INFO = "info"
INITIALIZE = "init"
CARD = "list"
SERVER = "server"
RESET = "reset"
SEED = "seed"
UNLOCK_PIN = "unlock_pin"
Expand Down
66 changes: 34 additions & 32 deletions cryptnoxpro/interactive_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,38 +337,40 @@ def _process_command(self):
pass
UsageParser.throw_error = True
else:
if args.command == "exit":
raise InteractiveCli.ExitException
if args.command == "use":
self._card_info = None
if args.serial_index is None:
try:
self._card_info = self._cards.select_card().info
except (cryptnoxpy.CryptnoxException, ExitException, TimeoutException) as error:
print(error)
return
else:
print(f"Changing card to: {self._card_info['serial_number']}\n")
else:
try:
self._card_info = self._cards[args.serial_index].info
except (cryptnoxpy.CryptnoxException, ExitException, TimeoutException) as error:
print(error)
return
except KeyError:
pass
else:
print(f"Changing card to: {self._card_info['serial_number']}\n")
if not self._card_info:
print("Can't change card")

elif args.command == "back" and self.subcommand:
self.subcommand.pop(-1)
elif args.command:
if self._card_info and args.command in to_always_run:
if self._card_info["serial_number"] not in self._cards:
self._card_info = None
self._run_command(args, to_always_run)
self._process(args, to_always_run)

def _process(self, args, to_always_run: List = None) -> None:
to_always_run = [] or to_always_run
if args.command == "exit":
raise InteractiveCli.ExitException

if args.command == "use":
self._use(args.serial_index)

elif args.command == "back" and self.subcommand:
self.subcommand.pop(-1)
elif args.command:
if self._card_info and args.command in to_always_run:
if self._card_info["serial_number"] not in self._cards:
self._card_info = None
self._run_command(args, to_always_run)

def _use(self, serial_index):
self._card_info = None

try:
if serial_index is None:
self._card_info = self._cards.select_card().info
else:
self._card_info = self._cards[serial_index].info
except (cryptnoxpy.CryptnoxException, ExitException, TimeoutException) as error:
print(error)
return

if self._card_info:
print(f"Changing card to: {self._card_info['serial_number']}\n")
else:
print("Can't change card")

@property
def _prompt(self) -> str:
Expand Down
65 changes: 32 additions & 33 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ aiosignal==1.3.1; python_version >= '3.7'
altgraph==0.17.3
appdirs==1.4.4
argparse==1.4.0
astroid==2.12.13; python_full_version >= '3.7.2'
astroid==2.13.4; python_full_version >= '3.7.2'
async-timeout==4.0.2; python_version >= '3.6'
attrs==22.1.0; python_version >= '3.5'
attrs==22.2.0; python_version >= '3.6'
base58==2.1.1
bitarray==2.6.0
boto3==1.26.17
botocore==1.29.17; python_version >= '3.7'
certifi==2022.9.24; python_version >= '3.6'
bitarray==2.6.2
boto3==1.26.60
botocore==1.29.60; python_version >= '3.7'
certifi==2022.12.7; python_version >= '3.6'
cffi==1.15.1
charset-normalizer==2.1.1; python_version >= '3.6'
colander==1.8.3
colander==2.0
colorama==0.4.6; sys_platform == 'win32'
cryptnoxpy==2.3.0
cryptography==38.0.4; python_version >= '3.6'
cytoolz==0.12.0; python_version >= '3.5'
dill==0.3.6; python_version >= '3.7'
cryptnoxpy==2.4.0
cryptography==39.0.0; python_version >= '3.6'
cytoolz==0.12.1; python_version >= '3.6'
dill==0.3.6; python_version < '3.11'
ecdsa==0.18.0
eth-abi==2.2.0; python_version >= '3.6' and python_version < '4'
eth-account==0.5.9; python_version >= '3.6' and python_version < '4'
Expand All @@ -39,50 +39,49 @@ eth-keys==0.3.4
eth-rlp==0.2.1; python_version >= '3.6' and python_version < '4'
eth-typing==2.3.0; python_version >= '3.5' and python_version < '4'
eth-utils==1.9.5; python_version >= '3.5' and python_version < '4' and python_full_version != '3.5.2'
exceptiongroup==1.0.4; python_version < '3.11'
exceptiongroup==1.1.0; python_version < '3.11'
frozenlist==1.3.3; python_version >= '3.7'
future==0.18.2; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
future==0.18.3; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
hexbytes==0.3.0; python_version >= '3.7' and python_version < '4'
idna==3.4; python_version >= '3.5'
iniconfig==1.1.1
iniconfig==2.0.0; python_version >= '3.7'
ipfshttpclient==0.8.0a2; python_full_version >= '3.6.2' and python_full_version not in '3.7.0, 3.7.1'
iso8601==1.1.0; python_version < '4' and python_full_version >= '3.6.2'
isort==5.10.1; python_version < '4.0' and python_full_version >= '3.6.1'
isort==5.12.0; python_full_version >= '3.8.0'
jmespath==1.0.1; python_version >= '3.7'
jsonschema==4.17.1; python_version >= '3.7'
jsonschema==4.17.3; python_version >= '3.7'
lazy-import==0.2.2
lazy-object-proxy==1.8.0; python_version >= '3.7'
lazy-object-proxy==1.9.0; python_version >= '3.7'
lru-dict==1.1.8
mccabe==0.7.0; python_version >= '3.6'
multiaddr==0.0.9; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
multidict==6.0.2; python_version >= '3.7'
multidict==6.0.4; python_version >= '3.7'
mypy-extensions==0.4.3
mypy==0.991
netaddr==0.8.0
packaging==21.3; python_version >= '3.6'
packaging==23.0; python_version >= '3.7'
parsimonious==0.8.1
pefile==2022.5.30; sys_platform == 'win32'
platformdirs==2.5.4; python_version >= '3.7'
platformdirs==2.6.2; python_version >= '3.7'
pluggy==1.0.0; python_version >= '3.6'
protobuf==3.19.5; python_version >= '3.5'
pycparser==2.21
pycryptodome==3.16.0
pyinstaller-hooks-contrib==2022.13; python_version >= '3.7'
pyinstaller==5.6.2
pylint==2.15.6
pyparsing==3.0.9; python_full_version >= '3.6.8'
pyrsistent==0.19.2; python_version >= '3.7'
pycryptodome==3.17
pyinstaller-hooks-contrib==2022.15; python_version >= '3.7'
pyinstaller==5.7.0
pylint==2.15.10
pyrsistent==0.19.3; python_version >= '3.7'
pyscard==2.0.3
pytest-pylint==0.19.0
pytest==7.2.0
pytest==7.2.1
python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
pytz==2022.6
pytz==2022.7.1
pywin32-ctypes==0.2.0; sys_platform == 'win32'
pywin32==305; platform_system == 'Windows'
requests==2.28.1
requests==2.28.2
rlp==2.0.1
s3transfer==0.6.0; python_version >= '3.7'
setuptools==65.6.3; python_version >= '3.7'
setuptools==67.0.0; python_version >= '3.7'
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
stdiomask==0.0.6
tabulate==0.9.0
Expand All @@ -92,10 +91,10 @@ tomlkit==0.11.6; python_version >= '3.6'
toolz==0.12.0; python_version >= '3.5'
translationstring==1.4
typing-extensions==4.4.0; python_version >= '3.7'
urllib3==1.26.13; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
urllib3==1.26.14; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
varint==1.0.2
web3==5.31.1
web3==5.31.3
websockets==9.1; python_full_version >= '3.6.1'
winsdk==1.0.0b7; sys_platform == 'win32'
wrapt==1.14.1; python_version < '3.11'
yarl==1.8.1; python_version >= '3.7'
yarl==1.8.2; python_version >= '3.7'
Expand Down
Loading

0 comments on commit b9557b3

Please sign in to comment.