Merge pull request #3130 from hosseinsh/improved-csr-support
Improved csr support and EC key_type support
This commit is contained in:
commit
e4ed2a14e7
|
@ -9,9 +9,10 @@ from datetime import timedelta
|
|||
|
||||
import arrow
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa, ec
|
||||
from flask import current_app
|
||||
from idna.core import InvalidCodepoint
|
||||
from lemur.common.utils import get_key_type_from_ec_curve
|
||||
from sqlalchemy import (
|
||||
event,
|
||||
Integer,
|
||||
|
@ -302,6 +303,8 @@ class Certificate(db.Model):
|
|||
return "RSA{key_size}".format(
|
||||
key_size=self.parsed_cert.public_key().key_size
|
||||
)
|
||||
elif isinstance(self.parsed_cert.public_key(), ec.EllipticCurvePublicKey):
|
||||
return get_key_type_from_ec_curve(self.parsed_cert.public_key().curve.name)
|
||||
|
||||
@property
|
||||
def validity_remaining(self):
|
||||
|
|
|
@ -148,6 +148,13 @@ class CertificateInputSchema(CertificateCreationSchema):
|
|||
data["extensions"]["subAltNames"]["names"] = []
|
||||
|
||||
data["extensions"]["subAltNames"]["names"] = csr_sans
|
||||
|
||||
common_name = cert_utils.get_cn_from_csr(data["csr"])
|
||||
if common_name:
|
||||
data["common_name"] = common_name
|
||||
key_type = cert_utils.get_key_type_from_csr(data["csr"])
|
||||
if key_type:
|
||||
data["key_type"] = key_type
|
||||
return missing.convert_validity_years(data)
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ Utils to parse certificate data.
|
|||
from cryptography import x509
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from marshmallow.exceptions import ValidationError
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa, ec
|
||||
from lemur.common.utils import get_key_type_from_ec_curve
|
||||
|
||||
|
||||
def get_sans_from_csr(data):
|
||||
|
@ -39,3 +41,45 @@ def get_sans_from_csr(data):
|
|||
pass
|
||||
|
||||
return sub_alt_names
|
||||
|
||||
|
||||
def get_cn_from_csr(data):
|
||||
"""
|
||||
Fetches common name (CN) from CSR.
|
||||
Works with any kind of SubjectAlternativeName
|
||||
:param data: PEM-encoded string with CSR
|
||||
:return: the common name
|
||||
"""
|
||||
try:
|
||||
request = x509.load_pem_x509_csr(data.encode("utf-8"), default_backend())
|
||||
except Exception:
|
||||
raise ValidationError("CSR presented is not valid.")
|
||||
|
||||
common_name = request.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
|
||||
return common_name[0].value
|
||||
|
||||
|
||||
def get_key_type_from_csr(data):
|
||||
"""
|
||||
Fetches key_type from CSR.
|
||||
Works with any kind of SubjectAlternativeName
|
||||
:param data: PEM-encoded string with CSR
|
||||
:return: key_type
|
||||
"""
|
||||
try:
|
||||
request = x509.load_pem_x509_csr(data.encode("utf-8"), default_backend())
|
||||
except Exception:
|
||||
raise ValidationError("CSR presented is not valid.")
|
||||
|
||||
try:
|
||||
if isinstance(request.public_key(), rsa.RSAPublicKey):
|
||||
return "RSA{key_size}".format(
|
||||
key_size=request.public_key().key_size
|
||||
)
|
||||
elif isinstance(request.public_key(), ec.EllipticCurvePublicKey):
|
||||
return get_key_type_from_ec_curve(request.public_key().curve.name)
|
||||
else:
|
||||
raise Exception("Unsupported key type")
|
||||
|
||||
except NotImplemented:
|
||||
raise NotImplemented()
|
||||
|
|
|
@ -114,6 +114,39 @@ def get_authority_key(body):
|
|||
return authority_key.hex()
|
||||
|
||||
|
||||
def get_key_type_from_ec_curve(curve_name):
|
||||
"""
|
||||
Give an EC curve name, return the matching key_type.
|
||||
|
||||
:param: curve_name
|
||||
:return: key_type
|
||||
"""
|
||||
|
||||
_CURVE_TYPES = {
|
||||
ec.SECP192R1().name: "ECCPRIME192V1",
|
||||
ec.SECP256R1().name: "ECCPRIME256V1",
|
||||
ec.SECP224R1().name: "ECCSECP224R1",
|
||||
ec.SECP384R1().name: "ECCSECP384R1",
|
||||
ec.SECP521R1().name: "ECCSECP521R1",
|
||||
ec.SECP256K1().name: "ECCSECP256K1",
|
||||
ec.SECT163K1().name: "ECCSECT163K1",
|
||||
ec.SECT233K1().name: "ECCSECT233K1",
|
||||
ec.SECT283K1().name: "ECCSECT283K1",
|
||||
ec.SECT409K1().name: "ECCSECT409K1",
|
||||
ec.SECT571K1().name: "ECCSECT571K1",
|
||||
ec.SECT163R2().name: "ECCSECT163R2",
|
||||
ec.SECT233R1().name: "ECCSECT233R1",
|
||||
ec.SECT283R1().name: "ECCSECT283R1",
|
||||
ec.SECT409R1().name: "ECCSECT409R1",
|
||||
ec.SECT571R1().name: "ECCSECT571R2",
|
||||
}
|
||||
|
||||
if curve_name in _CURVE_TYPES.keys():
|
||||
return _CURVE_TYPES[curve_name]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def generate_private_key(key_type):
|
||||
"""
|
||||
Generates a new private key based on key_type.
|
||||
|
@ -128,11 +161,11 @@ def generate_private_key(key_type):
|
|||
"""
|
||||
|
||||
_CURVE_TYPES = {
|
||||
"ECCPRIME192V1": ec.SECP192R1(),
|
||||
"ECCPRIME256V1": ec.SECP256R1(),
|
||||
"ECCSECP192R1": ec.SECP192R1(),
|
||||
"ECCPRIME192V1": ec.SECP192R1(), # duplicate
|
||||
"ECCPRIME256V1": ec.SECP256R1(), # duplicate
|
||||
"ECCSECP192R1": ec.SECP192R1(), # duplicate
|
||||
"ECCSECP224R1": ec.SECP224R1(),
|
||||
"ECCSECP256R1": ec.SECP256R1(),
|
||||
"ECCSECP256R1": ec.SECP256R1(), # duplicate
|
||||
"ECCSECP384R1": ec.SECP384R1(),
|
||||
"ECCSECP521R1": ec.SECP521R1(),
|
||||
"ECCSECP256K1": ec.SECP256K1(),
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
name="certificate signing request"
|
||||
ng-model="certificate.csr"
|
||||
placeholder="PEM encoded string..." class="form-control"
|
||||
ng-pattern="/^-----BEGIN CERTIFICATE REQUEST-----/"></textarea>
|
||||
ng-pattern="/(^-----BEGIN CERTIFICATE REQUEST-----[\S\s]*-----END CERTIFICATE REQUEST-----)|(^-----BEGIN NEW CERTIFICATE REQUEST-----[\S\s]*-----END NEW CERTIFICATE REQUEST-----)/"></textarea>
|
||||
|
||||
<p ng-show="trackingForm.csr.$invalid && !trackingForm.csr.$pristine"
|
||||
class="help-block">Enter a valid certificate signing request.</p>
|
||||
|
|
|
@ -11,6 +11,12 @@ from lemur.tests.vectors import (
|
|||
)
|
||||
|
||||
|
||||
def test_get_key_type_from_ec_curve():
|
||||
from lemur.common.utils import get_key_type_from_ec_curve
|
||||
|
||||
assert get_key_type_from_ec_curve("secp256r1") == "ECCPRIME256V1"
|
||||
|
||||
|
||||
def test_generate_private_key():
|
||||
from lemur.common.utils import generate_private_key
|
||||
|
||||
|
|
Loading…
Reference in New Issue