Skip to content

Commit

Permalink
Added support for extended key usage, fixes #3
Browse files Browse the repository at this point in the history
  • Loading branch information
bentoi committed Sep 2, 2019
1 parent bf53036 commit b13d32c
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 9 deletions.
12 changes: 8 additions & 4 deletions IceCertUtils/CertificateUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,11 @@ def parse(str):
return DistinguishedName(**args)

class Certificate:
def __init__(self, parent, alias, dn=None, altName=None):
def __init__(self, parent, alias, dn=None, altName=None, extendedKeyUsage=None):
self.parent = parent
self.dn = dn
self.altName = altName or {}
self.extendedKeyUsage = extendedKeyUsage
self.alias = alias
self.pem = None

Expand Down Expand Up @@ -251,6 +252,9 @@ def getAlternativeName(self):
items.append("{0}:{1}".format(k, v))
return ",".join(items) if len(items) > 0 else None

def getExtendedKeyUsage(self):
return self.extendedKeyUsage

defaultDN = DistinguishedName("ZeroC IceCertUtils CA", "Ice", "ZeroC, Inc.", "Jupiter", "Florida", "US",
emailAddress="[email protected]")

Expand Down Expand Up @@ -303,7 +307,7 @@ def __init__(self, home=None, debug=None, validity=None, keysize=None, keyalg=No
self.parent = parent;

# Certificate generate parameters
self.validity = validity or (parent.validity if parent else 1825)
self.validity = validity or (parent.validity if parent else 825)
self.keysize = keysize or (parent.keysize if parent else 2048)
self.keyalg = keyalg or (parent.keyalg if parent else "rsa")
self.sigalg = sigalg or (parent.sigalg if parent else "sha256")
Expand Down Expand Up @@ -342,7 +346,7 @@ def rmpass():
def __str__(self):
return str(self.cacert)

def create(self, alias, serial=None, validity=None, *args, **kargs):
def create(self, alias, serial=None, validity=None, extendedKeyUsage=None, *args, **kargs):
cert = self.get(alias)
if cert:
cert.destroy() # Remove previous certificate
Expand All @@ -351,7 +355,7 @@ def create(self, alias, serial=None, validity=None, *args, **kargs):
if len(args) > 0 or len(kargs) > 0:
raise TypeError("unexpected arguments")

cert = self._createChild(alias, dn, altName)
cert = self._createChild(alias, dn, altName, extendedKeyUsage)
self._generateChild(cert, serial, validity)
self.certs[alias] = cert
return cert
Expand Down
3 changes: 2 additions & 1 deletion IceCertUtils/IceCaUtil.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ def create(script, factory):
"common name is specified, the alias is used as the common name.\n"
"\nOptions:\n"
"--ip Optional IP subject alternative name field\n"
"--dns Optional DNS subject alternative name field\n")
"--dns Optional DNS subject alternative name field\n"
"--eku Optional Extended Key Usage\n")

alias = args[0]
commonName = len(args) == 2 and args[1] or alias
Expand Down
4 changes: 3 additions & 1 deletion IceCertUtils/KeyToolCertificateUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def _createChild(self, *args):
def _generateChild(self, cert, serial, validity):
subAltName = cert.getAlternativeName()
issuerAltName = self.cacert.getAlternativeName()
extendedKeyUsage = cert.getExtendedKeyUsage()

# Generate a certificate/key pair
cert.keyTool("genkeypair")
Expand All @@ -142,7 +143,8 @@ def _generateChild(self, cert, serial, validity):

ext = "-ext ku:c=dig,keyEnc" + \
((" -ext san=" + subAltName) if subAltName else "") + \
((" -ext ian=" + issuerAltName) if issuerAltName else "")
((" -ext ian=" + issuerAltName) if issuerAltName else "") + \
((" -ext eku=" + extendedKeyUsage) if extendedKeyUsage else "")

# Sign the certificate with the CA
if validity is None or validity > 0:
Expand Down
6 changes: 5 additions & 1 deletion IceCertUtils/OpenSSLCertificateUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ def _generateChild(self, cert, serial, validity):
altName = (("\nsubjectAltName = " + subAltName) if subAltName else "") + \
(("\nissuerAltName = " + issuerAltName) if issuerAltName else "")

extendedKeyUsage = cert.getExtendedKeyUsage()
extendedKeyUsage = ("extendedKeyUsage = " + extendedKeyUsage) if extendedKeyUsage else ""

# Generate a certificate request
req = cert.openSSL("req", config=
"""
Expand All @@ -184,8 +187,9 @@ def _generateChild(self, cert, serial, validity):
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
{extendedKeyUsage}
{altName}
""".format(altName=altName))
""".format(altName=altName, extendedKeyUsage=extendedKeyUsage))

return cert

Expand Down
8 changes: 6 additions & 2 deletions IceCertUtils/PyOpenSSLCertificateUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,12 @@ def _generateChild(self, cert, serial, validity):
if subAltName:
extensions.append(crypto.X509Extension(b('subjectAltName'), False, b(subAltName)))
if self.cacert.getAlternativeName():
extensions.append(crypto.X509Extension(b('issuerAltName'), False, b("issuer:copy"),
issuer=self.cacert.x509))
extensions.append(crypto.X509Extension(b('issuerAltName'), False, b("issuer:copy"),issuer=self.cacert.x509))

extendedKeyUsage = cert.getExtendedKeyUsage()
if extendedKeyUsage:
extensions.append(crypto.X509Extension(b('extendedKeyUsage'),False,b(extendedKeyUsage)))

x509.add_extensions(extensions)

x509.sign(self.cacert.pkey, self.sigalg)
Expand Down
20 changes: 20 additions & 0 deletions tests/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ def test_altName(self):

factory.destroy()

def test_extendedKeyUsage(self):
Factory = vars(IceCertUtils)[self.factory]
dn = IceCertUtils.DistinguishedName("CN")
factory = Factory(dn=dn)

cert = factory.create("cert", cn = "CERT", extendedKeyUsage="serverAuth")
txt = cert.toText()
self.assertTrue(txt.find("serverAuth") > 0 or txt.find("TLS Web Server Authentication") > 0)

cert = factory.create("cert", cn = "CERT", extendedKeyUsage="clientAuth")
txt = cert.toText()
self.assertTrue(txt.find("clientAuth") > 0 or txt.find("TLS Web Client Authentication") > 0)

cert = factory.create("cert", cn = "CERT", extendedKeyUsage="serverAuth,clientAuth")
txt = cert.toText()
self.assertTrue(txt.find("serverAuth") > 0 or txt.find("TLS Web Server Authentication") > 0)
self.assertTrue(txt.find("clientAuth") > 0 or txt.find("TLS Web Client Authentication") > 0)

factory.destroy()

def test_persistent(self):

if os.path.exists(self.home):
Expand Down

0 comments on commit b13d32c

Please sign in to comment.