Skip to content
This repository was archived by the owner on Sep 2, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ app/vault/ui_*py
#[folders]
app/vault/src/atdlib/
bin/
dojo/
etc/blockstack/*
etc/zerotier/*
ext/pyqt/
Expand Down
7 changes: 5 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# Release Notes

## ΔOS v0.8-alpha.9

* restore: `logger`
* add-`graphviz`: `logger` graphics

## ΔOS v0.8-alpha.8

* add-`atdlib`: `vault_module.c`
* add-`atdlib`: `deos_module.c`
* add-`app`: `wallet`
* clone-repo: `electrum` -> `app/wallet`
* restore: `logger`
* add-`graphviz`: `logger` graphics
* create-protocol: release notes
* restore: `var/wiki`
* restore: `boot/*.lz`
2 changes: 1 addition & 1 deletion src/atdlib/atdlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

__author__ = "Andrew DeSantis <atd@gmx.it>"
__license__ = "GPLv3"
__version__ = "v0.8-alpha.8"
__version__ = "v0.8-alpha.9"

import atdlib.deos as deos
import atdlib.vault as vault
19 changes: 11 additions & 8 deletions src/trezor-agent/scripts/gpg-init
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
#!/bin/bash
set -eu

gpg2 --version >/dev/null # verify that GnuPG 2 is installed
# verify that GnuPG 2 is installed
gpg2 --version >/dev/null

USER_ID="${1}"
HOMEDIR=~/.gnupg/trezor
CURVE=${CURVE:="nist256p1"} # or "ed25519"
TIMESTAMP=${TIMESTAMP:=`date +%s`} # key creation timestamp
CURVE=${CURVE:="nist256p1"} # or "ed25519"
TIMESTAMP=${TIMESTAMP:=`date +%s`} # key creation timestamp

# Prepare new GPG home directory for TREZOR-based identity
rm -rf "${HOMEDIR}"
mkdir -p "${HOMEDIR}"
chmod 700 "${HOMEDIR}"
rm -rf "${HOMEDIR}" && mkdir -p "${HOMEDIR}" && chmod 700 "${HOMEDIR}"

# Generate new GPG identity and import into GPG keyring
trezor-gpg-create -v "${USER_ID}" -t "${TIMESTAMP}" -e "${CURVE}" > "${HOMEDIR}/pubkey.asc"
trezor-gpg-create -v "${USER_ID}" \
-t "${TIMESTAMP}" \
-e "${CURVE}" > "${HOMEDIR}/pubkey.asc"
gpg2 --homedir "${HOMEDIR}" --import < "${HOMEDIR}/pubkey.asc"
rm -f "${HOMEDIR}/S.gpg-agent" # (otherwise, our agent won't be started automatically)

# (otherwise, our agent won't be started automatically)
rm -f "${HOMEDIR}/S.gpg-agent"

# Make new GPG identity with "ultimate" trust (via its fingerprint)
FINGERPRINT=$(gpg2 --homedir "${HOMEDIR}" --list-public-keys --with-fingerprint --with-colons | sed -n -E 's/^fpr:::::::::([0-9A-F]+):$/\1/p' | head -n1)
Expand Down
3 changes: 2 additions & 1 deletion src/trezor-agent/scripts/gpg-shell
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#!/bin/bash
set -eu

gpg2 --version >/dev/null # verify that GnuPG 2 is installed
# verify that GnuPG 2 is installed
gpg2 --version >/dev/null

export GNUPGHOME=~/.gnupg/trezor

Expand Down
7 changes: 4 additions & 3 deletions src/trezor-agent/trezor_agent/device/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Cryptographic hardware device management."""
""" Cryptographic hardware device management.
"""

import logging

Expand All @@ -15,9 +16,9 @@
ledger.LedgerNanoS,
]


def detect():
"""Detect the first available device and return it to the user."""
""" Detect the first available device and return it to the user.
"""
for device_type in DEVICE_TYPES:
try:
with device_type() as d:
Expand Down
73 changes: 44 additions & 29 deletions src/trezor-agent/trezor_agent/device/interface.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Device abstraction layer."""
""" Device abstraction layer.
"""

import hashlib
import io
Expand All @@ -20,17 +21,17 @@
'$'
]))


def string_to_identity(identity_str):
"""Parse string into Identity dictionary."""
""" Parse string into Identity dictionary.
"""
m = _identity_regexp.match(identity_str)
result = m.groupdict()
log.debug('parsed identity: %s', result)
return {k: v for k, v in result.items() if v}


def identity_to_string(identity_dict):
"""Dump Identity dictionary into its string representation."""
""" Dump Identity dictionary into its string representation.
"""
result = []
if identity_dict.get('proto'):
result.append(identity_dict['proto'] + '://')
Expand All @@ -44,37 +45,42 @@ def identity_to_string(identity_dict):
log.debug('identity parts: %s', result)
return ''.join(result)


class Error(Exception):
"""Device-related error."""

""" Device-related error.
"""

class NotFoundError(Error):
"""Device could not be found."""

""" Device could not be found.
"""

class DeviceError(Error):
""""Error during device operation."""

""" Error during device operation.
"""

class Identity(object):
"""Represent SLIP-0013 identity, together with a elliptic curve choice."""
""" Represent SLIP-0013 identity, together w/ a elliptic curve choice.
"""

def __init__(self, identity_str, curve_name):
"""Configure for specific identity and elliptic curve usage."""
""" Configure for specific identity and elliptic curve usage.
"""
self.identity_dict = string_to_identity(identity_str)
self.curve_name = curve_name

def items(self):
"""Return a copy of identity_dict items."""
""" Return a copy of identity_dict items.
"""
return self.identity_dict.items()

def __str__(self):
"""Return identity serialized to string."""
return '<{}|{}>'.format(identity_to_string(self.identity_dict), self.curve_name)
""" Return identity serialized to string.
"""
return '<{}|{}>'.format(identity_to_string(self.identity_dict),
self.curve_name)

def get_bip32_address(self, ecdh=False):
"""Compute BIP32 derivation address according to SLIP-0013/0017."""
""" Compute BIP32 derivation address according to SLIP-0013/0017.
"""
index = struct.pack('<L', self.identity_dict.get('index', 0))
addr = index + identity_to_string(self.identity_dict).encode('ascii')
log.debug('bip32 address string: %r', addr)
Expand All @@ -87,49 +93,58 @@ def get_bip32_address(self, ecdh=False):
return [(hardened | value) for value in address_n]

def get_curve_name(self, ecdh=False):
"""Return correct curve name for device operations."""
""" Return correct curve name for device operations.
"""
if ecdh:
return formats.get_ecdh_curve_name(self.curve_name)
else:
return self.curve_name


class Device(object):
"""Abstract cryptographic hardware device interface."""
""" Abstract cryptographic hardware device interface.
"""

def __init__(self):
"""C-tor."""
""" C-tor.
"""
self.conn = None

def connect(self):
"""Connect to device, otherwise raise NotFoundError."""
""" Connect to device, otherwise raise NotFoundError.
"""
raise NotImplementedError()

def __enter__(self):
"""Allow usage as context manager."""
""" Allow usage as context manager.
"""
self.conn = self.connect()
return self

def __exit__(self, *args):
"""Close and mark as disconnected."""
""" Close and mark as disconnected.
"""
try:
self.conn.close()
except Exception as e: # pylint: disable=broad-except
log.exception('close failed: %s', e)
self.conn = None

def pubkey(self, identity, ecdh=False):
"""Get public key (as bytes)."""
""" Get public key (as bytes).
"""
raise NotImplementedError()

def sign(self, identity, blob):
"""Sign given blob and return the signature (as bytes)."""
""" Sign given blob and return the signature (as bytes).
"""
raise NotImplementedError()

def ecdh(self, identity, pubkey):
"""Get shared session key using Elliptic Curve Diffie-Hellman."""
""" Get shared session key using Elliptic Curve Diffie-Hellman.
"""
raise NotImplementedError()

def __str__(self):
"""Human-readable representation."""
""" Human-readable representation.
"""
return '{}'.format(self.__class__.__name__)
18 changes: 10 additions & 8 deletions src/trezor-agent/trezor_agent/device/keepkey.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"""KeepKey-related code (see https://www.keepkey.com/)."""
""" KeepKey-related code (see: https://www.keepkey.com/).
"""

from . import trezor
from .. import formats


def _verify_support(identity, ecdh):
"""Make sure the device supports given configuration."""
""" Make sure the device supports given configuration.
"""
protocol = identity.identity_dict['proto']
if protocol not in {'ssh'}:
raise NotImplementedError(
Expand All @@ -16,10 +17,9 @@ def _verify_support(identity, ecdh):
raise NotImplementedError(
'Unsupported elliptic curve: {}'.format(identity.curve_name))


class KeepKey(trezor.Trezor):
"""Connection to KeepKey device."""

""" Connection to KeepKey device.
"""
@property
def _defs(self):
from . import keepkey_defs
Expand All @@ -28,10 +28,12 @@ def _defs(self):
required_version = '>=1.0.4'

def pubkey(self, identity, ecdh=False):
"""Return public key."""
""" Return public key.
"""
_verify_support(identity, ecdh)
return trezor.Trezor.pubkey(self, identity=identity, ecdh=ecdh)

def ecdh(self, identity, pubkey):
"""No support for ECDH in KeepKey firmware."""
""" No support for ECDH in KeepKey firmware.
"""
_verify_support(identity, ecdh=True)
3 changes: 2 additions & 1 deletion src/trezor-agent/trezor_agent/device/keepkey_defs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""KeepKey-related definitions."""
""" KeepKey-related definitions.
"""

# pylint: disable=unused-import

Expand Down
27 changes: 16 additions & 11 deletions src/trezor-agent/trezor_agent/device/ledger.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Ledger-related code (see https://www.ledgerwallet.com/)."""
""" Ledger-related code (see https://www.ledgerwallet.com/).
"""

import binascii
import logging
Expand All @@ -10,14 +11,14 @@

log = logging.getLogger(__name__)


def _expand_path(path):
"""Convert BIP32 path into bytes."""
""" Convert BIP32 path into bytes.
"""
return b''.join((struct.pack('>I', e) for e in path))


def _convert_public_key(ecdsa_curve_name, result):
"""Convert Ledger reply into PublicKey object."""
""" Convert Ledger reply into PublicKey object.
"""
if ecdsa_curve_name == 'nist256p1':
if (result[64] & 1) != 0:
result = bytearray([0x03]) + result[1:33]
Expand All @@ -32,20 +33,22 @@ def _convert_public_key(ecdsa_curve_name, result):
result = b'\x00' + bytes(keyY)
return bytes(result)


class LedgerNanoS(interface.Device):
"""Connection to Ledger Nano S device."""
""" Connection to Ledger Nano S device.
"""

def connect(self):
"""Enumerate and connect to the first USB HID interface."""
""" Enumerate and connect to the first USB HID interface.
"""
try:
return comm.getDongle()
except comm.CommException as e:
raise interface.NotFoundError(
'{} not connected: "{}"'.format(self, e))

def pubkey(self, identity, ecdh=False):
"""Get PublicKey object for specified BIP32 address and elliptic curve."""
""" Get PublicKey object for specified BIP32 address & elliptic curve.
"""
curve_name = identity.get_curve_name(ecdh)
path = _expand_path(identity.get_bip32_address(ecdh))
if curve_name == 'nist256p1':
Expand All @@ -60,7 +63,8 @@ def pubkey(self, identity, ecdh=False):
return _convert_public_key(curve_name, result)

def sign(self, identity, blob):
"""Sign given blob and return the signature (as bytes)."""
""" Sign given blob and return the signature (as bytes).
"""
path = _expand_path(identity.get_bip32_address(ecdh=False))
if identity.identity_dict['proto'] == 'ssh':
ins = '04'
Expand Down Expand Up @@ -95,7 +99,8 @@ def sign(self, identity, blob):
return bytes(result[:64])

def ecdh(self, identity, pubkey):
"""Get shared session key using Elliptic Curve Diffie-Hellman."""
""" Get shared session key using Elliptic Curve Diffie-Hellman.
"""
path = _expand_path(identity.get_bip32_address(ecdh=True))
if identity.curve_name == 'nist256p1':
p2 = '01'
Expand Down
Loading