Skip to content

Instantly share code, notes, and snippets.

@bluec0re
Created November 16, 2016 14:01
Show Gist options
  • Select an option

  • Save bluec0re/232e76fd6edb43783b70aac20a5d2293 to your computer and use it in GitHub Desktop.

Select an option

Save bluec0re/232e76fd6edb43783b70aac20a5d2293 to your computer and use it in GitHub Desktop.

Revisions

  1. bluec0re revised this gist Nov 16, 2016. No changes.
  2. bluec0re created this gist Nov 16, 2016.
    91 changes: 91 additions & 0 deletions cert_clone.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,91 @@
    #!/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()