Skip to content

Commit

Permalink
Add certificate builder and test ED25519 signed by RSA
Browse files Browse the repository at this point in the history
  • Loading branch information
jnewbigin authored and russell-lewis committed Jul 13, 2018
1 parent cdde67a commit f1e2a30
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 5 deletions.
39 changes: 39 additions & 0 deletions bless/ssh/certificates/ed25519_certificate_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
.. module: bless.ssh.certificates.ed25519_certificate_builder
:copyright: (c) 2016 by Netflix Inc., see AUTHORS for more
:license: Apache, see LICENSE for more details.
"""
from bless.ssh.certificates.ssh_certificate_builder import \
SSHCertificateBuilder, SSHCertifiedKeyType
from bless.ssh.protocol.ssh_protocol import pack_ssh_string


class ED25519CertificateBuilder(SSHCertificateBuilder):
def __init__(self, ca, cert_type, ssh_public_key_ed25519):
"""
Produces an SSH certificate for ED25519 public keys.
:param ca: The SSHCertificateAuthority that will sign the certificate. The
SSHCertificateAuthority type does not need to be the same type as the
SSHCertificateBuilder.
:param cert_type: The SSHCertificateType. Is this a User or Host certificate? Some of
the SSH Certificate fields do not apply or have a slightly different meaning depending on
the certificate type.
See http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys
:param ssh_public_key_ed25519: The ED25519PublicKey to issue a certificate for.
"""
super(ED25519CertificateBuilder, self).__init__(ca, cert_type)
self.cert_key_type = SSHCertifiedKeyType.ED25519
self.ssh_public_key = ssh_public_key_ed25519
self.public_key_comment = ssh_public_key_ed25519.key_comment
self.a = ssh_public_key_ed25519.a

def _serialize_ssh_public_key(self):
"""
Serialize the Public Key into a string. This is not specified in
http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys
but https://tools.ietf.org/id/draft-ietf-curdle-ssh-ed25519-02.html
:return: The bytes that belong in the SSH Certificate between the nonce and the
certificate serial number.
"""
public_key = pack_ssh_string(self.a)
return public_key
4 changes: 4 additions & 0 deletions bless/ssh/certificates/ssh_certificate_builder_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"""
from bless.ssh.certificates.rsa_certificate_builder \
import RSACertificateBuilder
from bless.ssh.certificates.ed25519_certificate_builder \
import ED25519CertificateBuilder
from bless.ssh.public_keys.ssh_public_key import SSHPublicKeyType
from bless.ssh.public_keys.ssh_public_key_factory import get_ssh_public_key

Expand All @@ -23,5 +25,7 @@ def get_ssh_certificate_builder(ca, cert_type, public_key_to_sign):

if ssh_public_key.type is SSHPublicKeyType.RSA:
return RSACertificateBuilder(ca, cert_type, ssh_public_key)
elif ssh_public_key.type is SSHPublicKeyType.ED25519:
return ED25519CertificateBuilder(ca, cert_type, ssh_public_key)
else:
raise TypeError("Unsupported Public Key Type")
11 changes: 7 additions & 4 deletions tests/ssh/test_ssh_certificate_builder_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
get_ssh_certificate_authority
from bless.ssh.certificates.rsa_certificate_builder import RSACertificateBuilder, \
SSHCertifiedKeyType
from bless.ssh.certificates.ed25519_certificate_builder import ED25519CertificateBuilder
from bless.ssh.certificates.ssh_certificate_builder import SSHCertificateType
from bless.ssh.certificates.ssh_certificate_builder_factory import get_ssh_certificate_builder
from tests.ssh.vectors import RSA_CA_PRIVATE_KEY, RSA_CA_PRIVATE_KEY_PASSWORD, \
Expand All @@ -18,10 +19,12 @@ def test_valid_rsa_request():
assert cert.startswith(SSHCertifiedKeyType.RSA)


