#!/usr/bin/env python # #vim: ts=4 sw=4 nowrap # import M2Crypto import time import sys import hashlib CERT_PATH='/root/root-ca' MBSTRING_FLAG = 0x1000 MBSTRING_ASC = MBSTRING_FLAG | 1 MBSTRING_BMP = MBSTRING_FLAG | 2 class Cert: def __init__ ( self ): self.RsaKey = { 'KeyLength' : 1024, 'PubExponent' : 0x10001, # -> 65537 'keygen_callback' : self.callback } self.KeyPair = None self.PKey = None self.X509Request = None self.X509Certificate = None self.X509CACertificate = None self.CAPKey = None def callback ( self, *args ): return 'p' def CreatePKey ( self ): # Create a keypair for RSA magic self.KeyPair = M2Crypto.RSA.gen_key( self.RsaKey['KeyLength'], self.RsaKey[' PubExponent'], self.RsaKey['keygen_callback'] ) self.PKey = M2Crypto.EVP.PKey ( md='sha1') # Set PKey to the RSA side of this keypair self.PKey.assign_rsa ( self.KeyPair ) def CreateX509Request ( self, cn ): # Start X509 request self.X509Request = M2Crypto.X509.Request () # Set up the subject X509Name = M2Crypto.X509.X509_Name () X509Name.add_entry_by_txt ( field='C', type=MBSTRING_ASC, entry=' US', len=-1, loc=-1, set=0 ) # country name X509Name.add_entry_by_txt ( field='ST', type=MBSTRING_ASC, entry=' California', len=-1, loc=-1, set=0 ) # state of province name X509Name.add_entry_by_txt ( field='L', type=MBSTRING_ASC, entry=' Menlo Park', len=-1, loc=-1, set=0 ) # locality name X509Name.add_entry_by_txt ( field='O', type=MBSTRING_ASC, entry='Nevro', len=-1, loc=-1, set=0 ) # organization name X509Name.add_entry_by_txt ( field='OU', type=MBSTRING_ASC, entry='it-department', len=-1, loc=-1, set=0 ) # organizational unit name X509Name.add_entry_by_txt ( field='CN', type=MBSTRING_ASC, entry=cn, len=-1, loc=-1, set=0 ) # common name X509Name.add_entry_by_txt ( field='Email', type=MBSTRING_ASC, entry='admin@nevro.com', len=-1, loc=-1, set=0 ) # pkcs9 email address X509Name.add_entry_by_txt ( field='emailAddress', type=MBSTRING_ASC, entry='admin@nevro.com', len=-1, loc=-1, set=0 ) # pkcs9 email address self.X509Request.set_subject_name( X509Name ) # Assign it to the RSA publicKey self.X509Request.set_pubkey ( pkey=self.PKey ) # Sign off on the fact that this publicKey is for this CSR self.X509Request.sign ( pkey=self.PKey, md='sha1' ) def CreateX509Certificate ( self ): self.X509Certificate = M2Crypto.X509.X509 () self.X509Certificate.set_version ( 0 ) t = long(time.time()) # Set notBefore and notAfter for a 5-year cert ASN1 = M2Crypto.ASN1.ASN1_UTCTIME () ASN1.set_time ( t ) self.X509Certificate.set_not_before( ASN1 ) ASN1 = M2Crypto.ASN1.ASN1_UTCTIME () ASN1.set_time ( t + 60 * 60 * 24 * 365 * 5 ) # 5 years self.X509Certificate.set_not_after( ASN1 ) # Assign it to the same RSA publicKey self.X509Certificate.set_pubkey ( pkey=self.PKey ) # Set the CRT subject from the CSR X509Name = self.X509Request.get_subject () self.X509Certificate.set_subject_name( X509Name ) # Load the root CA/key self.X509CACertificate = M2Crypto.X509.load_cert(CERT_PATH + '/public/root.pem') self.CAPKey = M2Crypto.EVP.load_key(CERT_PATH + '/private/root.pem') # Set the root CA as the issuer self.X509Certificate.set_issuer( self.X509CACertificate.get_issuer() ) ext1 = M2Crypto.X509.new_extension('basicConstraints', 'CA:FALSE') ext1.set_critical(1) modulus = self.PKey.get_modulus() sha_hash = hashlib.sha1(modulus).digest() sub_key_id = ":".join(["%02X"%ord(byte) for byte in sha_hash]) ext2 = M2Crypto.X509.new_extension('subjectKeyIdentifier', sub_key_id) ext3 = M2Crypto.X509.new_extension('keyUsage', 'Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment') ext3.set_critical(1) ext4 = self.X509CACertificate.get_ext('authorityKeyIdentifier') self.X509Certificate.add_ext(ext1) self.X509Certificate.add_ext(ext2) self.X509Certificate.add_ext(ext3) self.X509Certificate.add_ext(ext4) # Sign with the root CA's key self.X509Certificate.sign( pkey=self.CAPKey, md='sha1' ) if __name__ == '__main__': if len (sys.argv) < 2: sys.exit('Usage: %s any.domain-name.com' % sys.argv[0]) run = Cert () run.CreatePKey () run.CreateX509Request (sys.argv[1]) run.CreateX509Certificate () # Save the cert run.X509Certificate.save( CERT_PATH + '/signed-certs/' + sys.argv[1] + '.crt') # Save the key without a passphrase (cipher = None) run.PKey.save_key( CERT_PATH + '/signed-certs/' + sys.argv[1] + '.key', cipher=None, callback=run.callback )