def test_encrypt(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() x509 = X509.load_cert('tests/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) with self.assertRaises(ValueError): SMIME.Cipher('nosuchcipher') s.set_cipher(SMIME.Cipher('des_ede3_cbc')) p7 = s.encrypt(buf) self.assertEqual(len(buf), 0) self.assertEqual(p7.type(), SMIME.PKCS7_ENVELOPED, p7.type()) self.assertIsInstance(p7, SMIME.PKCS7, p7) out = BIO.MemoryBuffer() p7.write(out) buf = out.read() self.assertTrue(buf.startswith(b'-----BEGIN PKCS7-----')) buf = buf.strip() self.assertTrue(buf.endswith(b'-----END PKCS7-----')) self.assertGreater( len(buf), len(b'-----END PKCS7-----') + len(b'-----BEGIN PKCS7-----')) s.write(out, p7) return out
def encrypt_email_body(client: Client, args: Dict): """ generate an S/MIME-encrypted message Args: client: Client args: Dict """ message_body = args.get('message', '').encode('utf-8') buf = makebuf(message_body) x509 = X509.load_cert(client.public_key_file) sk = X509.X509_Stack() sk.push(x509) client.smime.set_x509_stack(sk) client.smime.set_cipher(SMIME.Cipher('des_ede3_cbc')) p7 = client.smime.encrypt(buf) out = BIO.MemoryBuffer() client.smime.write(out, p7) encrypted_message = out.read().decode('utf-8') message = encrypted_message.split('\n\n') headers = message[0] new_headers = headers.replace(': ', '=').replace('\n', ',') entry_context = { 'SMIME.Encrypted': { 'Message': encrypted_message, 'Headers': new_headers } } return encrypted_message, entry_context
def encrypt(input_bio, cert, keyring_source, cypher): """ Encrypts the input data with the public key in the certificate from keyring source with selected cypher. @type input_bio: M2Crypto.BIO @param input_bio: input data to encrypt. @type cert: filepath or M2Crypto.BIO or M2Crypto.X509.X509 @param cert: the recipient certificate reference from filepath, could be from file, from memory or from pkcs11 smartcard, based on keyring_soruce input parameter. @type keyring_source: str @keyword keyring_source: the type of the source for input certificate, used to recall the appropriate method for encrypter settings. Ammitted values are: file, memory, pkcs11. @type cypher: str @keyword cypher: the cypher to use for encryption of the data, run "openssl enc -help" for supported cyphers, you have to choose a public key cypher from availables. @rtype: M2Crypto.SMIME.PKCS7 @return: the PKCS#7 encrypted data in PEM format. """ encrypter = SMIME.SMIME() x509 = set_certificate(cert, keyring_source) sk = X509.X509_Stack() sk.push(x509) encrypter.set_x509_stack(sk) encrypter.set_cipher(SMIME.Cipher(cypher)) Rand.load_file('randpool.dat', -1) try: p7 = encrypter.encrypt(input_bio) except SMIME.SMIME_Error, e: logging.error('smime error: ' + str(e)) raise
def test_encrypt(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() x509 = X509.load_cert('test/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) self.assertRaises(ValueError, SMIME.Cipher, 'nosuchcipher') s.set_cipher(SMIME.Cipher('des_ede3_cbc')) p7 = s.encrypt(buf) assert len(buf) == 0 assert p7.type() == SMIME.PKCS7_ENVELOPED, p7.type() assert isinstance(p7, SMIME.PKCS7), p7 out = BIO.MemoryBuffer() p7.write(out) buf = out.read() assert buf[:len('-----BEGIN PKCS7-----')] == '-----BEGIN PKCS7-----' buf = buf.strip() assert buf[-len('-----END PKCS7-----'):] == '-----END PKCS7-----' assert len(buf) > len('-----END PKCS7-----') + len('-----BEGIN PKCS7-----') s.write(out, p7) return out
def encrypt_block(blob, pubkey): """ Encrypt the given blob of data, given the public key provided. :return The encrypted blob. """ # Make a MemoryBuffer of the message. inbuf = BIO.MemoryBuffer(blob) # Seed the PRNG. Rand.rand_seed(os.urandom(1024)) # Instantiate an SMIME object. s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert(pubkey) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: AES 256 bit in CBC mode. s.set_cipher(SMIME.Cipher('aes_256_cbc')) # Encrypt the buffer. p7 = s.encrypt(inbuf) temp_buff = BIO.MemoryBuffer() s.write(temp_buff, p7) x = temp_buff.read() return x
def encrypt(data, cert_path='/workspace/personal/python_test/keys/myCert.pem', compact=True): # Make a MemoryBuffer of the message. buf = BIO.MemoryBuffer(data) # Instantiate an SMIME object. s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert(cert_path) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Encrypt the buffer. p7 = s.encrypt(buf) # Output p7 to a MemoryBuffer. out = BIO.MemoryBuffer() s.write(out, p7) # Read output as string output = out.read() if compact: # create a single line encrypted message output = ''.join(output.split('\n')[5:]) return output
def _encrypt(self): """Use your key thing to encrypt things.""" from M2Crypto import BIO, SMIME, X509 CERT = self.settings.private_cert PUB_CERT = self.settings.public_cert PAYPAL_CERT = self.settings.paypal_cert CERT_ID = self.settings.cert_id # Iterate through the fields and pull out the ones that have a value. plaintext = 'cert_id=%s' % CERT_ID for name, value in self.items.iteritems(): plaintext += '\n%s=%s' % (name, value) #plaintext = plaintext.encode('utf-8') # Begin crypto weirdness. s = SMIME.SMIME() s.load_key_bio(BIO.openfile(CERT), BIO.openfile(PUB_CERT)) p7 = s.sign(BIO.MemoryBuffer(plaintext), flags=SMIME.PKCS7_BINARY) x509 = X509.load_cert_bio(BIO.openfile(PAYPAL_CERT)) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp = BIO.MemoryBuffer() p7.write_der(tmp) p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() p7.write(out) return out.read()
def ed(): print 'test encrypt/decrypt...', buf = makebuf() s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert('client.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Add a cipher. s.set_cipher(SMIME.Cipher('bf_cbc')) # Encrypt. p7 = s.encrypt(buf) # Load target's private key. s.load_key('client.pem') # Decrypt. data = s.decrypt(p7) if data: print 'ok' else: print 'not ok'
def _encrypt(self): """Use your key thing to encrypt things.""" from M2Crypto import BIO, SMIME, X509 # Iterate through the fields and pull out the ones that have a value. plaintext = 'cert_id=%s\n' % self.cert_id for name, field in self.fields.items(): value = None if name in self.initial: value = self.initial[name] elif field.initial is not None: value = field.initial if value is not None: plaintext += u'%s=%s\n' % (name, value) plaintext = plaintext.encode('utf-8') # Begin crypto weirdness. s = SMIME.SMIME() s.load_key_bio(BIO.openfile(self.private_cert), BIO.openfile(self.public_cert)) p7 = s.sign(BIO.MemoryBuffer(plaintext), flags=SMIME.PKCS7_BINARY) x509 = X509.load_cert_bio(BIO.openfile(self.paypal_cert)) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp = BIO.MemoryBuffer() p7.write_der(tmp) p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() p7.write(out) return out.read().decode()
def smime_encrypt(raw_message, recipients): if not get_bool_from_cfg('smime', 'cert_path'): log("No valid path for S/MIME certs found in config file. S/MIME encryption aborted." ) return recipients cert_path = cfg['smime']['cert_path'] + "/" s = SMIME.SMIME() sk = X509.X509_Stack() smime_to = list() unsmime_to = list() for addr in recipients: cert_and_email = get_cert_for_email(addr, cert_path) if not (cert_and_email is None): (to_cert, normal_email) = cert_and_email if verbose: log("Found cert " + to_cert + " for " + addr + ": " + normal_email) smime_to.append(addr) x509 = X509.load_cert(to_cert, format=X509.FORMAT_PEM) sk.push(x509) else: unsmime_to.append(addr) if smime_to != list(): s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('aes_192_cbc')) p7 = s.encrypt(BIO.MemoryBuffer(raw_message.as_string())) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: ' + from_addr + '\n') out.write('To: ' + raw_message['To'] + '\n') if raw_message['Cc']: out.write('Cc: ' + raw_message['Cc'] + '\n') if raw_message['Bcc']: out.write('Bcc: ' + raw_message['Bcc'] + '\n') if raw_message['Subject']: out.write('Subject: ' + raw_message['Subject'] + '\n') if get_bool_from_cfg('default', 'add_header', 'yes'): out.write('X-GPG-Mailgate: Encrypted by GPG Mailgate\n') s.write(out, p7) if verbose: log("Sending message from " + from_addr + " to " + str(smime_to)) send_msg(out.read(), smime_to) if unsmime_to != list(): if verbose: log("Unable to find valid S/MIME certificates for " + str(unsmime_to)) return unsmime_to
def encrypt_payload(payload, key, cipher): encrypter = SMIME.SMIME() certificate = X509.X509_Stack() certificate.push(X509.load_cert(key)) encrypter.set_x509_stack(certificate) encrypter.set_cipher(SMIME.Cipher(cipher)) encrypted_content = encrypter.encrypt(BIO.MemoryBuffer(payload), SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() encrypter.write(out, encrypted_content) return email.message_from_string(out.read())
def to_smime(message, sender_key, sender_cert, recipient_cert, cipher='aes_128_cbc'): try: message = RFC822 % message smime = SMIME.SMIME() #smime.pkey = sender_key #smime.x509 = sender_cert signature = '' logging.debug('Signing outgoing message') command = ('/usr/bin/env', 'openssl', 'cms', '-sign', '-signer', sender_cert, '-inkey', sender_key, '-md', 'sha256') proc = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=-1) #proc.stdin.write(message) #signature, stderr = proc.communicate() thread = threading.Thread(target=writer, args=( proc, message, )) thread.start() for line in proc.stdout: signature += line thread.join() logging.debug('Message signed') logging.debug('Encrypting message') #signature = smime.sign(BIO.MemoryBuffer(message), flags=SMIME.PKCS7_DETACHED) #init buffer message_signed = BIO.MemoryBuffer(signature) #smime.write(message_signed, signature, BIO.MemoryBuffer(message)) cert_stack = X509.X509_Stack() #for cert in recipient_certs: cert_stack.push(X509.load_cert_der_string(recipient_cert)) smime.set_x509_stack(cert_stack) smime.set_cipher(SMIME.Cipher(cipher)) message_encrypted = smime.encrypt(message_signed) out = BIO.MemoryBuffer() smime.write(out, message_encrypted) out.close() logging.debug('Message encrypted') return out.read().replace('x-pkcs7-mime', 'pkcs7-mime') except SMIME.SMIME_Error, e: logging.error('smime error: %s', e) raise
def form_encrypted(self, data): """Return an s/mime encrypted form. Refer to http://sandbox.rulemaker.net/ngps/m2/howto.smime.html for instructions.""" from M2Crypto import BIO, SMIME, X509 certid = self.settings["PUBLIC_CERT_ID"] ret = ['CERT_ID=%s' % certid] ret.extend([u'%s=%s' % (key, val) for key, val in data.items() if val]) raw = "\n".join(ret) raw = raw.encode('utf-8') self.log_extra('Plaintext form: %s', raw) # encrypt the plaintext # make an smime object s = SMIME.SMIME() # load our public and private keys s.load_key_bio(BIO.openfile(self.localprikey), BIO.openfile(self.localpubkey)) # put the data in the buffer buf = BIO.MemoryBuffer(raw) # sign the text p7 = s.sign(buf, flags=SMIME.PKCS7_BINARY) # Load target cert to encrypt to. x509 = X509.load_cert_bio(BIO.openfile(self.paypalpubkey)) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # save data to buffer tmp = BIO.MemoryBuffer() p7.write_der(tmp) # encrypt p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() # write into a new buffer p7.write(out) # read the result form = out.read() self.log_extra('Encrypted form: %s', form) return mark_safe( u"""<input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="encrypted" value="%s" /> """ % form)
def sendsmime(from_addr, to_addrs, subject, msg, from_key, from_cert=None, to_certs=None, smtpd='localhost'): msg_bio = BIO.MemoryBuffer(msg) sign = from_key encrypt = to_certs s = SMIME.SMIME() if sign: s.load_key(from_key, from_cert) if encrypt: p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT) else: p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT | SMIME.PKCS7_DETACHED) msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it. if encrypt: sk = X509.X509_Stack() for x in to_certs: sk.push(X509.load_cert(x)) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('rc2_40_cbc')) tmp_bio = BIO.MemoryBuffer() if sign: s.write(tmp_bio, p7) else: tmp_bio.write(msg) p7 = s.encrypt(tmp_bio) out = BIO.MemoryBuffer() out.write('From: %s\r\n' % from_addr) out.write('To: %s\r\n' % string.join(to_addrs, ", ")) out.write('Subject: %s\r\n' % subject) if encrypt: s.write(out, p7) else: if sign: s.write(out, p7, msg_bio, SMIME.PKCS7_TEXT) else: out.write('\r\n') out.write(msg) out.close() smtp = smtplib.SMTP() smtp.connect(smtpd) smtp.sendmail(from_addr, to_addrs, out.read()) smtp.quit()
def set_message(self, message, certificates=[]): """Sign and encrypt the email and prepare it to send""" self.message = message # Seed the PRNG. Rand.load_file('randpool.dat', -1) smime = SMIME.SMIME() # put message with attachments into into SSL" I/O buffer msg_str = self.message.msg.as_string() msg_bio = BIO.MemoryBuffer(bytes(msg_str, 'utf-8')) if self.sign: smime.load_key(self.key, self.cert) p7 = smime.sign(msg_bio, SMIME.PKCS7_DETACHED) # Recreate the message because sign function has consumed it msg_bio = BIO.MemoryBuffer(bytes(msg_str, 'utf-8')) if self.encrypt: sk = X509.X509_Stack() for cert in certificates: sk.push(X509.load_cert(cert)) smime.set_x509_stack(sk) smime.set_cipher(SMIME.Cipher(self.cipher)) tmp_bio = BIO.MemoryBuffer() if self.sign: smime.write(tmp_bio, p7, msg_bio) else: tmp_bio.write(msg_str) p7 = smime.encrypt(tmp_bio) out = BIO.MemoryBuffer() out.write('From: %s\r\n' % self.message.sender) out.write('To: %s\r\n' % ", ".join(self.message.recipients)) out.write('Subject: %s\r\n' % self.message.subject) if self.encrypt: smime.write(out, p7) elif self.sign: smime.write(out, p7, msg_bio) else: out.write(msg_str) out.close() # Save the PRNG's state. Rand.save_file('randpool.dat') return out.read().decode("utf-8")
def encrypt(self, sender_address, encrypting_identities, message): """ Encrypts the given message for all the supplied recipients. """ if not encrypting_identities: raise ValueError("Encrypting recipient identities not supplied.") if not message: raise ValueError("Valid Message not supplied.") s = SMIME.SMIME() cipher = getattr(settings, "DJEMBE_CIPHER", "aes_256_cbc") s.set_cipher(SMIME.Cipher(cipher)) self.logger.debug("Encrypting message for %s" % encrypting_identities) # Gather all the recipient certificates sk = X509.X509_Stack() for identity in encrypting_identities: sk.push(identity.x509) s.set_x509_stack(sk) # prepare the payload for encryption payload_msg = self.extract_payload(message) # encrypt the payload payload = BIO.MemoryBuffer(payload_msg.as_bytes()) pkcs7_encrypted_data = s.encrypt(payload) payload.close() # get the PKCS7 object into a string payload = BIO.MemoryBuffer() s.write(payload, pkcs7_encrypted_data) pkcs7_string = payload.read() payload.close() encrypted_message = email.message_from_string(pkcs7_string.decode("UTF-8")) message.set_payload(encrypted_message.get_payload()) for header, value in encrypted_message.items(): del message[header] message[header] = value del message["Message-ID"] message["Message-ID"] = make_msgid() return message
def render(self, md): # Render the dtml block. data = render_blocks(self.section.blocks, md) data_bio = BIO.MemoryBuffer(data) # Prepare to S/MIME. s = SMIME.SMIME() # Render the signer key, load into BIO. try: signer = Var(self.signer).render(md) except ParseError: raise SmimeError, ('Invalid parameter "signer".') signer_key_bio = BIO.MemoryBuffer(signer) signer_cert_bio = BIO.MemoryBuffer(signer) # XXX Kludge. # Sign the data. s.load_key_bio(signer_key_bio, signer_cert_bio) p7 = s.sign(data_bio, flags=SMIME.PKCS7_TEXT) # Recreate coz sign() has consumed the MemoryBuffer. # May be cheaper to seek to start. data_bio = BIO.MemoryBuffer(data) # Render recipients, load into BIO. try: recip = Var(self.recipients).render(md) except ParseError: raise SmimeError, ('Invalid parameter "recipients".') recip_bio = BIO.MemoryBuffer(recip) # Load recipient certificates. sk = X509.X509_Stack() sk.push(X509.load_cert_bio(recip_bio)) s.set_x509_stack(sk) # Set a cipher. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Encrypt. tmp_bio = BIO.MemoryBuffer() s.write(tmp_bio, p7) p7 = s.encrypt(tmp_bio) # Finally, return the now signed/encrypted PKCS7. out = BIO.MemoryBuffer() s.write(out, p7) return out.getvalue()
def paypalencrypt(self): plaintext = '' for key, value in self.attributes.items(): plaintext += u'%s=%s\n' % (key, value) plaintext = plaintext.encode('utf-8') # Instantiate an SMIME object. s = SMIME.SMIME() # Load signer's key and cert. Sign the buffer. s.pkey = EVP.load_key( os.path.join(current.request.folder, 'private/paypal', 'priv_paypalgextiendas.pem')) s.x509 = X509.load_cert( os.path.join(current.request.folder, 'private/paypal', 'pub_paypalgextiendas.pem')) p7 = s.sign(BIO.MemoryBuffer(plaintext), flags=SMIME.PKCS7_BINARY) x509 = X509.load_cert( os.path.join(current.request.folder, 'private/paypal', 'paypal_cert_pem.txt')) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Create a temporary buffer. tmp = BIO.MemoryBuffer() # Write the signed message into the temporary buffer. p7.write_der(tmp) # Encrypt the temporary buffer. p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() p7.write(out) return out.read()
def encrypt(filename, outfilename): from M2Crypto import BIO, Rand, SMIME, X509 PUBLIC_KEY = '''-----BEGIN CERTIFICATE----- MIIEUTCCAzmgAwIBAgIJAK1MSC7OcXXEMA0GCSqGSIb3DQEBBQUAMIG+MQswCQYD VQQGEwJVUzENMAsGA1UECAwEVXRhaDEPMA0GA1UEBwwGRHJhcGVyMR0wGwYDVQQK DBRDb250cm9sNCBDb3Jwb3JhdGlvbjEiMCAGA1UECwwZRHJpdmVyV29ya3MgRW5j cnlwdGlvbiBWMjEiMCAGA1UEAwwZRHJpdmVyV29ya3MgRW5jcnlwdGlvbiBWMjEo MCYGCSqGSIb3DQEJARYZY2VydC1zdXBwb3J0QGNvbnRyb2w0LmNvbTAeFw0xMzA5 MTcxOTUwMTlaFw0zMzA5MTIxOTUwMTlaMIG+MQswCQYDVQQGEwJVUzENMAsGA1UE CAwEVXRhaDEPMA0GA1UEBwwGRHJhcGVyMR0wGwYDVQQKDBRDb250cm9sNCBDb3Jw b3JhdGlvbjEiMCAGA1UECwwZRHJpdmVyV29ya3MgRW5jcnlwdGlvbiBWMjEiMCAG A1UEAwwZRHJpdmVyV29ya3MgRW5jcnlwdGlvbiBWMjEoMCYGCSqGSIb3DQEJARYZ Y2VydC1zdXBwb3J0QGNvbnRyb2w0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBANpapgg8oU3FIhzDYEVM14lPKVbsuqm/+9CJKYSPVPjEvdm17IMI O4axqFDj1BH8qdbSwhPugC+j0q5O2jlfA19u5aL2vHpr04MSZF0OHWYN20g+pWXe gaq3LQsjBLiQPQKewS5v5Ff4GydJD63rJz8pO18ztYlPYNrABOBcEM7MiVvzJK6e NMTOOEZqf2FIjtXQhyclkzcBz7j/TC2jqvYa96DmfpYoPAajf+ypzxezSZ6G4GRa 6jlNtBg40QjHtHxWa3PsZ86PiLMnZ2z4SryMpcecm7Jj/iA9Hh76wLglv4TtjXxk gtqkv7RzOHlmOeB4nH8lsqTyRBmnn39fDuMCAwEAAaNQME4wHQYDVR0OBBYEFHCV PSWmatjY5ixd4azS6+GxDIpwMB8GA1UdIwQYMBaAFHCVPSWmatjY5ixd4azS6+Gx DIpwMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHl58yYI7IMWkkxI vu5kff/MKTSt4SXN365o3opc8FBuo/d3v2IKkIlo8BWbuCp4MwqV8L/0UYupFs49 RI5N0ETTapdg1uoVUd8NGHx7FgZ5MU9+caMEI8PoaRcFPdrxL1S7nOyl0ceFWwIz 1V2Hc9hZQEcv586El+/xXq/jd/oydN+j+knaL/dwvcK88TvQjl3AS974QuedvGIh pq8tXfMiu1iPpc29tOMgfJzO0V6T92Fn5XbAY4u5p9Rvs/h8x7Ono++zRh66JOXQ T++pYjmRUr+BSgZfoZzvs9mdMqtFpeWIx6nW4vXjDwAILVP3Bgh9MwrEzJtIQ/qy Zwi18AY= -----END CERTIFICATE-----''' with open(filename, 'rb') as file: str = file.read() buf = BIO.MemoryBuffer(str) smime = SMIME.SMIME() x509 = X509.load_cert_string(PUBLIC_KEY) x509_stack = X509.X509_Stack() x509_stack.push(x509) smime.set_x509_stack(x509_stack) smime.set_cipher(SMIME.Cipher('aes_256_cbc')) pkcs7 = smime.encrypt(buf, flags=SMIME.PKCS7_BINARY) outbuf = BIO.MemoryBuffer() pkcs7.write_der(outbuf) with open(outfilename, 'wb') as outfile: outfile.write(outbuf.read())
def test_signEncryptDecryptVerify(self): # sign buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(buf) # encrypt x509 = X509.load_cert('tests/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp = BIO.MemoryBuffer() s.write(tmp, p7) p7 = s.encrypt(tmp) signedEncrypted = BIO.MemoryBuffer() s.write(signedEncrypted, p7) # decrypt s = SMIME.SMIME() s.load_key('tests/recipient_key.pem', 'tests/recipient.pem') p7, data = SMIME.smime_load_pkcs7_bio(signedEncrypted) out = s.decrypt(p7) # verify x509 = X509.load_cert('tests/signer.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('tests/ca.pem') s.set_x509_store(st) p7_bio = BIO.MemoryBuffer(out) p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) v = s.verify(p7) self.assertEqual(v, self.cleartext)
def sign_and_encrypt(self): # Make a MemoryBuffer of the message. buf = makebuf('a sign of our times') # Seed the PRNG. Rand.load_file(randpool, -1) # Instantiate an SMIME object. s = SMIME.SMIME() # Load signer's key and cert. Sign the buffer. s.load_key(signer_key, signer_cert) p7 = s.sign(buf, SMIME.PKCS7_DETACHED) # Load target cert to encrypt the signed message to. x509 = X509.load_cert(recipient_cert) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Create a temporary buffer. tmp = BIO.MemoryBuffer() # Write the signed message into the temporary buffer. s.write(tmp, p7, buf) # Encrypt the temporary buffer. p7 = s.encrypt(tmp) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: [email protected]\n') out.write('To: [email protected]\n') out.write('Subject: M2Crypto S/MIME testing\n') s.write(out, p7) result = out.read() # Save the PRNG's state. Rand.save_file(randpool) open('smime-m2-sign-encrypt.txt', 'wt').write(result)
def sign_and_encrypt(client: Client, args: Dict): message = args.get('message', '').encode('utf-8') msg_bio = BIO.MemoryBuffer(message) sign = client.private_key_file encrypt = client.public_key_file if sign: client.smime.load_key(client.private_key_file, client.public_key_file) if encrypt: p7 = client.smime.sign(msg_bio, flags=SMIME.PKCS7_TEXT) else: p7 = client.smime.sign(msg_bio, flags=SMIME.PKCS7_TEXT | SMIME.PKCS7_DETACHED) msg_bio = BIO.MemoryBuffer( message) # Recreate coz sign() has consumed it. if encrypt: x509 = X509.load_cert(client.public_key_file) sk = X509.X509_Stack() sk.push(x509) client.smime.set_x509_stack(sk) client.smime.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp_bio = BIO.MemoryBuffer() if sign: client.smime.write(tmp_bio, p7) else: tmp_bio.write(message) p7 = client.smime.encrypt(tmp_bio) out = BIO.MemoryBuffer() if encrypt: client.smime.write(out, p7) else: if sign: client.smime.write(out, p7, msg_bio, SMIME.PKCS7_TEXT) else: out.write('\r\n') out.write(message) msg = out.read().decode('utf-8') entry_context = {'SMIME.SignedAndEncrypted': {'Message': msg}} return msg, entry_context
def __init__(self, d): self.plaindict = d plaintext = dumps(dict(d)) self.key_hashes = set([self.hash_key(k) for k in d.keys()]) s = SMIME.SMIME() x509 = X509.load_cert(settings.RSA_CERTIFICATE) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) p7 = s.encrypt(BIO.MemoryBuffer(plaintext), flags=SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() p7.write(out) self.ciphertext = out.read()
def _encrypt(self): """Use your key thing to encrypt things.""" from M2Crypto import BIO, SMIME, X509 # @@@ Could we move this to conf.py? CERT = settings.PAYPAL_PRIVATE_CERT PUB_CERT = settings.PAYPAL_PUBLIC_CERT PAYPAL_CERT = settings.PAYPAL_CERT CERT_ID = self.cert_id # Iterate through the fields and pull out the ones that have a value. plaintext = 'cert_id=%s\n' % CERT_ID for name, field in self.fields.items(): value = None if name in self.initial: value = self.initial[name] elif field.initial is not None: value = field.initial if value is not None: # @@@ Make this less hackish and put it in the widget. if name == "return_url": name = "return" plaintext += u'%s=%s\n' % (name, value) plaintext = plaintext.encode('utf-8') with BIO.openfile(CERT) as cert_f, \ BIO.openfile(PUB_CERT) as pub_cert_f, \ BIO.openfile(settings.PAYPAL_CERT) as pp_cert_f: # Begin crypto weirdness. s = SMIME.SMIME() s.load_key_bio(cert_f, pub_cert_f) p7 = s.sign(BIO.MemoryBuffer(plaintext), flags=SMIME.PKCS7_BINARY) x509 = X509.load_cert_bio(pp_cert_f) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp = BIO.MemoryBuffer() p7.write_der(tmp) p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() p7.write(out) return out.read()
def get_encrypt_ctx(self, receiver_name): """Return SMIME context for encryption.""" ck = ('E', receiver_name) if ck in self.cache: return self.cache[ck] # here we could add several certs crt = self.ks.load_cert_obj(receiver_name) x = X509.X509_Stack() x.push(crt) # SMIME setup sm = SMIME.SMIME() sm.set_x509_stack(x) sm.set_cipher(SMIME.Cipher('aes_128_cbc')) if CACHE_KEYS: self.cache[ck] = sm return sm
def encrypt(self, attributes): plaintext = '' for key, value in attributes.items(): plaintext += u'%s=%s\n' % (key, value) plaintext = plaintext.encode('utf-8') # Instantiate an SMIME object. s = SMIME.SMIME() # Load signer's key and cert. Sign the buffer. s.load_key_bio(BIO.openfile(PAYPAL_PRIVATE_KEY), BIO.openfile(PAYPAL_PUBLIC_KEY)) p7 = s.sign(BIO.MemoryBuffer(plaintext), flags=SMIME.PKCS7_BINARY) # Load target cert to encrypt the signed message to. x509 = X509.load_cert_bio(BIO.openfile(PAYPAL_PAYPAL_CERT)) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Create a temporary buffer. tmp = BIO.MemoryBuffer() # Write the signed message into the temporary buffer. p7.write_der(tmp) # Encrypt the temporary buffer. p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() p7.write(out) return out.read()
def _encrypt_data(self, data): """ Encrypt the form data. Refer to http://sandbox.rulemaker.net/ngps/m2/howto.smime.html """ # Don't import at top because these are only required if user wants encryption from M2Crypto import BIO, SMIME, X509 certid = self.settings["PUBLIC_CERT_ID"] # Assemble form data and encode in utf-8 raw = ["cert_id=%s" % certid] raw.extend([u"%s=%s" % (key, val) for key, val in data.items() if val]) raw = "\n".join(raw) raw = raw.encode("utf-8") self.log.debug('Encrypted Paypal data: %s' % raw) # make an smime object s = SMIME.SMIME() # load our public and private keys s.load_key_bio(BIO.openfile(self.localprikey), BIO.openfile(self.localpubkey)) # put the data in the buffer buf = BIO.MemoryBuffer(raw) # sign the text p7 = s.sign(buf, flags=SMIME.PKCS7_BINARY) # Load target cert to encrypt to. x509 = X509.load_cert_bio(BIO.openfile(self.paypalpubkey)) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher("des_ede3_cbc")) # save data to buffer tmp = BIO.MemoryBuffer() p7.write_der(tmp) # encrypt p7 = s.encrypt(tmp, flags=SMIME.PKCS7_BINARY) out = BIO.MemoryBuffer() # write into a new buffer p7.write(out) return out.read()
def to_smime_handler(raw_message, recipients=None): if recipients == None: recipients = to_addrs s = SMIME.SMIME() sk = X509.X509_Stack() normalized_recipient = [] for addr in recipients: addr_addr = email.utils.parseaddr(addr)[1].lower() cert_and_email = get_cert_for_email(addr_addr) if cert_and_email: (to_cert, normal_email) = cert_and_email log("Found cert " + to_cert + " for " + addr + ": " + normal_email) normalized_recipient.append( (email.utils.parseaddr(addr)[0], normal_email)) x509 = X509.load_cert(to_cert, format=X509.FORMAT_PEM) sk.push(x509) if len(normalized_recipient): s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('aes_192_cbc')) p7 = s.encrypt(BIO.MemoryBuffer(raw_message.as_string())) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: ' + from_addr + '\n') to_list = ",".join( [email.utils.formataddr(x) for x in normalized_recipient]) out.write('To: ' + to_list + '\n') if raw_message['Subject']: out.write('Subject: ' + raw_message['Subject'] + '\n') if cfg['default'].has_key( 'add_header') and cfg['default']['add_header'] == 'yes': out.write('X-GPG-Mailgate: Encrypted by GPG Mailgate\n') s.write(out, p7) log("Sending message from " + from_addr + " to " + str(recipients)) raw_msg = out.read() send_msg(raw_msg, recipients) else: log("Unable to find valid S/MIME recipient") send_msg(raw_message.as_string(), recipients) return None
def send(self, to, subject='None', message='None', attachments=None, cc=None, bcc=None, reply_to=None, encoding='utf-8', raw=False, headers={}): """ Sends an email using data specified in constructor Arguments: to: list or tuple of receiver addresses; will also accept single object subject: subject of the email message: email body text; depends on type of passed object: if 2-list or 2-tuple is passed: first element will be source of plain text while second of html text; otherwise: object will be the only source of plain text and html source will be set to None; If text or html source is: None: content part will be ignored, string: content part will be set to it, file-like object: content part will be fetched from it using it's read() method attachments: list or tuple of Mail.Attachment objects; will also accept single object cc: list or tuple of carbon copy receiver addresses; will also accept single object bcc: list or tuple of blind carbon copy receiver addresses; will also accept single object reply_to: address to which reply should be composed encoding: encoding of all strings passed to this method (including message bodies) headers: dictionary of headers to refine the headers just before sending mail, e.g. {'Return-Path' : '*****@*****.**'} Examples: #Send plain text message to single address: mail.send('*****@*****.**', 'Message subject', 'Plain text body of the message') #Send html message to single address: mail.send('*****@*****.**', 'Message subject', '<html>Plain text body of the message</html>') #Send text and html message to three addresses (two in cc): mail.send('*****@*****.**', 'Message subject', ('Plain text body', '<html>html body</html>'), cc=['*****@*****.**', '*****@*****.**']) #Send html only message with image attachment available from the message by 'photo' content id: mail.send('*****@*****.**', 'Message subject', (None, '<html><img src="cid:photo" /></html>'), Mail.Attachment('/path/to/photo.jpg' content_id='photo')) #Send email with two attachments and no body text mail.send('[email protected], 'Message subject', None, [Mail.Attachment('/path/to/fist.file'), Mail.Attachment('/path/to/second.file')]) Returns True on success, False on failure. Before return, method updates two object's fields: self.result: return value of smtplib.SMTP.sendmail() or GAE's mail.send_mail() method self.error: Exception message or None if above was successful """ def encode_header(key): if [c for c in key if 32 > ord(c) or ord(c) > 127]: return Header.Header(key.encode('utf-8'), 'utf-8') else: return key # encoded or raw text def encoded_or_raw(text): if raw: text = encode_header(text) return text if not isinstance(self.server, str): raise Exception('Server address not specified') if not isinstance(self.sender, str): raise Exception('Sender address not specified') if not raw: payload_in = MIMEMultipart.MIMEMultipart('mixed') else: # no encoding configuration for raw messages if isinstance(message, basestring): text = message.decode(encoding).encode('utf-8') else: text = message.read().decode(encoding).encode('utf-8') # No charset passed to avoid transport encoding # NOTE: some unicode encoded strings will produce # unreadable mail contents. payload_in = MIMEText.MIMEText(text) if to: if not isinstance(to, (list, tuple)): to = [to] else: raise Exception('Target receiver address not specified') if cc: if not isinstance(cc, (list, tuple)): cc = [cc] if bcc: if not isinstance(bcc, (list, tuple)): bcc = [bcc] if message is None: text = html = None elif isinstance(message, (list, tuple)): text, html = message elif message.strip().startswith('<html') and message.strip().endswith( '</html>'): text = self.server == 'gae' and message or None html = message else: text = message html = None if (not text is None or not html is None) and (not raw): attachment = MIMEMultipart.MIMEMultipart('alternative') if not text is None: if isinstance(text, basestring): text = text.decode(encoding).encode('utf-8') else: text = text.read().decode(encoding).encode('utf-8') attachment.attach(MIMEText.MIMEText(text, _charset='utf-8')) if not html is None: if isinstance(html, basestring): html = html.decode(encoding).encode('utf-8') else: html = html.read().decode(encoding).encode('utf-8') attachment.attach( MIMEText.MIMEText(html, 'html', _charset='utf-8')) payload_in.attach(attachment) if (attachments is None) or raw: pass elif isinstance(attachments, (list, tuple)): for attachment in attachments: payload_in.attach(attachment) else: payload_in.attach(attachments) ####################################################### # CIPHER # ####################################################### cipher_type = self.cipher_type sign = self.sign sign_passphrase = self.sign_passphrase encrypt = self.encrypt ####################################################### # GPGME # ####################################################### if cipher_type == 'gpg': if self.gpg_home: # Set GNUPGHOME environment variable to set home of gnupg import os os.environ['GNUPGHOME'] = self.gpg_home if not sign and not encrypt: self.error = "No sign and no encrypt is set but cipher type to gpg" return False # need a python-pyme package and gpgme lib from pyme import core, errors from pyme.constants.sig import mode ############################################ # sign # ############################################ if sign: import string core.check_version(None) pin = string.replace(payload_in.as_string(), '\n', '\r\n') plain = core.Data(pin) sig = core.Data() c = core.Context() c.set_armor(1) c.signers_clear() # search for signing key for From: for sigkey in c.op_keylist_all(self.sender, 1): if sigkey.can_sign: c.signers_add(sigkey) if not c.signers_enum(0): self.error = 'No key for signing [%s]' % self.sender return False c.set_passphrase_cb(lambda x, y, z: sign_passphrase) try: # make a signature c.op_sign(plain, sig, mode.DETACH) sig.seek(0, 0) # make it part of the email payload = MIMEMultipart.MIMEMultipart( 'signed', boundary=None, _subparts=None, **dict(micalg="pgp-sha1", protocol="application/pgp-signature")) # insert the origin payload payload.attach(payload_in) # insert the detached signature p = MIMEBase.MIMEBase("application", 'pgp-signature') p.set_payload(sig.read()) payload.attach(p) # it's just a trick to handle the no encryption case payload_in = payload except errors.GPGMEError: self.error = "GPG error: %s" return False ############################################ # encrypt # ############################################ if encrypt: core.check_version(None) plain = core.Data(payload_in.as_string()) cipher = core.Data() c = core.Context() c.set_armor(1) # collect the public keys for encryption recipients = [] rec = to[:] if cc: rec.extend(cc) if bcc: rec.extend(bcc) for addr in rec: c.op_keylist_start(addr, 0) r = c.op_keylist_next() if r is None: self.error = 'No key for [%s]' % addr return False recipients.append(r) try: # make the encryption c.op_encrypt(recipients, 1, plain, cipher) cipher.seek(0, 0) # make it a part of the email payload = MIMEMultipart.MIMEMultipart( 'encrypted', boundary=None, _subparts=None, **dict(protocol="application/pgp-encrypted")) p = MIMEBase.MIMEBase("application", 'pgp-encrypted') p.set_payload("Version: 1\r\n") payload.attach(p) p = MIMEBase.MIMEBase("application", 'octet-stream') p.set_payload(cipher.read()) payload.attach(p) except errors.GPGMEError: self.error = "GPG error: %s" return False ####################################################### # X.509 # ####################################################### elif cipher_type == 'x509': if not sign and not encrypt: self.error = "No sign and no encrypt is set but cipher type to x509" return False x509_sign_keyfile = self.x509_sign_keyfile if self.x509_sign_certfile: x509_sign_certfile = self.x509_sign_certfile else: # if there is no sign certfile we'll assume the # cert is in keyfile x509_sign_certfile = self.x509_sign_keyfile # crypt certfiles could be a string or a list x509_crypt_certfiles = self.x509_crypt_certfiles x509_nocerts = self.x509_nocerts # need m2crypto try: from M2Crypto import BIO, SMIME, X509 except Exception: self.error = "Can't load M2Crypto module" return False msg_bio = BIO.MemoryBuffer(payload_in.as_string()) s = SMIME.SMIME() # SIGN if sign: #key for signing try: s.load_key(x509_sign_keyfile, x509_sign_certfile, callback=lambda x: sign_passphrase) except Exception: self.error = "Something went wrong on certificate / private key loading: <%s>" % str( e) return False try: if x509_nocerts: flags = SMIME.PKCS7_NOCERTS else: flags = 0 if not encrypt: flags += SMIME.PKCS7_DETACHED p7 = s.sign(msg_bio, flags=flags) msg_bio = BIO.MemoryBuffer(payload_in.as_string( )) # Recreate coz sign() has consumed it. except Exception: self.error = "Something went wrong on signing: <%s> %s" return False # ENCRYPT if encrypt: try: sk = X509.X509_Stack() if not isinstance(x509_crypt_certfiles, (list, tuple)): x509_crypt_certfiles = [x509_crypt_certfiles] # make an encryption cert's stack for x in x509_crypt_certfiles: sk.push(X509.load_cert(x)) s.set_x509_stack(sk) s.set_cipher(SMIME.Cipher('des_ede3_cbc')) tmp_bio = BIO.MemoryBuffer() if sign: s.write(tmp_bio, p7) else: tmp_bio.write(payload_in.as_string()) p7 = s.encrypt(tmp_bio) except Exception: self.error = "Something went wrong on encrypting: <%s>" return False # Final stage in sign and encryption out = BIO.MemoryBuffer() if encrypt: s.write(out, p7) else: if sign: s.write(out, p7, msg_bio, SMIME.PKCS7_DETACHED) else: out.write('\r\n') out.write(payload_in.as_string()) out.close() st = str(out.read()) payload = message_from_string(st) else: # no cryptography process as usual payload = payload_in payload['From'] = encoded_or_raw(self.sender.decode(encoding)) origTo = to[:] if to: payload['To'] = encoded_or_raw(', '.join(to).decode(encoding)) if reply_to: payload['Reply-To'] = encoded_or_raw(reply_to.decode(encoding)) if cc: payload['Cc'] = encoded_or_raw(', '.join(cc).decode(encoding)) to.extend(cc) if bcc: to.extend(bcc) payload['Subject'] = encoded_or_raw(subject.decode(encoding)) payload['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) for k, v in headers.iteritems(): payload[k] = encoded_or_raw(v.decode(encoding)) result = {} try: if self.server == 'logging': logger.warn('email not sent\n%s\nFrom: %s\nTo: %s\nSubject: %s\n\n%s\n%s\n' % \ ('-'*40,self.sender, ', '.join(to),subject, text or html,'-'*40)) elif self.server == 'gae': xcc = dict() if cc: xcc['cc'] = cc if bcc: xcc['bcc'] = bcc if reply_to: xcc['reply_to'] = reply_to from google.appengine.api import mail attachments = attachments and [(a.my_filename, a.my_payload) for a in attachments if not raw] if attachments: result = mail.send_mail(sender=self.sender, to=origTo, subject=subject, body=text, html=html, attachments=attachments, **xcc) elif html and (not raw): result = mail.send_mail(sender=self.sender, to=origTo, subject=subject, body=text, html=html, **xcc) else: result = mail.send_mail(sender=self.sender, to=origTo, subject=subject, body=text, **xcc) else: smtp_args = self.server.split(':') if self.ssl: server = smtplib.SMTP_SSL(*smtp_args) else: server = smtplib.SMTP(*smtp_args) if self.tls and not self.ssl: server.ehlo() server.starttls() server.ehlo() if self.login: server.login(*self.login.split(':', 1)) result = server.sendmail(self.sender, to, payload.as_string()) server.quit() except Exception: self.result = result self.error = None return False self.result = result self.error = None return True
buf = makebuf(message) # Seed the PRNG. Rand.load_file('randpool.dat', -1) # Instantiate an SMIME object. s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert('sample_keys/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) # Set cipher: 3-key triple-DES in CBC mode. s.set_cipher(SMIME.Cipher('des_ede3_cbc')) # Encrypt the buffer. p7 = s.encrypt(buf) # Output p7 in mail-friendly format. out = BIO.MemoryBuffer() out.write('From: [email protected]\n') out.write('To: [email protected]\n') out.write('Subject: M2Crypto S/MIME testing\n') s.write(out, p7) stringEncrypted = str(out.read(), 'utf-8') print(stringEncrypted) with open('encrypt.p7', 'w') as outf: