123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- import subprocess
- import tempfile
- import pytest
- keytypes = [
- "rsa", "rsa-4096",
- "ed25519",
- "ecdsa", "ecdsa-256", "ecdsa-384", "ecdsa-521",
- "dss",
- ]
- def parse_keytype(kt):
- if '-' in kt:
- return kt.split('-')
- else:
- return (kt, None)
- @pytest.mark.parametrize("keytype", keytypes)
- @pytest.mark.parametrize("keyformat", [None, "PEM"])
- def test_from_openssh(request, tmp_path, keytype, keyformat):
- """
- Convert OpenSSH to Dropbear format,
- PEM and OpenSSH internal
- """
- opt = request.config.option
- kt, keybits = parse_keytype(keytype)
- if kt == 'dss' and keyformat is None:
- pytest.skip("dss doesn't support openssh format")
- os_kt = kt
- if os_kt == 'dss':
- # OpenSSH calls it 'dsa', Dropbear calls it 'dss'
- os_kt = 'dsa'
- os_key = tmp_path / 'oskey1'
- db_key = tmp_path / 'dbkey1'
- # Generate an OpenSSH key
- args = [
- opt.ssh_keygen,
- '-f', os_key,
- '-t', os_kt,
- '-N', '', # no password
- ]
- if keybits is not None:
- args += ['-b', keybits]
- if keyformat:
- args += ['-m', keyformat]
- p = subprocess.run(args, check=True)
- # Convert to dropbear format
- args = [
- opt.dropbearconvert,
- 'openssh', 'dropbear',
- os_key, db_key,
- ]
- p = subprocess.run(args, check=True)
- # Compare pubkeys
- args = [
- opt.dropbearkey,
- '-f', db_key,
- '-y'
- ]
- p = subprocess.run(args, check=True, stdout=subprocess.PIPE, text=True)
- db_pubkey = p.stdout.splitlines()[1].strip()
- os_pubkey = os_key.with_suffix('.pub').open().read().strip()
- # we compare the whole key including comment since it currently matches
- assert db_pubkey == os_pubkey
- @pytest.mark.parametrize("keytype", keytypes)
- def test_roundtrip(request, tmp_path, keytype):
- """
- Dropbear's private key format is deterministic so
- we can compare round trip conversion. (OpenSSH's
- format has more variable comments and other fields).
- """
- opt = request.config.option
- kt, keybits = parse_keytype(keytype)
- os_key = tmp_path / 'oskey1'
- db_key1 = tmp_path / 'dbkey1'
- db_key2 = tmp_path / 'dbkey2'
- # generate a key
- args = [
- opt.dropbearkey,
- '-t', kt,
- '-f', db_key1,
- ]
- if keybits is not None:
- args += ['-s', keybits]
- p = subprocess.run(args, check=True)
- # convert to openssh
- args = [
- opt.dropbearconvert,
- 'dropbear', 'openssh',
- db_key1, os_key,
- ]
- p = subprocess.run(args, check=True)
- # Check ssh-keygen can read it
- args = [
- opt.ssh_keygen,
- '-f', os_key,
- '-y',
- ]
- p = subprocess.run(args, check=True, text=True, stdout=subprocess.PIPE)
- os_pubkey = p.stdout.strip()
- # Compare public keys
- args = [
- opt.dropbearkey,
- '-f', db_key1,
- '-y',
- ]
- p = subprocess.run(args, check=True, text=True, stdout=subprocess.PIPE)
- db_pubkey = p.stdout.splitlines()[1].strip()
- # comment may differ
- db_pubkey = db_pubkey.split(' ')[:2]
- os_pubkey = os_pubkey.split(' ')[:2]
- assert db_pubkey == os_pubkey
- # convert back to dropbear
- args = [
- opt.dropbearconvert,
- 'openssh', 'dropbear',
- os_key, db_key2,
- ]
- p = subprocess.run(args, check=True)
- # check the round trip is identical
- assert db_key1.open('rb').read() == db_key2.open('rb').read()
|