def generate_minion_keys(self): #XXX TODO: Replace M2Crypto with PyCrypto # see: https://github.com/saltstack/salt/pull/1112/files # generate keys keyname = self.get_keyname() if not keyname: LOG.error("Must specify salt_id or hostname") return False gen = RSA.gen_key(2048, 1, callback=lambda x, y, z: None) pubpath = os.path.join(self.pki_dir, '{0}.pub'.format(keyname)) gen.save_pub_key(pubpath) LOG.info("public key {0}".format(pubpath)) if self.config.get('save_keys'): cumask = os.umask(191) gen.save_key(os.path.join(self.pki_dir, '{0}.pem'.format(keyname)), None) os.umask(cumask) # public key _pub = TemporaryFile() bio_pub = BIO.File(_pub) m2.rsa_write_pub_key(gen.rsa, bio_pub._ptr()) _pub.seek(0) self.config['public_key'] = self.public_key = _pub.read() self.config['formatted_public_key'] = '\n'.join( " {0}".format(k) for k in self.public_key.split('\n')) # private key _pem = TemporaryFile() bio_pem = BIO.File(_pem) gen.save_key_bio(bio_pem, None) _pem.seek(0) self.config['private_key'] = self.private_key = _pem.read() self.config['formatted_private_key'] = '\n'.join( " {0}".format(k) for k in self.private_key.split('\n')) return True
def bio_from_file_path(file_path): """Returns a BIO object for OpenSSL from input file path""" try: fdsc = open(file_path, 'rb') file_bio = BIO.File(fdsc) except IOError: file_bio = None return file_bio
def write(self, proxypath=None): """ Writes the proxy information to a file """ proxyfile = create_write_file(proxypath) bio = BIO.File(proxyfile) bio.write(self._cert.as_pem()) self._key.save_key_bio(bio, cipher=None) bio.write(self._issuer.as_pem()) bio.close()
def sign_file_with_ds_certificate(self, filename): if not os.access(filename, os.R_OK): # se riesco a leggere il file da firmare self.logger.error("No file to sign '%s' found" % filename) return None if not self.load_engine(): return None # nel caso sia fallito il caricamento scard_pin = self.config.get_smartcard_pin( ) # ottengo il pin della smartcard if scard_pin is None: return None filename_desc = open(filename) input_bio = BIO.File(filename_desc) smartcard = SmartcardFetcher.SmartcardFetcher( self.smartcard_driver_path, self.logger) self.logger.status("get digital signature id") ds_id = smartcard.get_ds_id( ) # ottengo l'id per estrarre il certificato dall smartcard # ottengo la chiave privata self.logger.status("get private key reference") pkey = self.get_ds_private_key( ds_id) # otteno la chiave privata tramite l'id if pkey is None: return False # ottengo il certificato self.logger.status("get certificate reference") certificate = self.get_ds_certificate(ds_id) if certificate is None: return False signer = SMIME.SMIME() signer.pkey = pkey signer.x509 = certificate # firmo il buffer pkcs7 = signer.sign(input_bio) # TODO da aggiungere try-except # creo un buffere di uscita out = BIO.MemoryBuffer() pkcs7.write_der(out) # per scriverlo in pem pkcs11.write(out) p7m_out = open("%s.p7m" % filename, "w") p7m_out.write(out.read()) self.logger.status('file firmato correttamente') return True
def read(self, proxypath=None): """ reads in a proxy certificate information """ if proxypath is None: proxypath = get_proxy_filename() proxyfile = open(proxypath) bio = BIO.File(proxyfile) self._cert = X509.load_cert_bio(bio) self._key = RSA.load_key_bio(bio) self._issuer = X509.load_cert_bio(bio)
def get_userkey(keyfile=None): """ function that returns a X509 instance which is the user cert that is expected to be a ~/.globus/userkey.pem """ if keyfile is None: keyfile = open( os.path.join(os.getenv("HOME"), ".globus", "userkey.pem")) else: keyfile = open(keyfile) bio = BIO.File(keyfile) key = RSA.load_key_bio(bio) return key
def get_usercert(certfile=None): """ function that returns a X509 instance which is the user cert that is expected to be a ~/.globus/usercert.pem A check is performed to ensure the certificate has valid before and after times. """ if certfile is None: certfile = open( os.path.join(os.getenv("HOME"), ".globus", "usercert.pem")) else: certfile = open(certfile) bio = BIO.File(certfile) cert = X509.load_cert_bio(bio) return cert
def getCertificateDetails(filename): basename = "" cert_details = {} basename = os.path.basename(filename).split('.')[0] cert_name = "%s_digisig.crt" % basename try: if _extractDigitalSignature(filename, signatureFile=cert_name) != None: bio=BIO.File(open(cert_name)) smime_object = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr())) signers = smime_object.get0_signers(X509.X509_Stack()) cert_details["cert_issued_by"] = signers[0].get_issuer().CN cert_details["cert_issued_to"] = signers[0].get_subject().CN validity = signers[0].get_not_after().get_datetime() cert_details["cert_expiration"] = "%s-%s-%s" % (validity.year, validity.month, validity.day) except Exception, ex: print "ERROR: Problem in retrieving certificate details : %s" % ex
def sign(filename, pkey, cert, signed_file): """Sign a text file""" try: handle = open(filename, 'rb') filebio = BIO.File(handle) signer = SMIME.SMIME() signer.load_key(pkey, cert) Rand.rand_seed(os.urandom(2048)) p7f = signer.sign(filebio) data = BIO.MemoryBuffer(None) p7f.write_der(data) with open(signed_file, 'wb') as handle: handle.write(data.read()) return True except (IOError, SMIME.SMIME_Error, SMIME.PKCS7_Error), msg: raise ValueError(str(msg))
def cmd_mkcert(workingdir, name): cwd = os.getcwd() try: config.ch_dir(workingdir, logger) priv = read_private() cacert = X509.load_cert('cacert.crt') ca_pk = EVP.load_key_string(priv[0]['ca']) cert, pk = ca_impl.mk_signed_cert(cacert, ca_pk, name, priv[0]['lastserial'] + 1) with open('%s-cert.crt' % name, 'wb') as f: f.write(cert.as_pem()) f = BIO.MemoryBuffer() pk.save_key_bio(f, None) priv[0][name] = f.getvalue() f.close() # increment serial number after successful creation priv[0]['lastserial'] += 1 write_private(priv) # write out the private key with password with os.fdopen( os.open("%s-private.pem" % name, os.O_WRONLY | os.O_CREAT, 0o600), 'wb') as f: biofile = BIO.File(f) pk.save_key_bio(biofile, None) biofile.close() pk.get_rsa().save_pub_key('%s-public.pem' % name) cc = X509.load_cert('%s-cert.crt' % name) if cc.verify(cacert.get_pubkey()): logger.info( f"Created certificate for name {name} successfully in {workingdir}" ) else: logger.error("ERROR: Cert does not validate against CA") finally: os.chdir(cwd)
def cmd_mkcert(workingdir,name): cwd = os.getcwd() try: common.ch_dir(workingdir,os.getuid()==0) priv = read_private() cacert = X509.load_cert('cacert.crt') ca_pk = EVP.load_key_string(str(priv[0]['ca'])) cert,pk = ca_impl.mk_signed_cert(cacert,ca_pk,name,priv[0]['lastserial']+1) with open('%s-cert.crt'%name, 'w') as f: f.write(cert.as_pem()) f = BIO.MemoryBuffer() pk.save_key_bio(f,None) priv[0][name]=f.getvalue() f.close() #increment serial number after successful creation priv[0]['lastserial']+=1 # extract the serial number serial = cert.get_serial_number() write_private(priv) # write out the private key with password with os.fdopen(os.open("%s-private.pem"%name,os.O_WRONLY | os.O_CREAT,0600), 'w') as f: biofile = BIO.File(f) pk.save_key_bio(biofile, 'aes_256_cbc', globalcb) biofile.close() pk.get_rsa().save_pub_key('%s-public.pem'%name) cc = X509.load_cert('%s-cert.crt'%name) if cc.verify(cacert.get_pubkey()): logger.info("Created certificate for name %s successfully in %s"%(name,workingdir)) else: logger.errro("ERROR: Cert does not validate against CA")
def validate_smime(self, msg_part, ): ''' Validates SMIME certs :param msg_part: email.message :return signer_certs: valid signer certs ''' _dashes = '-----' if self._smime is None: self.__setup_smimesetup() if msg_part.get_content_type() in self.SMIME_CONTENT_TYPES: with TemporaryFile('r+b') as fh: fh.write('%sBEGIN PKCS7%s\n%s\n%sEND PKCS7%s' % ( _dashes, _dashes, msg_part.get_payload(), _dashes, _dashes )) fh.seek(0) pfh = BIO.File(fh) p7 = SMIME.load_pkcs7_bio(pf) sk3 = p7.get0_signers(X509.X509_Stack()) if len(sk3) == 0: raise [] signer_certs = [] for cert in sk3: signer_certs.append( "%sBEGIN CERTIFICATE%s\n%s\n%sEND CERTIFICATE%s" % ( _dashes, _dashes, base64.encodestring(cert.as_der()), _dashes, _dashes )) self._smime.set_x509_stack(sk3) try: v = self._smime.verify(p7) except SMIME.SMIME_Error, e: return [] if data_bio is not None and data != v: raise [] return signer_certs
# To run, provide the path to a signed profile at the command line: # ./unsignprofile.py SignedProfile.mobileconfig from M2Crypto import SMIME, X509, m2, BIO from plistlib import * import sys import logging # Can be any file probably since we're not verifying. certstore_path = "/etc/ssl/certs/ca-certificates.crt" file_descriptor = open(sys.argv[1], 'rb') input_bio = BIO.File(file_descriptor) signer = SMIME.SMIME() cert_store = X509.X509_Store() cert_store.load_info(certstore_path) signer.set_x509_store(cert_store) try: p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) except SMIME.SMIME_Error, e: logging.error('load pkcs7 error: ' + str(e)) sk3 = p7.get0_signers(X509.X509_Stack()) signer.set_x509_stack(sk3) data_bio = None content = signer.verify(p7, data_bio, flags=SMIME.PKCS7_NOVERIFY) # Printing the contents of the profile/plist, modify to save to file with write() print readPlistFromString(content)
#!/usr/bin/env python from M2Crypto import SMIME, X509, BIO, m2 import plistlib import sys if len(sys.argv) < 3: print "Usage: %s [Provisioning Profile] [Out .xcconfig]" % __file__ exit() inProfile = sys.argv[1] outXcConfig = sys.argv[2] provision = open(inProfile, 'r') inBio = BIO.File(provision) pkcs7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(inBio._ptr())) smime = SMIME.SMIME() stack = X509.X509_Stack() smime.set_x509_stack(stack) store = X509.X509_Store() smime.set_x509_store(store) dataBio = None blob = smime.verify(pkcs7, dataBio, SMIME.PKCS7_NOVERIFY | SMIME.PKCS7_NOSIGS) certs = pkcs7.get0_signers(stack) signer = certs[0]
def BIO_from_file(fd): """ Returns a BIO object for OpenSSL from input file descriptor """ return BIO.File(fd)
def verify_file_with_ds_certificate(self, filename, p7filename, is_self_signed=True): if not os.access(filename, os.R_OK): self.logger.error("No filename to verify '%s' found" % filename) return None if not os.access(p7filename, os.R_OK): self.logger.error("No filename to verify '%s' found" % filename) return None if not self.load_engine(): return None # nel caso sia fallito il caricamento smartcard_atr = SmartcardFetcher.get_smartcard_atr(self.logger) smartcard_library = SmartcardFetcher.get_smartcard_library( smartcard_atr, self.config, self.logger) smartcard = SmartcardFetcher.SmartcardFetcher(smartcard_library, self.logger) self.logger.status('get ds id') ds_id = smartcard.get_ds_id( ) # ottengo l'id per estrarre il certificato dall smartcard self.logger.status('get ds certificate') certificate = self.get_ds_certificate(ds_id) # ottengo il certificato if certificate is None: return None # creo uno store di certificati store_stack = X509.X509_Stack() store_stack.push(certificate) store = X509.X509_Store() store.add_x509(certificate) signer = SMIME.SMIME() signer.set_x509_stack(store_stack) signer.set_x509_store(store) #p7, data = SMIME.load_pkcs7(p7m_file) # carico il file firmato in formato PEM self.logger.status('read p7mfile %s' % p7filename) p7m_fd = open(p7filename, "rb") p7_input_bio = BIO.File(p7m_fd) # carico il file p7m p7 = SMIME.PKCS7( m2.pkcs7_read_bio_der(p7_input_bio._ptr()), 1 ) # al momento non c'e' nessun modo per estrarre i dati del DER dal certificato # p7, data = SMIME.load_pkcs7_bio(p7_input_bio) # l'input bio deve essere in formato PEM (basa64) data_bio = None try: if is_self_signed: self.logger.status('verifing file') v = signer.verify(p7, data_bio, flags=SMIME.PKCS7_NOVERIFY) else: v = signer.verify(p7, data_bio) except SMIME.SMIME_Error, e: self.logger.error('smime error: ' + str(e)) return None
data = s.decrypt(p7) # Because we passed in a SignAndEnveloped blob, the output # of our decryption is a Signed blob. We now verify it. # Load the signer's cert. sk = X509.X509_Stack() s.set_x509_stack(sk) # Load the CA cert. st = X509.X509_Store() st.load_info(ca_cert) s.set_x509_store(st) # Verify. p7, bio = SMIME.smime_load_pkcs7_bio(BIO.MemoryBuffer(data)) if bio is not None: # Netscape Messenger clear-signs, when also encrypting. data = s.verify(p7, bio) else: # M2Crypto's sendsmime.py opaque-signs, when also encrypting. data = s.verify(p7) print data if __name__ == '__main__': Rand.load_file('../randpool.dat', -1) decrypt_verify(BIO.File(sys.stdin), 'client.pem', 'client2.pem', 'ca.pem') Rand.save_file('../randpool.dat')