Browse Source

Initial commit

Mike Richardson 5 years ago
commit
25f02d36b9
4 changed files with 324 additions and 0 deletions
  1. 2 0
      .gitignore
  2. 203 0
      cert_gen.py
  3. 40 0
      certs.py
  4. 79 0
      cli.py

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+*~
+*.pyc

+ 203 - 0
cert_gen.py

@@ -0,0 +1,203 @@
+#import cryptography
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import serialization
+from cryptography.hazmat.primitives.asymmetric import rsa
+
+from cryptography import x509
+from cryptography.x509.oid import NameOID
+from cryptography.hazmat.primitives import hashes
+
+import datetime
+
+c=u"GB"
+st=u"England"
+l=u"Manchester"
+o=u'Jisc'
+ou=u''
+servername = u"jadzia.mcc.ac.uk"
+crldp=u'http://somewhere.example.com/awebserver'
+passphrase=b'somethingsecure'
+
+
+def gen_cakey():
+  key = rsa.generate_private_key(
+     public_exponent=65537,
+     key_size=2048,
+     backend=default_backend()
+  )
+  return key
+
+
+
+def write_key_encrypted(filename,key,passphrase):
+  with open(filename, "wb") as f:
+     f.write(key.private_bytes(
+     encoding=serialization.Encoding.PEM,
+     format=serialization.PrivateFormat.TraditionalOpenSSL,
+     encryption_algorithm=serialization.BestAvailableEncryption(passphrase),
+  ))
+
+def output_key_encrypted(key,passphrase):
+     return key.private_bytes(
+     encoding=serialization.Encoding.PEM,
+     format=serialization.PrivateFormat.TraditionalOpenSSL,
+     encryption_algorithm=serialization.BestAvailableEncryption(passphrase),
+  )
+
+def write_key(filename,key):
+  with open(filename, "wb") as f:
+     f.write(key.private_bytes(
+     encoding=serialization.Encoding.PEM,
+     format=serialization.PrivateFormat.TraditionalOpenSSL,
+     encryption_algorithm=serialization.NoEncryption(),
+  ))
+
+def output_key(key):
+     return key.private_bytes(
+     encoding=serialization.Encoding.PEM,
+     format=serialization.PrivateFormat.TraditionalOpenSSL,
+     encryption_algorithm=serialization.NoEncryption(),
+  )
+
+
+
+def build_name(c,st,l,o,ou,cn):
+  array = []
+  if (c):
+    array.append(x509.NameAttribute(NameOID.COUNTRY_NAME,c))
+  if (st): 
+    array.append(x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME,st))
+  if (l):
+    array.append(x509.NameAttribute(NameOID.LOCALITY_NAME,l))
+  if (o):
+    array.append(x509.NameAttribute(NameOID.ORGANIZATION_NAME,o))
+  if (ou): 
+    array.append(x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME,ou))
+  if (cn):
+    array.append(x509.NameAttribute(NameOID.COMMON_NAME,cn))
+
+  return x509.Name(array)
+
+
+def build_rootca(key,subject,issuer,duration):
+
+  cert = x509.CertificateBuilder().subject_name(
+    subject
+  ).issuer_name(
+    issuer
+  ).public_key(
+    key.public_key() 
+  ).serial_number(
+    x509.random_serial_number()
+  ).not_valid_before(
+    datetime.datetime.utcnow()
+  ).not_valid_after(
+    datetime.datetime.utcnow() + datetime.timedelta(days=duration)
+  ).add_extension(
+#    x509.AuthorityKeyIdentifier(public_key,[x509.DirectoryName(caissuer)],caserial),
+    x509.AuthorityKeyIdentifier.from_issuer_public_key(key.public_key()),
+    critical=False,  
+  ).add_extension(
+    x509.SubjectKeyIdentifier.from_public_key(key.public_key()),
+    critical=False,
+  ).add_extension(
+    x509.BasicConstraints(True,None),
+    critical=True,
+  ).sign(key, hashes.SHA256(), default_backend())
+
+  return cert
+
+def build_servercert(key,root,csr,name,crldp,duration):
+
+  builder = x509.CertificateBuilder().subject_name(
+    csr.subject
+  ).issuer_name(
+    root.issuer
+  ).public_key(
+    csr.public_key()
+  ).serial_number(
+    x509.random_serial_number()
+  ).not_valid_before(
+    datetime.datetime.utcnow()
+  ).not_valid_after(
+    datetime.datetime.utcnow() + datetime.timedelta(days=duration)
+  ).add_extension(
+    x509.KeyUsage(True,True,True,False,False,False,False,False,False),
+    critical=True,
+  ).add_extension(
+    x509.SubjectAlternativeName([x509.DNSName(name)]),
+    critical=False,
+  ).add_extension(
+    x509.BasicConstraints(False,None),
+    critical=True,
+  ).add_extension(
+    x509.ExtendedKeyUsage([x509.ExtendedKeyUsageOID.SERVER_AUTH]),
+    critical=False,
+  ).add_extension(
+    x509.AuthorityKeyIdentifier.from_issuer_public_key(root.public_key()),
+    critical=False,
+  ).add_extension(
+    x509.SubjectKeyIdentifier.from_public_key(key.public_key()),
+    critical=False,
+  )
+  
+  if ( crldp ):
+    builder = builder.add_extension(
+      x509.CRLDistributionPoints(
+         [x509.DistributionPoint(
+            [x509.UniformResourceIdentifier(crldp)],
+            None,
+            None,
+            None
+         )
+      ]
+      ),
+      critical=False,
+    )
+  
+  cert = builder.sign(key, hashes.SHA256(), default_backend())
+
+  return cert
+
+def build_csr(key,subject,name):
+  csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name(
+    subject
+  )).add_extension(
+    x509.SubjectAlternativeName([
+        x509.DNSName(name),
+    ]),
+    critical=False,
+# Sign the CSR with our private key.
+  ).sign(key, hashes.SHA256(), default_backend())
+  
+  return csr
+
+def build_crl(key,issuer,duration):
+  builder = x509.CertificateRevocationListBuilder()
+  builder = builder.issuer_name(issuer)
+
+  builder = builder.last_update(datetime.datetime.today())
+  builder = builder.next_update(datetime.datetime.today() + datetime.timedelta(days=duration))
+    
+  revoked_cert = x509.RevokedCertificateBuilder().serial_number(
+    x509.random_serial_number()
+  ).revocation_date(
+    datetime.datetime.today()
+  ).build(default_backend())
+
+#  builder = builder.add_revoked_certificate(revoked_cert)
+
+  crl = builder.sign(
+    private_key=key, algorithm=hashes.SHA256(),
+    backend=default_backend()
+  )
+
+  return crl
+    
+def write_cert(filename,cert):
+  with open(filename, "wb") as f:
+    f.write(cert.public_bytes(serialization.Encoding.PEM))     
+
+def output_cert(cert):
+    return cert.public_bytes(serialization.Encoding.PEM)
+

