diff --git a/libagent/formats.py b/libagent/formats.py index 36f69d6..28a911a 100644 --- a/libagent/formats.py +++ b/libagent/formats.py @@ -25,8 +25,10 @@ SSH_NIST256_DER_OCTET = b'\x04' SSH_NIST256_KEY_PREFIX = b'ecdsa-sha2-' SSH_NIST256_CURVE_NAME = b'nistp256' SSH_NIST256_KEY_TYPE = SSH_NIST256_KEY_PREFIX + SSH_NIST256_CURVE_NAME +SSH_NIST256_CERT_POSTFIX = b'-cert-v01@openssh.com' +SSH_NIST256_CERT_TYPE = SSH_NIST256_KEY_TYPE + SSH_NIST256_CERT_POSTFIX SSH_ED25519_KEY_TYPE = b'ssh-ed25519' -SUPPORTED_KEY_TYPES = {SSH_NIST256_KEY_TYPE, SSH_ED25519_KEY_TYPE} +SUPPORTED_KEY_TYPES = {SSH_NIST256_KEY_TYPE, SSH_NIST256_CERT_TYPE, SSH_ED25519_KEY_TYPE} hashfunc = hashlib.sha256 @@ -49,6 +51,7 @@ def parse_pubkey(blob): The verifier returns the signatures in the required SSH format. Currently, NIST256P1 and ED25519 elliptic curves are supported. """ + # pylint: disable=too-many-locals fp = fingerprint(blob) s = io.BytesIO(blob) key_type = util.read_frame(s) @@ -57,10 +60,27 @@ def parse_pubkey(blob): result = {'blob': blob, 'type': key_type, 'fingerprint': fp} - if key_type == SSH_NIST256_KEY_TYPE: + if key_type in (SSH_NIST256_KEY_TYPE, SSH_NIST256_CERT_TYPE): + if key_type == SSH_NIST256_CERT_TYPE: + _nonce = util.read_frame(s) + curve_name = util.read_frame(s) log.debug('curve name: %s', curve_name) point = util.read_frame(s) + + if key_type == SSH_NIST256_CERT_TYPE: + _serial_number = util.recv(s, '>Q') + _type = util.recv(s, '>L') + _key_id = util.read_frame(s) + _valid_principals = util.read_frame(s) + _valid_after = util.recv(s, '>Q') + _valid_before = util.recv(s, '>Q') + _critical_options = util.read_frame(s) + _extensions = util.read_frame(s) + _reserved = util.read_frame(s) + _signature_key = util.read_frame(s) + _signature = util.read_frame(s) + assert s.read() == b'' _type, point = point[:1], point[1:] assert _type == SSH_NIST256_DER_OCTET diff --git a/libagent/tests/test_formats.py b/libagent/tests/test_formats.py index 93fce86..e0a777d 100644 --- a/libagent/tests/test_formats.py +++ b/libagent/tests/test_formats.py @@ -23,6 +23,26 @@ _public_key = ( 'home\n' ) +_public_key_cert = ( + 'ecdsa-sha2-nistp256-cert-v01@openssh.com ' + 'AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3B' + 'lbnNzaC5jb20AAAAgohlAP8H3LPYWz3+w/E+RGDxG6tNAEE' + '3Ao9Z6Pc66khEAAAAIbmlzdHAyNTYAAABBBGI2zqveJSB+g' + 'eQEWG46OvGs2h3+0qu7tIdsH8WylrV19vttd7GR5rKvTWJt' + '8b9ErthmnFALelAFKOB/u50jsukAAAAAAAAAFQAAAAEAAAA' + 'IdW5pdFRlc3QAAAAIAAAABHVzZXIAAAAAAAAAAP////////' + '//AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nA' + 'AAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAA' + 'AAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGV' + 'ybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAA' + 'AAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgf9gyPrF24CLZc' + '0rHoZuI1+yjBFWt66G8oUmm20yRO8IAAABTAAAAC3NzaC1l' + 'ZDI1NTE5AAAAQCEgVgsR7fSgcTxuAWqMW4h42y7pt1BAKR4' + 'HTRg178tl7Vx8WoRtQcNirX9eggBcTA+5ILWmeY3uDN+soW' + 't7fwk= ' + 'home\n' +) + def test_parse_public_key(): key = formats.import_public_key(_public_key) @@ -34,6 +54,16 @@ def test_parse_public_key(): assert key['type'] == b'ecdsa-sha2-nistp256' +def test_parse_public_key_cert(): + key = formats.import_public_key(_public_key_cert) + assert key['name'] == b'home' + assert key['point'] == _point + + assert key['curve'] == 'nist256p1' + assert key['fingerprint'] == 'ab:ab:5d:9f:f4:33:f4:d0:c3:68:65:3b:94:86:de:22' # nopep8 + assert key['type'] == b'ecdsa-sha2-nistp256-cert-v01@openssh.com' + + def test_decompress(): blob = '036236ceabde25207e81e404586e3a3af1acda1dfed2abbbb4876c1fc5b296b575' vk = formats.decompress_pubkey(binascii.unhexlify(blob),