def _create(self, hostname='localhost'): # Make the RSA key self.rsakey = RSA.gen_key(2048, m2.RSA_F4) if self.secure: # Save the key, AES256-CBC encrypted self.rsakey.save_key(self.keyfile, 'aes_256_cbc') else: # Save the key unencrypted. self.rsakey.save_key(self.keyfile, None, callback=m2util.no_passphrase_callback) # Make the public key pkey = EVP.PKey() pkey.assign_rsa(self.rsakey, 0) # Generate the certificate self.cert = X509.X509() self.cert.set_serial_number(long(bttime())) self.cert.set_version(0x2) self.cert.set_pubkey(pkey) # Set the name on the certificate name = X509.X509_Name() name.CN = hostname self.cert.set_subject(name) self.cert.set_issuer(name) # Set the period of time the cert is valid for (5 years from issue) notBefore = m2.x509_get_not_before(self.cert.x509) notAfter = m2.x509_get_not_after(self.cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, 60*60*24*365*5) # Sign the certificate self.cert.sign(pkey, 'sha1') # Save it self.cert.save_pem(self.certfile)
def generate_ssl_credential(self, hostname, lifetime=24 * 60 * 60, sign_hash="sha1"): """Generate credentials for a given target. Returns a tuple of X509 certificate and EVP key.""" cert = X509.X509() cert.set_serial_number(self._get_next_serial_number()) cert.set_version(2) name = self.get_relative_subject() name.CN = hostname cert.set_subject(name) cert.set_issuer(self.cert.get_subject()) cert.set_pubkey(self.service_key) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, lifetime) ext = X509.new_extension('basicConstraints', 'CA:FALSE') ext.set_critical() cert.add_ext(ext) ext = X509.new_extension('keyUsage', 'digitalSignature, keyEncipherment') ext.set_critical() cert.add_ext(ext) cert.sign(self.key, sign_hash) return cert, self.service_key
def generate_ssl_credential(self, hostname, lifetime=24*60*60, sign_hash="sha1"): """Generate credentials for a given target. Returns a tuple of X509 certificate and EVP key.""" cert = X509.X509() cert.set_serial_number(self._get_next_serial_number()) cert.set_version(2) name = self.get_relative_subject() name.CN = hostname cert.set_subject(name) cert.set_issuer(self.cert.get_subject()) cert.set_pubkey(self.service_key) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, lifetime) ext = X509.new_extension('basicConstraints', 'CA:FALSE') ext.set_critical() cert.add_ext(ext) ext = X509.new_extension('keyUsage', 'digitalSignature, keyEncipherment') ext.set_critical() cert.add_ext(ext) cert.sign(self.key, sign_hash) return cert, self.service_key
def _create(self, hostname='localhost'): # Make the RSA key self.rsakey = RSA.gen_key(2048, m2.RSA_F4) if self.secure: # Save the key, AES256-CBC encrypted self.rsakey.save_key(self.keyfile, 'aes_256_cbc') else: # Save the key unencrypted. self.rsakey.save_key(self.keyfile, None, callback=m2util.no_passphrase_callback) # Make the public key pkey = EVP.PKey() pkey.assign_rsa(self.rsakey, 0) # Generate the certificate self.cert = X509.X509() self.cert.set_serial_number(long(bttime())) self.cert.set_version(0x2) self.cert.set_pubkey(pkey) # Set the name on the certificate name = X509.X509_Name() name.CN = hostname self.cert.set_subject(name) self.cert.set_issuer(name) # Set the period of time the cert is valid for (5 years from issue) notBefore = m2.x509_get_not_before(self.cert.x509) notAfter = m2.x509_get_not_after(self.cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, 60 * 60 * 24 * 365 * 5) # Sign the certificate self.cert.sign(pkey, 'sha1') # Save it self.cert.save_pem(self.certfile)
def get_not_after(self): assert m2.x509_type_check(self.x509), "'x509' type error" out = ASN1.ASN1_UTCTIME(m2.x509_get_not_after(self.x509)) if 'Bad time value' in str(out): raise X509Error('''M2Crypto cannot handle dates after year 2050. See RFC 5280 4.1.2.5 for more information. ''') return out
def _set_duration(self, cert): """Set certificate duration; return certificate object.""" notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) days = self.signca.ca_def_duration common.is_number(days) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, 60*60*24*int(days)) return cert
def _set_duration(self, cert): """Set certificate duration; return certificate object.""" notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) days = self.signca.ca_def_duration common.is_number(days) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, 60 * 60 * 24 * int(days)) return cert
def get_not_after(self): assert m2.x509_type_check(self.x509), "'x509' type error" out = ASN1.ASN1_UTCTIME(m2.x509_get_not_after(self.x509)) if 'Bad time value' in str(out): raise X509Error( '''M2Crypto cannot handle dates after year 2050. See RFC 5280 4.1.2.5 for more information. ''') return out
def makeCert(req, caPkey, issuer, client_cert = False, group = None): pkey = req.get_pubkey() #woop = makePKey(generateRSAKey()) #if not req.verify(woop.pkey): if not req.verify(pkey): # XXX What error object should I use? raise ValueError, 'Error verifying request' sub = req.get_subject() # If this were a real certificate request, you would display # all the relevant data from the request and ask a human operator # if you were sure. Now we just create the certificate blindly based # on the request. cert = X509.X509() # We know we are making CA cert now... # Serial defaults to 0. cert.set_serial_number(1) cert.set_version(2) cert.set_subject(sub) cert.set_issuer(issuer) cert.set_pubkey(pkey) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, -1*60*60*24) days = 1095 # 3 year m2.x509_gmtime_adj(notAfter, 60*60*24*days) if client_cert: cert.add_ext(X509.new_extension('basicConstraints', 'CA:FALSE')) cert.add_ext(X509.new_extension('nsCertType', 'client')) cert.add_ext(X509.new_extension \ ('keyUsage', 'digitalSignature, keyEncipherment')) cert.add_ext(X509.new_extension('extendedKeyUsage', 'clientAuth')) if group: cert.add_ext(X509.new_extension('nsComment', 'group:%s' %group)) else: ext = X509.new_extension('basicConstraints', 'CA:TRUE') ext.set_critical(1) cert.add_ext(ext) # Create the subject key identifier #modulus = cert.get_pubkey().get_modulus() #sha_hash = hashlib.sha1(modulus).digest() #sub_key_id = ":".join(["%02X"%ord(byte) for byte in sha_hash]) cert.add_ext(X509.new_extension('subjectKeyIdentifier', 'hash')) cert.add_ext(X509.new_extension('authorityKeyIdentifier','keyid')) cert.sign(caPkey, 'sha1') return cert
def create_certificate(issuerPrivKey, issuerInfo, subjectPubKey, subjectInfo, validForDays, serial, version = 0, hash = 'sha1'): """ Create a certificate and return certificate (PEM, text, fingerprint). """ ikey = RSA.load_key_bio(BIO.MemoryBuffer(issuerPrivKey)) if ikey.check_key() != 1: raise Exception("invalid issuer RSA key") p_ikey = EVP.PKey(md = hash) p_ikey.assign_rsa(ikey) skey = RSA.load_pub_key_bio(BIO.MemoryBuffer(subjectPubKey)) if skey.check_key() != 1: raise Exception("invalid subject RSA key") p_skey = EVP.PKey(md = hash) p_skey.assign_rsa(skey) cert = X509.X509() cert.set_pubkey(p_skey) issuer = x509name_from_info(issuerInfo) cert.set_issuer(issuer) subject = x509name_from_info(subjectInfo) cert.set_subject(subject) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, 60 * 60 * 24 * validForDays) cert.set_serial_number(serial) cert.set_version(version) cert.sign(p_ikey, hash) return (cert.as_pem(), cert.as_text(), cert_fingerprint(cert))
def makeCert(req, caPkey): pkey = req.get_pubkey() # woop = makePKey(generateRSAKey()) # if not req.verify(woop.pkey): if not req.verify(pkey): # XXX What error object should I use? raise ValueError('Error verifying request') sub = req.get_subject() # If this were a real certificate request, you would display # all the relevant data from the request and ask a human operator # if you were sure. Now we just create the certificate blindly based # on the request. cert = X509.X509() # We know we are making CA cert now... # Serial defaults to 0. cert.set_serial_number(1) cert.set_version(2) cert.set_subject(sub) issuer = X509.X509_Name() issuer.CN = 'The Issuer Monkey' issuer.O = 'The Organization Otherwise Known as My CA, Inc.' cert.set_issuer(issuer) cert.set_pubkey(pkey) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) days = 30 m2.x509_gmtime_adj(notAfter, 60 * 60 * 24 * days) cert.add_ext(X509.new_extension('subjectAltName', 'DNS:foobar.example.com')) ext = X509.new_extension('nsComment', 'M2Crypto generated certificate') ext.set_critical(0) # Defaults to non-critical, but we can also set it cert.add_ext(ext) cert.sign(caPkey, 'sha1') assert (cert.get_ext('subjectAltName').get_name() == 'subjectAltName') assert (cert.get_ext_at(0).get_name() == 'subjectAltName') assert (cert.get_ext_at(0).get_value() == 'DNS:foobar.example.com') return cert
def makeCert(req, caPkey): pkey = req.get_pubkey() # woop = makePKey(generateRSAKey()) # if not req.verify(woop.pkey): if not req.verify(pkey): # XXX What error object should I use? raise ValueError('Error verifying request') sub = req.get_subject() # If this were a real certificate request, you would display # all the relevant data from the request and ask a human operator # if you were sure. Now we just create the certificate blindly based # on the request. cert = X509.X509() # We know we are making CA cert now... # Serial defaults to 0. cert.set_serial_number(1) cert.set_version(2) cert.set_subject(sub) issuer = X509.X509_Name() issuer.CN = 'The Issuer Monkey' issuer.O = 'The Organization Otherwise Known as My CA, Inc.' cert.set_issuer(issuer) cert.set_pubkey(pkey) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) days = 30 m2.x509_gmtime_adj(notAfter, 60 * 60 * 24 * days) cert.add_ext( X509.new_extension('subjectAltName', 'DNS:foobar.example.com')) ext = X509.new_extension('nsComment', 'M2Crypto generated certificate') ext.set_critical(0) # Defaults to non-critical, but we can also set it cert.add_ext(ext) cert.sign(caPkey, 'sha1') assert(cert.get_ext('subjectAltName').get_name() == 'subjectAltName') assert(cert.get_ext_at(0).get_name() == 'subjectAltName') assert(cert.get_ext_at(0).get_value() == 'DNS:foobar.example.com') return cert
def main(argv=None): # Do argv default this way, as doing it in the functional # declaration sets it at compile time. if argv is None: argv = sys.argv # Set up out output via logging module output = logging.getLogger(argv[0]) output.setLevel(logging.DEBUG) output_handler = logging.StreamHandler(sys.stdout) # Default is sys.stderr # Set up formatter to just print message without preamble output_handler.setFormatter(logging.Formatter("%(message)s")) output.addHandler(output_handler) # Argument parsing parser = argparse.ArgumentParser( description=__doc__, # printed with -h/--help formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) # Only allow one of debug/quiet mode verbosity_group = parser.add_mutually_exclusive_group() verbosity_group.add_argument("-d", "--debug", action='store_const', const=logging.DEBUG, dest="output_level", default=logging.INFO, help="print debugging") verbosity_group.add_argument("-q", "--quiet", action="store_const", const=logging.WARNING, dest="output_level", help="run quietly") parser.add_argument("-k", "--keylength", type=int, default=2048, help="specify key length", metavar="length") parser.add_argument("-C", "--cn", type=str, default="My Service", help="specify CommonName component", metavar="cn") parser.add_argument("-O", "--org", type=str, default="My Org", help="specify Org component", metavar="org") parser.add_argument("-l", "--lifetime", type=int, default=365, help="specify certificate lifetime in days", metavar="days") parser.add_argument("--version", action="version", version="%(prog)s 1.0") parser.add_argument("ca_certFile", metavar="path", type=str, nargs="?", default="ca-cert.pem", help="where to save PEM-encoded certificate") parser.add_argument("ca_keyFile", metavar="path", type=str, nargs="?", default="ca-key.pem", help="where to save PEM-encoded key") parser.add_argument("certFile", metavar="path", type=str, nargs="?", default="cert.pem", help="where to save PEM-encoded certificate") parser.add_argument("keyFile", metavar="path", type=str, nargs="?", default="key.pem", help="where to save PEM-encoded key") args = parser.parse_args() output_handler.setLevel(args.output_level) output.info("Loading CA credentials...") ca_cert = X509.load_cert(args.ca_certFile) ca_key = EVP.load_key(args.ca_keyFile) output.info("Generating keys...") rsa_key = RSA.gen_key(args.keylength, m2.RSA_F4) key = EVP.PKey() key.assign_rsa(rsa_key) output.info("Generating certificate...") cert = X509.X509() cert.set_serial_number(ca_cert.get_serial_number() + 1) cert.set_version(2) name = X509.X509_Name() name.CN = args.cn name.O = args.org cert.set_subject(name) cert.set_issuer(name) cert.set_pubkey(key) notBefore = m2.x509_get_not_before(cert.x509) notAfter = m2.x509_get_not_after(cert.x509) m2.x509_gmtime_adj(notBefore, 0) m2.x509_gmtime_adj(notAfter, args.lifetime * 60 * 60 * 24) ext = X509.new_extension('basicConstraints', 'CA:FALSE') ext.set_critical() cert.add_ext(ext) ext = X509.new_extension('keyUsage', 'digitalSignature, keyEncipherment') ext.set_critical() cert.add_ext(ext) cert.sign(key, 'sha1') output.info("Saving certificate to {}".format(args.certFile)) cert.save_pem(args.certFile) output.info("Saving private key to {}".format(args.keyFile)) key.save_key(args.keyFile, cipher=None) # cipher=None -> save in the clear output.info("Success.") return(0)
def _make_valid_expiry(self, days=365): not_before = m2.x509_get_not_before(self._x509._ptr()) not_after = m2.x509_get_not_after(self._x509._ptr()) m2.x509_gmtime_adj(not_before, 0) m2.x509_gmtime_adj(not_after, days * 24 * 60 * 60)