def test_invalid_ed25519_request():
with pytest.raises(TypeError):
ca = get_ssh_certificate_authority(RSA_CA_PRIVATE_KEY, RSA_CA_PRIVATE_KEY_PASSWORD)
get_ssh_certificate_builder(ca, SSHCertificateType.USER, EXAMPLE_ED25519_PUBLIC_KEY)
def test_valid_ed25519_request():
ca = get_ssh_certificate_authority(RSA_CA_PRIVATE_KEY, RSA_CA_PRIVATE_KEY_PASSWORD)
cert_builder = get_ssh_certificate_builder(ca, SSHCertificateType.USER, EXAMPLE_ED25519_PUBLIC_KEY)
cert = cert_builder.get_cert_file()
assert isinstance(cert_builder, ED25519CertificateBuilder)
assert cert.startswith(SSHCertifiedKeyType.ED25519)


def test_invalid_key_request():
Expand Down
17 changes: 16 additions & 1 deletion tests/ssh/test_ssh_certificate_rsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@

from bless.ssh.certificate_authorities.rsa_certificate_authority import RSACertificateAuthority
from bless.ssh.certificates.rsa_certificate_builder import RSACertificateBuilder
from bless.ssh.certificates.ed25519_certificate_builder import ED25519CertificateBuilder
from bless.ssh.certificates.ssh_certificate_builder import SSHCertificateType
from bless.ssh.public_keys.rsa_public_key import RSAPublicKey
from bless.ssh.public_keys.ed25519_public_key import ED25519PublicKey
from tests.ssh.vectors import RSA_CA_PRIVATE_KEY, RSA_CA_PRIVATE_KEY_PASSWORD, \
EXAMPLE_RSA_PUBLIC_KEY, EXAMPLE_RSA_PUBLIC_KEY_NO_DESCRIPTION, RSA_USER_CERT_MINIMAL, \
RSA_USER_CERT_DEFAULTS, RSA_USER_CERT_DEFAULTS_NO_PUBLIC_KEY_COMMENT, \
RSA_USER_CERT_MANY_PRINCIPALS, RSA_HOST_CERT_MANY_PRINCIPALS, \
RSA_USER_CERT_FORCE_COMMAND_AND_SOURCE_ADDRESS, \
RSA_USER_CERT_FORCE_COMMAND_AND_SOURCE_ADDRESS_KEY_ID, RSA_HOST_CERT_MANY_PRINCIPALS_KEY_ID, \
RSA_USER_CERT_MANY_PRINCIPALS_KEY_ID, RSA_USER_CERT_DEFAULTS_NO_PUBLIC_KEY_COMMENT_KEY_ID, \
RSA_USER_CERT_DEFAULTS_KEY_ID, SSH_CERT_DEFAULT_EXTENSIONS, SSH_CERT_CUSTOM_EXTENSIONS
RSA_USER_CERT_DEFAULTS_KEY_ID, SSH_CERT_DEFAULT_EXTENSIONS, SSH_CERT_CUSTOM_EXTENSIONS, \
EXAMPLE_ED25519_PUBLIC_KEY, ED25519_USER_CERT_DEFAULTS, ED25519_USER_CERT_DEFAULTS_KEY_ID

USER1 = 'user1'

Expand Down Expand Up @@ -219,3 +222,15 @@ def test_nonce():
cert_builder2.set_nonce()

assert cert_builder.nonce != cert_builder2.nonce


def test_ed25519_user_cert_defaults():
ca = get_basic_rsa_ca()
pub_key = ED25519PublicKey(EXAMPLE_ED25519_PUBLIC_KEY)
cert_builder = ED25519CertificateBuilder(ca, SSHCertificateType.USER, pub_key)
cert_builder.set_nonce(
nonce=extract_nonce_from_cert(ED25519_USER_CERT_DEFAULTS))
cert_builder.set_key_id(ED25519_USER_CERT_DEFAULTS_KEY_ID)

cert = cert_builder.get_cert_file()
assert ED25519_USER_CERT_DEFAULTS == cert
4 changes: 4 additions & 0 deletions tests/ssh/vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@

SSH_CERT_CUSTOM_EXTENSIONS = base64.b64decode(
'AAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAA==')

# ssh-keygen -s test-rsa-ca -I "ssh-keygen -s test-rsa-ca -I '' test-ed25519-user-all-defaults.pub" test-ed25519-user-all-defaults.pub
ED25519_USER_CERT_DEFAULTS = '[email protected] AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAINa9ZmyR9YBRNfC464IJE2AlDa0xU02tVbY37AlRr79/AAAAIG7+cAbT4EFSPs87oS4kDYStQ0KL0xwHWqVSZ2bYHIApAAAAAAAAAAAAAAABAAAAQnNzaC1rZXlnZW4gLXMgdGVzdC1yc2EtY2EgLUkgJycgdGVzdC1lZDI1NTE5LXVzZXItYWxsLWRlZmF1bHRzLnB1YgAAAAAAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAAhcAAAAHc3NoLXJzYQAAAAMBAAEAAAIBAOI0JnxeJSdtUXtHu7x3MVVLdDN2iFCr8B8xCSGsdmJ+VdI2sBF0xc7l5/HZVyATgCBTt9dT7eG6zFCnQhPJUUB+uhUu9EeKwu3Pqw9mWnTXy/sa/R++yswFjU1Syxws+iBbiG9IG1BIqXY+eOuXaf+8kEFi877bjU4Nrl0U/KL2qpCJwhFh3vu5XBQ26ih/TcZVRaPyOTBVqOD0MNeVXs0JkVc/gd4mLHWgFvcIrTNmmKwR0HNSDPpYbLxol+3DbfaY9CE/sUetLA6OxO4EF38PQKPY+Ud2/yypc4uC/GT1VfEc4ALZVCZYC8Cut3hYb5ef3xdab7W4ikXIyU2vtPR/n1Ju/5nXVFX1Y0F5u0ShZkz8SI7/BLF2i4SIMiZhNTgqVj8mr2LpwSHB04m68d9GsPnD1mQQxlcfx7pbfOAjXmnTV3mQmn4TnW1KxKH0n7NJE1jvRy31n3Crs3aMJ6cuq6+gxbK4cg/X48Q16PnpuYzOiTtD5hEuu4RL4cg86Mi57DmchNwb1CsvxFJrueJB65J4efIDTqmuppDQVjkZOzH2URzRzGE2azdcQPgcV5aQQiZuiqeZ5xG9oEwB/2kNVu3hsM49ugJ9OBGHtlDoemC4YkQkJe0ejFJVc8uKOzGmXfjGcXKi21Aq5jGvEsDRb3DcuLEceOfXRpU/59OpAAACDwAAAAdzc2gtcnNhAAACACnir9y/PhoKvLNvs4fMkS24mrHyGxc24nTxaKJO9OBGr4PY3Glg90hKaZvC/cLN0wSAeIYzigp/PGm1PNIM342NqxMkIx7yUKrEbcIQaommn8kfThMIcLJo9QOpDoMAxOsfAtZrtWQKMMYM6s8hZKrb3OT8k0le/x4S2GttHMb9z006nZgyTUI4cniq+ZxwcL4l5/wzaXamQUsod/JRysEBZdLF88A50iCiSC+4NQUqquPBs76UmTpU+Lv3OEvVBwMil7Hxkzv8kqit2Xal0Ou9n/+CC1G9l/dpTO1TgaNtNERQT3rQOhkjqwmgN3wbh1sRkc1+zSenWsNrHkFBnVTJPxLwXbFeAvstDWDxTvNCpygsTfz/ejUnKfqZ1rAWfNRhzrSIz1D1+/GQbOdtM3xq3r6CVjVxE0KTLsdR1hyOd5SmszubE1UAkKWF7NRyHcgma/9hkOXc6a/4ylBcOj0yUFnjVq7Jb6C33ba0Ra6LnopZWUS7lr02dt7aYG/Qhd8OtJx7R+XiRYRnfsuJH+L18UxM34xqj9qlMPA5p1nUB2ZnklKyueLhrp0/thuWsdKCv4w66A8rOthbDtLip6TYtKwDDMBupq5ROoRHYXb6nYthHJYCX1QuDIzmoBjTlkWa7aVohggQWezYhGGo0owulURxkFNZBNi1Lc/aRuDs Test ED25519 User Key'
ED25519_USER_CERT_DEFAULTS_KEY_ID = 'ssh-keygen -s test-rsa-ca -I \'\' test-ed25519-user-all-defaults.pub'

0 comments on commit f1e2a30

Please sign in to comment.