def sign(self, sender_identity, message): """ Signs an email message. """ self.logger.debug("Signing message as %s" % sender_identity) s = SMIME.SMIME() signing_cert = BIO.MemoryBuffer(sender_identity.certificate.encode("UTF-8")) signing_key = BIO.MemoryBuffer(sender_identity.key.encode("UTF-8")) s.load_key_bio(signing_key, signing_cert) # extract the payload from the original message, construct a temporary # message without all the header info, and sign that message's string # representation payload_msg = self.extract_payload(message) content_to_sign = payload_msg.as_string() pkcs7_signed_data = s.sign( BIO.MemoryBuffer(content_to_sign.encode("UTF-8")), flags=SMIME.PKCS7_DETACHED, ) # get the PKCS7 object into a string payload = BIO.MemoryBuffer() s.write( payload, pkcs7_signed_data, BIO.MemoryBuffer(content_to_sign.encode("UTF-8")), flags=SMIME.PKCS7_DETACHED, ) pkcs7_string = payload.read() payload.close() signed_message = email.message_from_string(pkcs7_string.decode("UTF-8")) message.set_payload(signed_message.get_payload()) for header, value in list(signed_message.items()): del message[header] message[header] = value return message
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 sign_tra(self, tra): # Load cert and key s = SMIME.SMIME() s.load_key(self.credentials.key_path, self.credentials.crt_path) # Sign tra = BIO.MemoryBuffer(tra.encode('utf-8')) p7 = s.sign(tra) # Dump to e-Mail attachment format (don't ask) out = BIO.MemoryBuffer() s.write(out, p7) mail = out.read().decode('utf-8') # Unwrap signature msg = email.message_from_string(mail) for p in msg.walk(): if p.get_filename() == "smime.p7m": return p.get_payload(decode=False)
def smime_sign(key_path, cert_path, message): """ Sign message with given certificate and signing key :param str key_path: Path to the key file :param cert_path: Optional path to the certificate file :type cert_path: str or None :param message: Message to sign :type message: bytes or :class:`dpres_signature.manifest.Manifest` :returns: Signature :rtype: bytes """ # Instantiate an SMIME object; set it up; sign the buffer. key_path = _to_str_path(key_path) if cert_path: cert_path = _to_str_path(cert_path) # 'message' can be a byte string or a Manifest instance message = six.binary_type(message) smime = SMIME.SMIME() smime.load_key( keyfile=key_path, certfile=cert_path) message_buf = BIO.MemoryBuffer() message_buf.write(message) pkcs7 = smime.sign(message_buf, SMIME.PKCS7_DETACHED) # Must recreate message buffer, it was consumed by smime.sign() message_buf = BIO.MemoryBuffer() message_buf.write(message) # Destination buffer for combined message out = BIO.MemoryBuffer() # write message & signature to output buffer smime.write(out, pkcs7, message_buf) return out.read()
def sign(self, data, wwdrcert_data, cert_data, key_data, passphrase = None): """ https://github.com/devartis/passbook """ def passwordCallback(*args, **kwds): return passphrase wwdrcert_bio = SMIME.BIO.MemoryBuffer(wwdrcert_data) key_bio = SMIME.BIO.MemoryBuffer(key_data) cert_bio = SMIME.BIO.MemoryBuffer(cert_data) smime = SMIME.SMIME() wwdrcert = X509.load_cert_bio(wwdrcert_bio) stack = X509_Stack() stack.push(wwdrcert) smime.set_x509_stack(stack) smime.load_key_bio(key_bio, cert_bio, callback=passwordCallback) pk7 = smime.sign(SMIME.BIO.MemoryBuffer(data), flags = SMIME.PKCS7_DETACHED | SMIME.PKCS7_BINARY) pem = SMIME.BIO.MemoryBuffer() pk7.write(pem) der = ''.join(l.strip() for l in pem.read().split('----')[2].splitlines()).decode('base64') return der
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) p7 = s.sign(msg_bio, flags=SMIME.PKCS7_TEXT) 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 _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 sign_m2(keyfile, content): """ Sign content with a keyfile using M2Crypto """ # XXX kill once we can load the key directly from a buffer if not hasattr(keyfile, "name"): warnings.warn("Rewrapping keyfile into a temporary file. " "This may case the file to be written to insecure " "storage!") with NamedTemporaryFile() as kp: with StreamPositionRestore(kp): with StreamPositionRestore(keyfile): kp.write(keyfile.read()) return sign_m2(kp, content) try: # load intermediate certs if any stack = M2X509.X509_Stack() _, _, certificates = parse_keyfile(keyfile) for c in certificates: cert = M2X509.load_cert_string(c) # skip the main CA cert, as this must be built-in anyway if (cert.check_ca() and str(cert.get_issuer()) == str(cert.get_subject())): continue stack.push(cert) # actual signing smime = M2S.SMIME() smime.load_key(keyfile.name) smime.set_x509_stack(stack) pkcs7 = M2Buffer() smime.sign(M2Buffer(content), M2S.PKCS7_DETACHED | M2S.PKCS7_BINARY).write_der(pkcs7) return pkcs7.read() except (M2EVPError, ex): if re.search("ANY PRIVATE KEY", ex.message): raise ValueError("Key file does not contain a private key") raise ValueError("Signing failed. Wrong password?")
def create_signed_sample_mail(): multipart = MIMEMultipart() multipart.attach(MIMEText('Hello, i\'m a signed mail.')) smime = SMIME.SMIME() smime.load_key(SSL_KEY_FILE, SSL_CERT_FILE) p7 = smime.sign(BIO.MemoryBuffer(multipart.as_string()), SMIME.PKCS7_DETACHED) out_bio = BIO.MemoryBuffer() out_bio.write('From: [email protected]\n') out_bio.write('To: [email protected]\n') out_bio.write('Date: {}\n'.format(formatdate(localtime=True))) out_bio.write('Subject: Hello\n') data_bio = BIO.MemoryBuffer(multipart.as_string()) smime.write(out_bio, p7, data_bio) with open('signed.p7m', 'w') as signed: signed.write(out_bio.read())
def sign_tra(self, private_key, certificate): smime = SMIME.SMIME() ks = BIO.MemoryBuffer(private_key.encode('ascii')) cs = BIO.MemoryBuffer(certificate.encode('ascii')) bf = BIO.MemoryBuffer(str(self._create_tra())) out = BIO.MemoryBuffer() try: smime.load_key_bio(ks, cs) except Exception: raise Exception( 'Error en el formato del certificado o clave privada') sbf = smime.sign(bf) smime.write(out, sbf) head, body, end = out.read().split('\n\n') return body
def _createSignature(self, manifest, certificate, key, wwdr_certificate, password): def passwordCallback(*args, **kwds): return password smime = SMIME.SMIME() #we need to attach wwdr cert as X509 wwdrcert = X509.load_cert(wwdr_certificate) stack = X509_Stack() stack.push(wwdrcert) smime.set_x509_stack(stack) smime.load_key(key, certificate, callback=passwordCallback) pk7 = smime.sign(SMIME.BIO.MemoryBuffer(manifest), flags=SMIME.PKCS7_DETACHED | SMIME.PKCS7_BINARY) pem = SMIME.BIO.MemoryBuffer() pk7.write(pem) # convert pem to der der = ''.join(l.strip() for l in pem.read().split('-----')[2].splitlines()).decode('base64') return der
def test_sign(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() s.load_key('test/signer_key.pem', 'test/signer.pem') p7 = s.sign(buf, SMIME.PKCS7_DETACHED) assert len(buf) == 0 assert p7.type() == SMIME.PKCS7_SIGNED, 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-----', buf[-len('-----END PKCS7-----'):] assert len(buf) > len('-----END PKCS7-----') + len('-----BEGIN PKCS7-----') s.write(out, p7, BIO.MemoryBuffer(self.cleartext)) return out
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 verify_pkcs7(pkcs7_sig, document): try: # raw_sig = pkcs7_sig raw_sig = str(pkcs7_sig).encode('ascii') msg = document sm_obj = SMIME.SMIME() x509 = X509.load_cert( os.path.join(config.APP_STATIC, 'AWSpubkey')) # public key cert used by the remote # client when signing the message sk = X509.X509_Stack() sk.push(x509) sm_obj.set_x509_stack(sk) st = X509.X509_Store() st.load_info( os.path.join(config.APP_STATIC, 'AWSpubkey')) # Public cert for the CA which signed # the above certificate sm_obj.set_x509_store(st) # re-wrap signature so that it fits base64 standards cooked_sig = '\n'.join(raw_sig[pos:pos + 76] for pos in xrange(0, len(raw_sig), 76)) # cooked_sig = raw_sig # now, wrap the signature in a PKCS7 block sig = ("-----BEGIN PKCS7-----\n" + cooked_sig + "\n-----END PKCS7-----").encode('ascii') # and load it into an SMIME p7 object through the BIO I/O buffer: buf = BIO.MemoryBuffer(sig) p7 = SMIME.load_pkcs7_bio(buf) # finally, try to verify it: if dict(json.loads(sm_obj.verify(p7))) == dict(json.loads(msg)): return True else: return False except Exception as e: raise Exception("INVALID CLIENT MESSAGE SIGNATURE")
def sign_tra(tra, cert=CERT, privatekey=PRIVATEKEY, passphrase=""): "Firmar PKCS#7 el TRA y devolver CMS (recortando los headers SMIME)" if BIO: # Firmar el texto (tra) usando m2crypto (openssl bindings para python) buf = BIO.MemoryBuffer(tra) # Crear un buffer desde el texto #Rand.load_file('randpool.dat', -1) # Alimentar el PRNG s = SMIME.SMIME() # Instanciar un SMIME # soporte de contraseña de encriptación (clave privada, opcional) callback = lambda *args, **kwarg: passphrase # Cargar clave privada y certificado if privatekey.startswith("-----BEGIN RSA PRIVATE KEY-----"): key_bio = BIO.MemoryBuffer(privatekey) crt_bio = BIO.MemoryBuffer(cert) s.load_key_bio(key_bio, crt_bio, callback) # (desde buffer) elif os.path.exists(privatekey) and os.path.exists(cert): s.load_key(privatekey, cert, callback) # (desde archivo) else: raise RuntimeError("Archivos no encontrados: %s, %s" % (privatekey, cert)) p7 = s.sign(buf, 0) # Firmar el buffer out = BIO.MemoryBuffer() # Crear un buffer para la salida s.write(out, p7) # Generar p7 en formato mail #Rand.save_file('randpool.dat') # Guardar el estado del PRNG's # extraer el cuerpo del mensaje (parte firmada) msg = email.message_from_string(out.read()) for part in msg.walk(): filename = part.get_filename() if filename == "smime.p7m": # es la parte firmada? return part.get_payload(decode=False) # devolver CMS else: # Firmar el texto (tra) usando OPENSSL directamente out = Popen([ "openssl", "smime", "-sign", "-signer", cert, "-inkey", privatekey, "-outform", "DER", "-nodetach" ], stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(tra)[0] return b64encode(out)
def test_verify(self): s = SMIME.SMIME() 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, data = SMIME.smime_load_pkcs7_bio(self.signed) self.assertIsInstance(p7, SMIME.PKCS7, p7) v = s.verify(p7, data) self.assertEqual(v, self.cleartext) t = p7.get0_signers(sk) self.assertEqual(len(t), 1) self.assertEqual(t[0].as_pem(), x509.as_pem(), t[0].as_text())
def verifySignature(signaturePkcs7, hash, chainOfTrust): # see also in AM: src/crypto-lib/signature.cpp / Signature::verify() s = SMIME.SMIME() bioSignature = BIO.MemoryBuffer(data=base64.decodestring(signaturePkcs7)) signature = SMIME.load_pkcs7_bio(bioSignature) bioHash = BIO.MemoryBuffer(data=hash) certChain = X509.X509_Store() for trustedCert in chainOfTrust: bioCert = BIO.MemoryBuffer(data=trustedCert) while len(bioCert): cert = X509.load_cert_bio(bioCert, X509.FORMAT_PEM) certChain.add_x509(cert) s.set_x509_store(certChain) s.set_x509_stack(X509.X509_Stack()) s.verify(signature, bioHash, SMIME.PKCS7_NOCHAIN)
def test_verify(self): s = SMIME.SMIME() x509 = X509.load_cert('test/signer.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('test/ca.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7_bio(self.signed) assert isinstance(p7, SMIME.PKCS7), p7 v = s.verify(p7, data) assert v == self.cleartext t = p7.get0_signers(sk) assert len(t) == 1 assert t[0].as_pem() == x509.as_pem(), t[0].as_text()
def test_detailed_error_message(self): from M2Crypto import SMIME, X509 s = SMIME.SMIME() x509 = X509.load_cert('tests/recipient.pem') sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) st = X509.X509_Store() st.load_info('tests/recipient.pem') s.set_x509_store(st) p7, data = SMIME.smime_load_pkcs7('tests/sample-p7.pem') self.assertIsInstance(p7, SMIME.PKCS7, p7) try: s.verify(p7, data) except SMIME.PKCS7_Error as e: self.assertRegexpMatches(str(e), "unable to get local issuer certificate", "Not received expected error message")
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 sign_tra(tra, cert=CERT, privatekey=PRIVATEKEY, passphrase=""): "Sign using PKCS#7 the TRA and return CMS (trimming SMIME headers)" # Sign the text (tra) using m2crypto (openssl bindings for python) buf = BIO.MemoryBuffer(tra) # create the buffer from the file # Rand.load_file('randpool.dat', -1) # seed the PRNG s = SMIME.SMIME() # instantiate the SMIME # support encription passwords (for private key, optional) callback = lambda *args, **kwarg: passphrase # load the private key and certificate s.load_key(privatekey, cert, callback) # (frmo file) p7 = s.sign(buf, 0) # Sign the buffer out = BIO.MemoryBuffer() # Instantiathe the output buffer s.write(out, p7) # Generate p7 in mail format # Rand.save_file('randpool.dat') # Store the PRNG's state # extract the message body (signed part) msg = email.message_from_string(out.read()) for part in msg.walk(): filename = part.get_filename() if filename == "smime.p7m": # is the signed part? return part.get_payload(decode=False) # return the CMS
def decrypt(input_bio, private_key, cert, keyring_source, type): """ Decrypts the input data with the private key and the certificate from keyring source. @type input_bio: M2Crypto.BIO @param input_bio: input data to sign. @type private_key: filepath or M2Crypto.BIO or M2Crypto.EVP.PKey @param private_key: recipient private key reference, could be from file, from memory or from pkcs11 smartcard, based on keyring_soruce input parameter. @type cert: filepath or M2Crypto.BIO or M2Crypto.X509.X509 @param cert: recipient certificate, could be from filepath, 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 decrypter settings. Ammitted values are: file, memory, pkcs11. @type type: str @keyword type: specifies the type of input PKCS#7 data: PEM or DER @rtype: str @return: the decrypted data in plain form. @raise BadPKCS7Type: The requested PKCS#7 type is not valid. Ammitted values are PEM and DER. """ decrypter = SMIME.SMIME() set_keyring(decrypter, private_key, cert, keyring_source) try: if type == 'PEM': p7, data_bio = SMIME.smime_load_pkcs7_bio(input_bio) elif type == 'DER': p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(input_bio._ptr()), 1) else: logging.error('pkcs7 type error: unknown type') raise BadPKCS7Type('unknown type: ' + type + '; possible values: PEM, DER') except SMIME.SMIME_Error, e: logging.error('load pkcs7 error: ' + str(e)) pass
def upload_encr(): mdm_ca = get_ca() upl_encrypt = unhexlify(request.files['upload_encr_file'].stream.read()) s = SMIME.SMIME() bio = BIO.MemoryBuffer(upl_encrypt) s.load_key_bio(BIO.MemoryBuffer(mdm_ca.get_private_key().to_pem()), BIO.MemoryBuffer(mdm_ca.get_cacert().to_pem())) p7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(bio._ptr())) out = s.decrypt(p7) response = make_response(out) response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Content-Disposition'] = 'attachment; filename=mdm_signed_request.%s.plist.b64' % datetime.datetime.now( ).strftime('%Y%m%d_%H%M%S') return response
def createsmime(msg, from_key, from_cert): """ This part of code is a mix of code from: http://svn.osafoundation.org/m2crypto/trunk/doc/howto.smime.html """ s = SMIME.SMIME() s.load_key(from_key, from_cert) sk = X509.X509_Stack() x509 = X509.load_cert(settings.AUTH_CERT) sk.push(x509) s.set_x509_stack(sk) msg_bio = BIO.MemoryBuffer(msg) p7 = s.sign(msg_bio) msg_bio = BIO.MemoryBuffer(msg) # Recreate coz sign() has consumed it. out = BIO.MemoryBuffer() s.write(out, p7, msg_bio) out.close() return out.read()
def sign(input_bio, private_key, cert, keyring_source, type): """ Signs the input data with the private key and the certificate from keyring source. @type input_bio: M2Crypto.BIO @param input_bio: input data to sign. @type private_key: filepath or M2Crypto.BIO or M2Crypto.EVP.PKey @param private_key: sender private key reference, could be from file, from memory or from pkcs11 smartcard, based on keyring_soruce input parameter. @type cert: filepath or M2Crypto.BIO or M2Crypto.X509.X509 @param cert: sender certificate, could be from filepath, 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 signer settings. Ammitted values are: file, memory, pkcs11. @type type: str @keyword type: specifies the type of output PKCS#7 data: PEM or DER @rtype: M2Crypto.SMIME.PKCS7 @return: the PKCS#7 signed data in PEM or DER format. """ signer = SMIME.SMIME() set_keyring(signer, private_key, cert, keyring_source) Rand.load_file('randpool.dat', -1) try: if type == 'PEM': p7 = signer.sign(input_bio, flags=SMIME.PKCS7_DETACHED) elif type == 'DER': p7 = signer.sign(input_bio) else: logging.error('pkcs7 type error: unknown type') raise BadPKCS7Type('unknown type: ' + type + '; possible values: PEM, DER') except SMIME.SMIME_Error, e: logging.error('smime error: ' + str(e)) raise
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)) seed_prng() try: p7 = encrypter.encrypt(input_bio) except SMIME.SMIME_Error as e: logging.error('smime error: ' + str(e)) raise except SMIME.PKCS7_Error as e: logging.error('pkcs7 error: ' + str(e)) raise return p7
def test_load_bad(self): s = SMIME.SMIME() with self.assertRaises(EVP.EVPError): s.load_key('tests/signer.pem', 'tests/signer.pem') with self.assertRaises(BIO.BIOError): SMIME.load_pkcs7('nosuchfile-dfg456') with self.assertRaises(SMIME.PKCS7_Error): SMIME.load_pkcs7('tests/signer.pem') with self.assertRaises(SMIME.PKCS7_Error): SMIME.load_pkcs7_bio(BIO.MemoryBuffer(b'no pkcs7')) with self.assertRaises(BIO.BIOError): SMIME.load_pkcs7_der('nosuchfile-dfg456') with self.assertRaises(SMIME.PKCS7_Error): SMIME.load_pkcs7_der('tests/signer.pem') with self.assertRaises(SMIME.PKCS7_Error): SMIME.load_pkcs7_bio_der(BIO.MemoryBuffer(b'no pkcs7')) with self.assertRaises(SMIME.SMIME_Error): SMIME.smime_load_pkcs7('tests/signer.pem') with self.assertRaises(SMIME.SMIME_Error): SMIME.smime_load_pkcs7_bio(BIO.MemoryBuffer(b'no pkcs7'))
def smime(self, cr, uid, ids, message, context=None): """ Sign message in SMIME format. """ r = {} for cert in self.browse(cr, uid, ids): #if cert.status == 'valid': # EXTRANGE: Invalid certificates can be used for sign! if True: smime = SMIME.SMIME() ks = BIO.MemoryBuffer(cert.pairkey_id.key.encode('ascii')) cs = BIO.MemoryBuffer(cert.crt.encode('ascii')) bf = BIO.MemoryBuffer(str(message)) out = BIO.MemoryBuffer() try: smime.load_key_bio(ks, cs) except EVP.EVPError: raise osv.except_osv(_('Error in Key and Certificate strings !'), _('Please check if private key and certificate are in ASCII PEM format.')) sbf = smime.sign(bf) smime.write(out, sbf) r[cert.id] = out.read() else: raise osv.except_osv(_('This certificate is not ready to sign any message !'), _('Please set a certificate to continue. You must send your certification request to a authoritative certificator to get one, or execute a self sign certification')) return r