diff --git a/libagent/device/interface.py b/libagent/device/interface.py index 5d69d9b..006253f 100644 --- a/libagent/device/interface.py +++ b/libagent/device/interface.py @@ -6,6 +6,8 @@ import logging import re import struct +import unidecode + from .. import formats, util log = logging.getLogger(__name__) @@ -67,7 +69,13 @@ class Identity(object): def items(self): """Return a copy of identity_dict items.""" - return self.identity_dict.items() + return [(k, unidecode.unidecode(v)) + for k, v in self.identity_dict.items()] + + def to_bytes(self): + """Transliterate Unicode into ASCII.""" + s = identity_to_string(self.identity_dict) + return unidecode.unidecode(s).encode('ascii') def __str__(self): """Return identity serialized to string.""" @@ -76,7 +84,7 @@ class Identity(object): def get_bip32_address(self, ecdh=False): """Compute BIP32 derivation address according to SLIP-0013/0017.""" index = struct.pack('L', user_id.encode('ascii'))) + user_id_bytes = user_id.encode('utf-8') + user_id_packet = protocol.packet(tag=13, blob=user_id_bytes) + data_to_sign = (pubkey.data_to_hash() + user_id_packet[:1] + + util.prefix_len('>L', user_id_bytes)) hashed_subpackets = [ protocol.subpacket_time(pubkey.created), # signature time # https://tools.ietf.org/html/rfc4880#section-5.2.3.7 diff --git a/libagent/ssh/__init__.py b/libagent/ssh/__init__.py index 1c9b248..5772d4d 100644 --- a/libagent/ssh/__init__.py +++ b/libagent/ssh/__init__.py @@ -188,7 +188,7 @@ def main(device_type): public_keys = None if args.identity.startswith('/'): filename = args.identity - contents = open(filename, 'rb').read().decode('ascii') + contents = open(filename, 'rb').read().decode('utf-8') # Allow loading previously exported SSH public keys if filename.endswith('.pub'): public_keys = list(import_public_keys(contents)) diff --git a/libagent/ssh/protocol.py b/libagent/ssh/protocol.py index d0efb6e..f013ece 100644 --- a/libagent/ssh/protocol.py +++ b/libagent/ssh/protocol.py @@ -138,7 +138,7 @@ class Handler(object): else: raise KeyError('key not found') - label = key['name'].decode('ascii') # label should be a string + label = key['name'].decode('utf-8') log.debug('signing %d-byte blob with "%s" key', len(blob), label) try: signature = self.conn.sign(blob=blob, identity=key['identity']) diff --git a/libagent/tests/test_interface.py b/libagent/tests/test_interface.py new file mode 100644 index 0000000..41113c2 --- /dev/null +++ b/libagent/tests/test_interface.py @@ -0,0 +1,7 @@ +from ..device import interface + + +def test_unicode(): + i = interface.Identity(u'ko\u017eu\u0161\u010dek@host', 'ed25519') + assert i.to_bytes() == b'kozuscek@host' + assert sorted(i.items()) == [('host', 'host'), ('user', 'kozuscek')] diff --git a/setup.py b/setup.py index d7ec82e..acdddb7 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,8 @@ setup( install_requires=[ 'ecdsa>=0.13', 'ed25519>=1.4', - 'semver>=2.2' + 'semver>=2.2', + 'unidecode>=0.4.20', ], platforms=['POSIX'], classifiers=[