+ 40 - 0
certs.py

@@ -0,0 +1,40 @@
+from cert_gen import gen_cakey,build_name,build_csr,build_servercert,build_rootca,output_cert,output_key_encrypted,build_crl
+
+def gencerts(c,st,l,o,ou,cn,crldp,passphrase):
+## Start
+## Build Root CA
+
+#write_key_encrypted('rootca-key.pem',cakey,passphrase)
+
+  casubject = caissuer = build_name(c,st,l,o,ou,u'Root CA')
+
+  cakey = gen_cakey()
+
+  cacert = build_rootca(cakey,casubject,caissuer,36500)
+
+#write_cert('rootca.pem',cacert)
+
+## Build CSR
+
+  csrkey = gen_cakey()
+#write_key('csr-key.pem',csrkey)
+
+  csrsubject = build_name(c,st,l,o,ou,cn)
+
+  csrcert = build_csr(csrkey,csrsubject,cn)
+
+## Build Server Cert
+
+#servkey = key()
+#write_key("server-key.pem",servkey)
+
+#serversubject = build_name(c,st,l,o,ou,servername)
+
+  servercert = build_servercert(cakey,cacert,csrcert,cn,crldp,36500)
+
+#write_cert('server.pem',servercert)
+
+  crlcert = build_crl(cakey,caissuer,36500)
+
+  return csrsubject,output_cert(cacert),output_key_encrypted(cakey,passphrase),output_key_encrypted(csrkey,passphrase),output_cert(servercert),output_cert(csrcert),output_cert(crlcert)
+  

+ 79 - 0
cli.py

@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+from certs import gencerts
+import os,sys,getopt
+
+## def gencerts(c,st,l,o,ou,cn,crldp,passphrase):
+
+def main(argv):
+  c=u'UK'
+  st=u'England'
+  l=u'Manchester'
+  o=u'Jisc'
+  ou=u'Govroam'
+  cn=u'jadzia.mcc.ac.uk'
+  crldp=u'http://jadzia.mcc.ac.uk/crldp'
+  passphrase=b'something'
+
+  try:
+    opts, args = getopt.getopt(argv,"c:s:l:o:u:n:r:p:d:")
+  except getopt.GetoptError:
+    print "cli.py -c <County> -s <State> -l <Location> -o <Organisation> -ou <Organisation Unit> -n <CN> -r <CRLDP> -p <password> -d <Output Directory>"
+    sys.exit(2)
+  for opt, arg in opts:
+    if opt == '-c':
+      c=unicode(arg, "utf-8")
+    if opt == '-s':
+      st=unicode(arg, "utf-8")
+    if opt == '-l':
+      l=unicode(arg, "utf-8")
+    if opt == '-o':
+      o=unicode(arg, "utf-8")
+    if opt == '-u':
+      ou=unicode(arg, "utf-8")
+    if opt == '-n':
+      cn=unicode(arg, "utf-8")
+    if opt == '-r':
+      crldp=unicode(arg, "utf-8")
+    if opt == '-p':
+      password=unicode(arg, "utf-8")
+    if opt == '-d':
+      directory=unicode(arg, "utf-8")
+
+  if not os.path.exists(directory):
+    os.makedirs(directory)
+    
+## return csrsubject,output_cert(cacert),output_key_encrypted(cakey,passphrase),output_key_
+## encrypted(csrkey,passphrase),output_cert(servercert),output_cert(csrcert),output_cert(crlc
+## ert)
+
+  csrsubject, cacert, cakey_enc, csrkey_enc, servercert, csrcert, crlcert = gencerts(c,st,l,o,ou,cn,crldp,passphrase)
+
+  with open (directory + '/rootca.pem','w') as f:
+    f.write(cacert)
+    f.close
+  
+  with open (directory + '/root-key.pem','w') as f:
+    f.write(cakey_enc)
+    f.close
+  
+  with open (directory + '/csrkey.pem','w') as f:
+    f.write(csrkey_enc)
+    f.close
+  
+  with open (directory + '/server-cert.pem','w') as f:
+    f.write(servercert)
+    f.close
+  
+  with open (directory + '/server-key.pem','w') as f:
+    f.write(csrcert)
+    f.close
+  
+  with open (directory + '/list.crl','w') as f:
+    f.write(crlcert)
+    f.close
+  
+if __name__ == "__main__":
+  main(sys.argv[1:])
+    
+