diff --git a/libagent/device/interface.py b/libagent/device/interface.py index 006253f..9782aa4 100644 --- a/libagent/device/interface.py +++ b/libagent/device/interface.py @@ -77,9 +77,9 @@ class Identity(object): s = identity_to_string(self.identity_dict) return unidecode.unidecode(s).encode('ascii') - def __str__(self): + def to_string(self): """Return identity serialized to string.""" - return '<{}|{}>'.format(identity_to_string(self.identity_dict), self.curve_name) + return u'<{}|{}>'.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.""" diff --git a/libagent/formats.py b/libagent/formats.py index c5d501a..939311b 100644 --- a/libagent/formats.py +++ b/libagent/formats.py @@ -184,7 +184,7 @@ def export_public_key(vk, label): key_type, blob = serialize_verifying_key(vk) log.debug('fingerprint: %s', fingerprint(blob)) b64 = base64.b64encode(blob).decode('ascii') - return '{} {} {}\n'.format(key_type.decode('ascii'), b64, label) + return u'{} {} {}\n'.format(key_type.decode('ascii'), b64, label) def import_public_key(line): diff --git a/libagent/ssh/__init__.py b/libagent/ssh/__init__.py index 75cf03c..0f60334 100644 --- a/libagent/ssh/__init__.py +++ b/libagent/ssh/__init__.py @@ -48,6 +48,13 @@ def mosh_args(label): return args +def _to_unicode(s): + try: + return unicode(s, 'utf-8') + except NameError: + return s + + def create_agent_parser(): """Create an ArgumentParser for this tool.""" p = argparse.ArgumentParser() @@ -72,7 +79,7 @@ def create_agent_parser(): g.add_argument('--mosh', default=False, action='store_true', help='connect to specified host via using Mosh') - p.add_argument('identity', type=str, default=None, + p.add_argument('identity', type=_to_unicode, default=None, help='proto://[user@]host[:port][/path]') p.add_argument('command', type=str, nargs='*', metavar='ARGUMENT', help='command to run under the SSH agent') @@ -197,7 +204,7 @@ def main(device_type): identities = [device.interface.Identity( identity_str=args.identity, curve_name=args.ecdsa_curve_name)] for index, identity in enumerate(identities): - identity.identity_dict['proto'] = 'ssh' + identity.identity_dict['proto'] = u'ssh' log.info('identity #%d: %s', index, identity) if args.connect: diff --git a/libagent/ssh/client.py b/libagent/ssh/client.py index 98b5c8c..c34a73d 100644 --- a/libagent/ssh/client.py +++ b/libagent/ssh/client.py @@ -26,8 +26,9 @@ class Client(object): pubkey = self.device.pubkey(identity=i) vk = formats.decompress_pubkey(pubkey=pubkey, curve_name=i.curve_name) - public_keys.append(formats.export_public_key(vk=vk, - label=str(i))) + public_key = formats.export_public_key(vk=vk, + label=i.to_string()) + public_keys.append(public_key) return public_keys def sign_ssh_challenge(self, blob, identity): diff --git a/libagent/ssh/tests/test_protocol.py b/libagent/ssh/tests/test_protocol.py index fac093c..e226b80 100644 --- a/libagent/ssh/tests/test_protocol.py +++ b/libagent/ssh/tests/test_protocol.py @@ -45,7 +45,7 @@ def test_unsupported(): def ecdsa_signer(identity, blob): - assert str(identity) == '' + assert identity.to_string() == '' assert blob == NIST256_BLOB return NIST256_SIG @@ -66,7 +66,7 @@ def test_sign_missing(): def test_sign_wrong(): def wrong_signature(identity, blob): - assert str(identity) == '' + assert identity.to_string() == '' assert blob == NIST256_BLOB return b'\x00' * 64 @@ -96,7 +96,7 @@ ED25519_SIG = b'''\x8eb)\xa6\xe9P\x83VE\xfbq\xc6\xbf\x1dV3\xe3' + assert identity.to_string() == '' assert blob == ED25519_BLOB return ED25519_SIG