Skip to content

Instantly share code, notes, and snippets.

@bluec0re
Created November 16, 2016 14:01
Show Gist options
  • Save bluec0re/232e76fd6edb43783b70aac20a5d2293 to your computer and use it in GitHub Desktop.
Save bluec0re/232e76fd6edb43783b70aac20a5d2293 to your computer and use it in GitHub Desktop.
Python2 script to clone ssl certificates (chains). Requires M2Crypto.
#!/usr/bin/env python2
# encoding: utf-8
from M2Crypto import X509, EVP, RSA, m2
import sys
import argparse
def clone_to_req(crt, *args):
req = X509.Request()
req.set_version(crt.get_version())
key = clone_pubkey(crt.get_pubkey())
pkey = EVP.PKey()
pkey.assign_rsa(key)
req.set_pubkey(pkey)
req.set_subject_name(crt.get_subject())
extstack = X509.X509_Extension_Stack()
for extid in range(crt.get_ext_count()):
extstack.push(crt.get_ext_at(extid))
req.add_extensions(extstack)
req.sign(pkey, 'sha1') # TODO: read hash algo from cert?
return req, key
def clone(crt, self_sign, out):
cert = X509.X509()
cert.set_version(crt.get_version())
cert.set_serial_number(crt.get_serial_number())
cert.set_not_before(crt.get_not_before())
cert.set_not_after(crt.get_not_after())
key = clone_pubkey(crt.get_pubkey())
pkey = EVP.PKey()
pkey.assign_rsa(key)
cert.set_pubkey(pkey)
cert.set_subject_name(crt.get_subject())
if self_sign:
cert.set_issuer(cert.get_subject())
else:
cert.set_issuer(crt.get_issuer())
for extid in range(crt.get_ext_count()):
cert.add_ext(crt.get_ext_at(extid))
if self_sign:
cert.sign(pkey, 'sha1') # TODO: read hash algo from cert?
# segfaults outside of this function??
key.save_pem('{0}.key'.format(out), None)
return cert, key
def clone_pubkey(pubkey):
key = RSA.gen_key(pubkey.size()*8, m2.RSA_F4)
return key
def main():
parser = argparse.ArgumentParser()
parser.add_argument('CERT_TO_CLONE')
parser.add_argument('-o', '--out', help="name of output files (w/o extension)", default="cloned_cert")
xor = parser.add_mutually_exclusive_group(required=True)
xor.add_argument('-s', '--self-signed', action='store_true', dest='self_signed')
xor.add_argument('CA_CERT', nargs='?')
parser.add_argument('CA_KEY', nargs='?')
args = parser.parse_args()
if args.self_signed and (args.CA_CERT or args.CA_KEY):
print "-s and CA_* couldn't be used together"
exit(1)
if (args.CA_CERT and not args.CA_KEY) or (not args.CA_CERT and args.CA_KEY):
print "CA_CERT and CA_KEY required"
exit(1)
crt = X509.load_cert(args.CERT_TO_CLONE)
newcrt, key = clone(crt, args.self_signed, args.out)
if args.CA_CERT:
ca = X509.load_cert(args.CA_CERT)
newcrt.set_issuer_name(ca.get_subject())
cakey = EVP.load_key(args.CA_KEY)
newcrt.sign(cakey, 'sha1')
print newcrt.as_text()
newcrt.save_pem('{0}.pem'.format(args.out))
print "Saved as {0}.pem and {0}.key".format(args.out)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment