diff options
author | Rob Austein <sra@hactrn.net> | 2014-02-20 23:03:11 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2014-02-20 23:03:11 +0000 |
commit | 401bbea99c1ba43ae0987b6346c65293a8efafa0 (patch) | |
tree | bde4f7e451ab6795b211631cb2e62db1ac07d481 | |
parent | 4c537cad182aa3f4f5aea9322759cea88e2210bc (diff) |
Whack RSA-specific code to a more general API using PrivateKey and
PublicKey classes, with RSA and ECDSA as subclasses extending
PrivateKey. Revised API not necessarily in final form yet, but good
enough for smoketest to generate ECDSA keys for testing router certs.
svn path=/branches/tk671/; revision=5679
-rw-r--r-- | rpkid/rpki/irdb/models.py | 2 | ||||
-rw-r--r-- | rpkid/rpki/rootd.py | 2 | ||||
-rw-r--r-- | rpkid/rpki/rpkid.py | 12 | ||||
-rw-r--r-- | rpkid/rpki/x509.py | 124 | ||||
-rw-r--r-- | rpkid/tests/smoketest.py | 14 | ||||
-rw-r--r-- | rpkid/tests/yamlconf.py | 4 | ||||
-rw-r--r-- | rpkid/tests/yamltest.py | 4 |
7 files changed, 100 insertions, 62 deletions
diff --git a/rpkid/rpki/irdb/models.py b/rpkid/rpki/irdb/models.py index 8e492409..6772b542 100644 --- a/rpkid/rpki/irdb/models.py +++ b/rpkid/rpki/irdb/models.py @@ -401,7 +401,7 @@ class EECertificate(Certificate): self.private_key = rpki.x509.RSA.generate(quiet = True) self.certificate = self.issuer.certify( subject_name = self.subject_name, - subject_key = self.private_key.get_RSApublic(), + subject_key = self.private_key.get_public(), validity_interval = ee_certificate_lifetime, is_ca = False) diff --git a/rpkid/rpki/rootd.py b/rpkid/rpki/rootd.py index e0c59726..43e84873 100644 --- a/rpkid/rpki/rootd.py +++ b/rpkid/rpki/rootd.py @@ -229,7 +229,7 @@ class main(object): manifest_keypair = rpki.x509.RSA.generate() manifest_cert = self.rpki_root_cert.issue( keypair = self.rpki_root_key, - subject_key = manifest_keypair.get_RSApublic(), + subject_key = manifest_keypair.get_public(), serial = self.serial_number, sia = (None, None, self.rpki_base_uri + self.rpki_root_manifest), aia = self.rpki_root_cert_uri, diff --git a/rpkid/rpki/rpkid.py b/rpkid/rpki/rpkid.py index 69d7a242..0b564b57 100644 --- a/rpkid/rpki/rpkid.py +++ b/rpkid/rpki/rpkid.py @@ -766,10 +766,10 @@ class ca_detail_obj(rpki.sql.sql_persistent): "ca_detail", "ca_detail_id", ("private_key_id", rpki.x509.RSA), - ("public_key", rpki.x509.RSApublic), + ("public_key", rpki.x509.PublicKey), ("latest_ca_cert", rpki.x509.X509), ("manifest_private_key_id", rpki.x509.RSA), - ("manifest_public_key", rpki.x509.RSApublic), + ("manifest_public_key", rpki.x509.PublicKey), ("latest_manifest_cert", rpki.x509.X509), ("latest_manifest", rpki.x509.SignedManifest), ("latest_crl", rpki.x509.CRL), @@ -1116,10 +1116,10 @@ class ca_detail_obj(rpki.sql.sql_persistent): self.state = "pending" self.private_key_id = rpki.x509.RSA.generate() - self.public_key = self.private_key_id.get_RSApublic() + self.public_key = self.private_key_id.get_public() self.manifest_private_key_id = rpki.x509.RSA.generate() - self.manifest_public_key = self.manifest_private_key_id.get_RSApublic() + self.manifest_public_key = self.manifest_private_key_id.get_public() self.sql_store() return self @@ -1875,7 +1875,7 @@ class roa_obj(rpki.sql.sql_persistent): self.cert = ca_detail.issue_ee( ca = ca, resources = resources, - subject_key = keypair.get_RSApublic(), + subject_key = keypair.get_public(), sia = (None, None, self.uri_from_key(keypair))) self.roa = rpki.x509.ROA.build(self.asn, self.ipv4, self.ipv6, keypair, (self.cert,)) self.published = rpki.sundial.now() @@ -2070,7 +2070,7 @@ class ghostbuster_obj(rpki.sql.sql_persistent): self.cert = ca_detail.issue_ee( ca = ca, resources = resources, - subject_key = keypair.get_RSApublic(), + subject_key = keypair.get_public(), sia = (None, None, self.uri_from_key(keypair))) self.ghostbuster = rpki.x509.Ghostbuster.build(self.vcard, keypair, (self.cert,)) self.published = rpki.sundial.now() diff --git a/rpkid/rpki/x509.py b/rpkid/rpki/x509.py index 15adf12b..c69090e2 100644 --- a/rpkid/rpki/x509.py +++ b/rpkid/rpki/x509.py @@ -312,14 +312,26 @@ class DER_object(object): def get_DER(self): """ Get the DER value of this object. - - Subclasses will almost certainly override this method. + Subclasses may need to override this method. """ self.check() if self.DER: return self.DER + if self.POW: + self.DER = self.POW.derWrite() + return self.get_DER() raise rpki.exceptions.DERObjectConversionError("No conversion path to DER available") + def get_POW(self): + """ + Get the rpki.POW value of this object. + Subclasses may need to override this method. + """ + self.check() + if not self.POW: # pylint: disable=E0203 + self.POW = self.POW_class.derRead(self.get_DER()) + return self.POW + def get_Base64(self): """ Get the Base64 encoding of the DER value of this object. @@ -536,27 +548,6 @@ class X509(DER_object): POW_class = rpki.POW.X509 - def get_DER(self): - """ - Get the DER value of this certificate. - """ - self.check() - if self.DER: - return self.DER - if self.POW: - self.DER = self.POW.derWrite() - return self.get_DER() - raise rpki.exceptions.DERObjectConversionError("No conversion path to DER available") - - def get_POW(self): - """ - Get the rpki.POW value of this certificate. - """ - self.check() - if not self.POW: # pylint: disable=E0203 - self.POW = rpki.POW.X509.derRead(self.get_DER()) - return self.POW - def getIssuer(self): """ Get the issuer of this certificate. @@ -591,7 +582,7 @@ class X509(DER_object): """ Extract the public key from this certificate. """ - return RSApublic(POW = self.get_POW().getPublicKey()) + return PublicKey(POW = self.get_POW().getPublicKey()) def get_SKI(self): """ @@ -757,7 +748,7 @@ class X509(DER_object): keypair = keypair, issuer_name = subject_name, subject_name = subject_name, - subject_key = keypair.get_RSApublic(), + subject_key = keypair.get_public(), serial = serial, now = now, notAfter = notAfter, @@ -769,7 +760,7 @@ class X509(DER_object): """ Issue a normal BPKI certificate. """ - assert keypair.get_RSApublic() == self.getPublicKey() + assert keypair.get_public() == self.getPublicKey() return self._bpki_certify( keypair = keypair, issuer_name = self.getSubject(), @@ -793,7 +784,7 @@ class X509(DER_object): if now is None: now = rpki.sundial.now() - issuer_key = keypair.get_RSApublic() + issuer_key = keypair.get_public() assert (issuer_key == subject_key) == (issuer_name == subject_name) assert is_ca or issuer_name != subject_name @@ -890,7 +881,7 @@ class PKCS10(DER_object): """ Extract the public key from this certification request. """ - return RSApublic(POW = self.get_POW().getPublicKey()) + return PublicKey(POW = self.get_POW().getPublicKey()) def get_SKI(self): """ @@ -1129,9 +1120,10 @@ class insecure_debug_only_rsa_key_generator(object): self.keyno += 1 return v -class RSA(DER_object): + +class PrivateKey(DER_object): """ - Class to hold an RSA key pair. + Class to hold a Public/Private key pair. """ POW_class = rpki.POW.Asymmetric @@ -1170,18 +1162,6 @@ class RSA(DER_object): assert self.empty() self.POW = self.POW_class.pemReadPrivate(pem) - @classmethod - def generate(cls, keylength = 2048, quiet = False): - """ - Generate a new keypair. - """ - if not quiet: - rpki.log.debug("Generating new %d-bit RSA key" % keylength) - if generate_insecure_debug_only_rsa_key is not None: - return cls(POW = generate_insecure_debug_only_rsa_key()) - else: - return cls(POW = rpki.POW.Asymmetric.generateRSA(keylength)) - def get_public_DER(self): """ Get the DER encoding of the public key from this keypair. @@ -1194,15 +1174,15 @@ class RSA(DER_object): """ return self.get_POW().calculateSKI() - def get_RSApublic(self): + def get_public(self): """ - Convert the public key of this keypair into a RSApublic object. + Convert the public key of this keypair into a PublicKey object. """ - return RSApublic(DER = self.get_public_DER()) + return PublicKey(DER = self.get_public_DER()) -class RSApublic(DER_object): +class PublicKey(DER_object): """ - Class to hold an RSA public key. + Class to hold a public key. """ POW_class = rpki.POW.Asymmetric @@ -1247,6 +1227,56 @@ class RSApublic(DER_object): """ return self.get_POW().calculateSKI() +class KeyParams(DER_object): + """ + Wrapper for OpenSSL's asymmetric key parameter classes. + """ + + POW_class = rpki.POW.AsymmetricParams + + @classmethod + def generateEC(cls, curve = rpki.POW.EC_P256_CURVE): + return cls(POW = rpki.POW.AsymmetricParams.generateEC(curve = curve)) + +class RSA(PrivateKey): + """ + Class to hold an RSA key pair. + """ + + @classmethod + def generate(cls, keylength = 2048, quiet = False): + """ + Generate a new keypair. + """ + if not quiet: + rpki.log.debug("Generating new %d-bit RSA key" % keylength) + if generate_insecure_debug_only_rsa_key is not None: + return cls(POW = generate_insecure_debug_only_rsa_key()) + else: + return cls(POW = rpki.POW.Asymmetric.generateRSA(keylength)) + +class ECDSA(PrivateKey): + """ + Class to hold an ECDSA key pair. + """ + + @classmethod + def generate(cls, params = None, quiet = False): + """ + Generate a new keypair. + """ + + if params is None: + if not quiet: + rpki.log.debug("Generating new ECDSA key parameters") + params = KeyParams.generateEC() + + assert isinstance(params, KeyParams) + + if not quiet: + rpki.log.debug("Generating new ECDSA key") + + return cls(POW = rpki.POW.Asymmetric.generateFromParams(params.get_POW())) class CMS_object(DER_object): """ diff --git a/rpkid/tests/smoketest.py b/rpkid/tests/smoketest.py index 7f284550..5512b5bc 100644 --- a/rpkid/tests/smoketest.py +++ b/rpkid/tests/smoketest.py @@ -134,6 +134,8 @@ pubd_pubd_cert = None pubd_last_cms_time = None +ecdsa_params = None + class CantRekeyYAMLLeaf(Exception): """ Can't rekey YAML leaf. @@ -380,12 +382,18 @@ class router_cert(object): Representation for a router_cert object. """ + _ecparams = None + + @classmethod + def ecparams(cls): + if cls._ecparams is None: + cls._ecparams = rpki.x509.KeyParams.generateEC() + return cls._ecparams + def __init__(self, asn, router_id): self.asn = rpki.resource_set.resource_set_as("".join(str(asn).split())) self.router_id = router_id - - rpki.log.warn("Code to generate ECDSA keys not written yet, generating RSA as hack for testing") - self.keypair = rpki.x509.RSA.generate() + self.keypair = rpki.x509.ECDSA.generate(self.ecparams()) self.pkcs10 = rpki.x509.PKCS10.create( keypair = self.keypair, cn = "ROUTER-%d" % self.asn[0].min, diff --git a/rpkid/tests/yamlconf.py b/rpkid/tests/yamlconf.py index 81698fbf..3c71d3cd 100644 --- a/rpkid/tests/yamlconf.py +++ b/rpkid/tests/yamlconf.py @@ -467,7 +467,7 @@ class allocation(object): root_cert = rpki.x509.X509.self_certify( keypair = root_key, - subject_key = root_key.get_RSApublic(), + subject_key = root_key.get_public(), serial = 1, sia = root_sia, notAfter = rpki.sundial.now() + rpki.sundial.timedelta(days = 365), @@ -481,7 +481,7 @@ class allocation(object): with open(cleanpath(test_dir, "root.tal"), "w") as f: f.write("rsync://%s/root/root.cer\n\n%s" % ( - self.rsync_server, root_key.get_RSApublic().get_Base64())) + self.rsync_server, root_key.get_public().get_Base64())) def mkdir(self, *path): path = self.path(*path) diff --git a/rpkid/tests/yamltest.py b/rpkid/tests/yamltest.py index 08da81f3..9131a595 100644 --- a/rpkid/tests/yamltest.py +++ b/rpkid/tests/yamltest.py @@ -553,7 +553,7 @@ def create_root_certificate(db_root): root_cert = rpki.x509.X509.self_certify( keypair = root_key, - subject_key = root_key.get_RSApublic(), + subject_key = root_key.get_public(), serial = 1, sia = root_sia, notAfter = rpki.sundial.now() + rpki.sundial.timedelta(days = 365), @@ -569,7 +569,7 @@ def create_root_certificate(db_root): f = open(os.path.join(test_dir, "root.tal"), "w") f.write("rsync://localhost:%d/root/root.cer\n\n" % db_root.pubd.rsync_port) - f.write(root_key.get_RSApublic().get_Base64()) + f.write(root_key.get_public().get_Base64()) f.close() |