def create_signature_block(openssl_digest, certificate, private_key, data): """Produces a signature block for the data. Reference --------- http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures Note: Oracle does not specify the content of the "signature file block", friendly saying that "These are binary files not intended to be interpreted by humans". :param openssl_digest: alrogithm known to OpenSSL used to digest the data :type openssl_digest: str TODO: it is not used. M2Crypto cannot pass the signing digest. :param certificate: filename of the certificate file (PEM format) :type certificate: str :param private_key:filename of private key used to sign (PEM format) :type private_key: str :param data: the content to be signed :type data: str :returns: content of the signature block file as produced by jarsigner :rtype: str """ smime = SMIME.SMIME() smime.load_key_bio(BIO.openfile(private_key), BIO.openfile(certificate)) pkcs7 = smime.sign(BIO.MemoryBuffer(data), flags=SMIME.PKCS7_BINARY) tmp = BIO.MemoryBuffer() pkcs7.write_der(tmp) return tmp.read()
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: # @@@ 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') # 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()
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 test_load_bio(self): bio = BIO.openfile('tests/x509.pem') bio2 = BIO.openfile('tests/x509.der') x509 = X509.load_cert_bio(bio) x5092 = X509.load_cert_bio(bio2, format=X509.FORMAT_DER) assert x509.as_text() == x5092.as_text() assert x509.as_pem() == x5092.as_pem() assert x509.as_der() == x5092.as_der() return
def test_load_bio(self): bio = BIO.openfile('tests/x509.pem') bio2 = BIO.openfile('tests/x509.der') x509 = X509.load_cert_bio(bio) x5092 = X509.load_cert_bio(bio2, format=X509.FORMAT_DER) self.assertRaises(ValueError, X509.load_cert_bio, bio2, format=45678) assert x509.as_text() == x5092.as_text() assert x509.as_pem() == x5092.as_pem() assert x509.as_der() == x5092.as_der() return
def test_load_bio(self): with BIO.openfile('tests/x509.pem') as bio: with BIO.openfile('tests/x509.der') as bio2: x509 = X509.load_cert_bio(bio) x5092 = X509.load_cert_bio(bio2, format=X509.FORMAT_DER) with self.assertRaises(ValueError): X509.load_cert_bio(bio2, format=45678) self.assertEqual(x509.as_text(), x5092.as_text()) self.assertEqual(x509.as_pem(), x5092.as_pem()) self.assertEqual(x509.as_der(), x5092.as_der())
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 setUp(self): s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(BIO.MemoryBuffer('some text')) self.filename = 'tests/sig.p7' f = BIO.openfile(self.filename, 'wb') assert p7.write(f) == 1 f.close() self.filenameSmime = 'tests/sig.p7s' f = BIO.openfile(self.filenameSmime, 'wb') assert s.write(f, p7, BIO.MemoryBuffer('some text')) == 1 f.close()
def setUp(self): s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(BIO.MemoryBuffer('some text')) self.filename = 'tests/sig.p7' f = BIO.openfile(self.filename, 'wb') self.assertEqual(p7.write(f), 1) f.close() p7 = s.sign(BIO.MemoryBuffer('some text'), SMIME.PKCS7_DETACHED) self.filenameSmime = 'tests/sig.p7s' f = BIO.openfile(self.filenameSmime, 'wb') self.assertEqual(s.write(f, p7, BIO.MemoryBuffer('some text')), 1) f.close()
def setUp(self): s = SMIME.SMIME() s.load_key("tests/signer_key.pem", "tests/signer.pem") p7 = s.sign(BIO.MemoryBuffer("some text")) self.filename = "tests/sig.p7" f = BIO.openfile(self.filename, "wb") assert p7.write(f) == 1 f.close() p7 = s.sign(BIO.MemoryBuffer("some text"), SMIME.PKCS7_DETACHED) self.filenameSmime = "tests/sig.p7s" f = BIO.openfile(self.filenameSmime, "wb") assert s.write(f, p7, BIO.MemoryBuffer("some text")) == 1 f.close()
def setUp(self): s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(BIO.MemoryBuffer(b'some text')) self.filename = 'tests/sig.p7' with BIO.openfile(self.filename, 'wb') as f: self.assertEqual(p7.write(f), 1) self.filename_der = 'tests/sig.p7.der' with BIO.openfile(self.filename_der, 'wb') as f: self.assertEqual(p7.write_der(f), 1) p7 = s.sign(BIO.MemoryBuffer(b'some text'), SMIME.PKCS7_DETACHED) self.filenameSmime = 'tests/sig.p7s' with BIO.openfile(self.filenameSmime, 'wb') as f: self.assertEqual(s.write(f, p7, BIO.MemoryBuffer(b'some text')), 1)
def load_request(file, format=FORMAT_PEM): """ Load certificate request from file. @type file: string @param file: Name of file containing certificate request in either PEM or DER format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the file to be loaded, either PEM or DER. @rtype: M2Crypto.X509.Request @return: M2Crypto.X509.Request object. """ f = BIO.openfile(file) if format == FORMAT_PEM: cptr = m2.x509_req_read_pem(f.bio_ptr()) elif format == FORMAT_DER: cptr = m2.d2i_x509_req(f.bio_ptr()) else: raise ValueError( "Unknown filetype. Must be either FORMAT_PEM or FORMAT_DER") f.close() if cptr is None: raise X509Error(Err.get_error()) return Request(cptr, 1)
def load_session(pemfile): f = BIO.openfile(pemfile) cptr = m2.ssl_session_read_pem(f.bio_ptr()) f.close() if cptr is None: raise Err.get_error() return Session(cptr, 1)
def load_session(pemfile): # type: (AnyStr) -> Session with BIO.openfile(pemfile) as f: cptr = m2.ssl_session_read_pem(f.bio_ptr()) if cptr is None: raise SSLError(Err.get_error()) return Session(cptr, 1)
def load_cert(file, format=FORMAT_PEM): """ Load certificate from file. @type file: string @param file: Name of file containing certificate in either DER or PEM format. @type format: int, either FORMAT_PEM or FORMAT_DER @param format: Describes the format of the file to be loaded, either PEM or DER. @rtype: M2Crypto.X509.X509 @return: M2Crypto.X509.X509 object. """ bio = BIO.openfile(file) if format == FORMAT_PEM: return load_cert_bio(bio) elif format == FORMAT_DER: cptr = m2.d2i_x509(bio._ptr()) if cptr is None: raise X509Error(Err.get_error()) return X509(cptr, _pyfree=1) else: raise ValueError( "Unknown format. Must be either FORMAT_DER or FORMAT_PEM")
def verify_signature_block(certificate_file, content_file, signature): """Verifies the 'signature' over the 'content', trusting the 'certificate'. :param certificate_file: the trusted certificate (PEM format) :type certificate_file: str :param content_file: The signature should match this content :type content_file: str :param signature: data (DER format) subject to check :type signature: str :return: Error message, or None if the signature validates. :rtype: str """ sig_bio = BIO.MemoryBuffer(signature) pkcs7 = SMIME.PKCS7(m2.pkcs7_read_bio_der(sig_bio._ptr()), 1) signers_cert_stack = pkcs7.get0_signers(X509.X509_Stack()) trusted_cert_store = X509.X509_Store() trusted_cert_store.load_info(certificate_file) smime = SMIME.SMIME() smime.set_x509_stack(signers_cert_stack) smime.set_x509_store(trusted_cert_store) data_bio = BIO.openfile(content_file) try: smime.verify(pkcs7, data_bio) except SMIME.PKCS7_Error, message: return "Signature verification error: %s" % message
def create_signature_block(openssl_digest, certificate, private_key, extra_certs, data): """ Produces a signature block for the data. Reference --------- http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures Note: Oracle does not specify the content of the "signature file block", friendly saying that "These are binary files not intended to be interpreted by humans". :param openssl_digest: alrogithm known to OpenSSL used to digest the data :type openssl_digest: str :param certificate: filename of the certificate file (PEM format) :type certificate: str :param private_key:filename of private key used to sign (PEM format) :type private_key: str :param extra_certs: additional certificates to embed into the signature (PEM format) :type extra_certs: array of filenames :param data: the content to be signed :type data: bytes :returns: content of the signature block file as produced by jarsigner :rtype: bytes """ # noqa smime = SMIME.SMIME() with BIO.openfile(private_key) as k, BIO.openfile(certificate) as c: smime.load_key_bio(k, c) if extra_certs is not None: # Could we use just X509.new_stack_from_der() instead? stack = X509.X509_Stack() for cert in extra_certs: stack.push(X509.load_cert(cert)) smime.set_x509_stack(stack) pkcs7 = smime.sign(BIO.MemoryBuffer(data), algo=openssl_digest, flags=(SMIME.PKCS7_BINARY | SMIME.PKCS7_DETACHED | SMIME.PKCS7_NOATTR)) tmp = BIO.MemoryBuffer() pkcs7.write_der(tmp) return tmp.read()
def save_pem(self, filename): # type: (AnyStr) -> int """ :param filename: name of the file to be loaded :return: 1 for success or 0 for failure """ with BIO.openfile(filename, 'wb') as bio: return m2.x509_write_pem(bio.bio_ptr(), self.x509)
def load_session(pemfile): f = BIO.openfile(pemfile) cptr = m2.ssl_session_read_pem(f.bio_ptr()) f.close() if cptr is None: from M2Crypto.SSL import SSLError raise SSLError(Err.get_error()) return Session(cptr, 1)
def save_key_der(self, file): """ Save the key pair to a file in DER format. @type file: str @param file: Filename to save key to """ bio = BIO.openfile(file, 'wb') return self.save_key_der_bio(bio)
def save_pub_key(self, file): """ Save the public key to a file in PEM format. @type file: string @param file: Name of file to save key to. """ bio = BIO.openfile(file, 'wb') return m2.ec_key_write_pubkey(self.ec, bio._ptr())
def save_pub_key(self, file): # type: (AnyStr) -> int """ Save the public key to a filename in PEM format. :param file: Name of filename to save key to. """ with BIO.openfile(file, 'wb') as bio: return m2.ec_key_write_pubkey(self.ec, bio._ptr())
def save_key_der(self, file): # type: (AnyStr) -> int """ Save the key pair to a file in DER format. :param file: Filename to save key to """ with BIO.openfile(file, 'wb') as bio: return self.save_key_der_bio(bio)
def set_tmp_dh(self, dhpfile): """Load ephemeral DH parameters into the context. @param dhpfile: File object containing the PEM-encoded DH parameters. @type dhpfile: str """ f = BIO.openfile(dhpfile) dhp = m2.dh_read_parameters(f.bio_ptr()) return m2.ssl_ctx_set_tmp_dh(self.ctx, dhp)
def set_tmp_dh(self, dhpfile): # type: (AnyStr) -> int """Load ephemeral DH parameters into the context. @param dhpfile: Filename of the file containing the PEM-encoded DH parameters. """ f = BIO.openfile(dhpfile) dhp = m2.dh_read_parameters(f.bio_ptr()) return m2.ssl_ctx_set_tmp_dh(self.ctx, dhp)
def _sign_RS(self, alg, header, sbs): priv_key_u = self._config.get('jws.rsa_key_path', None) if priv_key_u is None: raise(JWSException("No private key found for RSA signature")) bio = BIO.openfile(priv_key_u) rsa = RSA.load_key_bio(bio) if not rsa.check_key(): raise(JWSException("Invalid key specified")) digest = self._get_sha(alg[2:])(sbs).digest() signature = rsa.sign_rsassa_pss(digest) return '%s.%s' % (sbs, base64.urlsafe_b64encode(signature))
def load_pub_key(file): # type: (AnyStr) -> RSA_pub """ Load an RSA public key from file. :param file: Name of file containing RSA public key in PEM format. :return: M2Crypto.RSA.RSA_pub object. """ with BIO.openfile(file) as bio: return load_pub_key_bio(bio)
def load_pub_key(file): # type: (AnyStr) -> EC_pub """ Load an EC public key from filename. @param file: Name of filename containing EC public key in PEM format. @return: M2Crypto.EC.EC_pub object. """ with BIO.openfile(file) as bio: return load_pub_key_bio(bio)
def from_pem_data(cls, data=None, filename=None): """Alternative constructor for loading from PEM format data.""" self = cls.__new__(cls) if data is not None: bio = BIO.MemoryBuffer(str(data)) elif filename is not None: bio = BIO.openfile(filename) else: msg = "Please specify either 'data' or 'filename' argument." raise ValueError(msg) self.keyobj = self.KEY_MODULE.load_pub_key_bio(bio) return self
def load_pub_key(file): """ Load an EC public key from file. @type file: string @param file: Name of file containing EC public key in PEM format. @rtype: M2Crypto.EC.EC_pub @return: M2Crypto.EC.EC_pub object. """ bio = BIO.openfile(file) return load_pub_key_bio(bio)
def test_load_pkcs7_bio(self): f = open(self.filename, 'rb') buf = BIO.MemoryBuffer(f.read()) f.close() self.assertEqual(SMIME.load_pkcs7_bio(buf).type(), SMIME.PKCS7_SIGNED)
def do_POST(self): # get public key pub_key_url = '' try: pub_key_url_base64 = self.headers['x-oss-pub-key-url'] pub_key_url = pub_key_url_base64.decode('base64') url_reader = urllib2.urlopen(pub_key_url) pub_key = url_reader.read() except Exception as e: logging.error('exception catched, pub_key_url : ' + pub_key_url) logging.error('Get pub key failed!') logging.error(e) self.send_response(400) self.end_headers() return # get authorization authorization_base64 = self.headers['authorization'] authorization = authorization_base64.decode('base64') # get callback body content_length = self.headers['content-length'] callback_body = self.rfile.read(int(content_length)) # compose authorization string auth_str = '' pos = self.path.find('?') if -1 == pos: auth_str = self.path + '\n' + callback_body else: auth_str = urllib2.unquote( self.path[0:pos]) + self.path[pos:] + '\n' + callback_body # verify authorization auth_md5 = md5.new(auth_str).digest() bio = BIO.MemoryBuffer(pub_key) rsa_pub = RSA.load_pub_key_bio(bio) try: result = rsa_pub.verify(auth_md5, authorization, 'md5') except Exception as e: logging.error('exception catched when rsa_pub.verify') logging.error(e) result = False if not result: logging.error('Authorization verify failed!') logging.error('Public key : %s' % (pub_key)) logging.error('Auth string : %s' % (auth_str)) self.send_response(400) self.end_headers() return # do something accoding to callback_body if callback_body: if type(callback_body) == str: list_data = callback_body.split('&') dict_data = {} for _ in list_data: kv = _.split('=') dict_data[kv[0]] = kv[1] else: dict_callback_body = json.loads(callback_body.decode('base64')) callbackUrl = dict_callback_body.get('callbackUrl') valid = callbackUrl and callbackUrl in LIST_VALID_CALLBACK_URL callbackBody = dict_callback_body.get('callbackBody') list_data = callbackBody.split('&') dict_data = {} for _ in list_data: kv = _.split('=') dict_data[kv[0]] = kv[1] logging.debug("dict_data:{}".format(dict_data)) # response to OSS resp_body = '{"Status":"OK"}' self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(resp_body))) self.end_headers() self.wfile.write(resp_body)
def test_sign_nondefault_digest(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') p7 = s.sign(buf, flags=SMIME.PKCS7_DETACHED, algo='sha512') self.assertEqual(p7.type(), SMIME.PKCS7_SIGNED)
def test_loadkey_bio(self): keybio = BIO.MemoryBuffer(open(self.privkey).read()) rsa = RSA.load_key_bio(keybio) assert len(rsa) == 1024 assert rsa.e == '\000\000\000\003\001\000\001' # aka 65537 aka 0xf4 assert rsa.check_key() == 1
#!/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 as_text(self): buf = BIO.MemoryBuffer() m2.ssl_session_print(buf.bio_ptr(), self.session) return buf.read_all()
def test_write_pkcs7_der(self): buf = BIO.MemoryBuffer() self.assertEqual(SMIME.load_pkcs7(self.filename).write_der(buf), 1) s = buf.read() assert len(s) in (1188, 1204, 1433, 1243, 1263, 1148, 1168), len(s)
def run(self): """Run analysis. @return: analysis results dict or None. """ if not os.path.exists(self.file_path): return None try: self.pe = pefile.PE(self.file_path) except pefile.PEFormatError: return None results = {} results["peid_signatures"] = self._get_peid_signatures() results["pe_imports"] = self._get_imported_symbols() results["pe_exports"] = self._get_exported_symbols() results["pe_dirents"] = self._get_directory_entries() results["pe_sections"] = self._get_sections() results["pe_overlay"] = self._get_overlay() results["pe_resources"] = self._get_resources() results["pe_icon"] = self._get_icon() results["pe_versioninfo"] = self._get_versioninfo() results["pe_imphash"] = self._get_imphash() results["pe_timestamp"] = self._get_timestamp() results["imported_dll_count"] = len( [x for x in results["pe_imports"] if x.get("dll")]) if HAVE_CRYPTO: address = self.pe.OPTIONAL_HEADER.DATA_DIRECTORY[ pefile.DIRECTORY_ENTRY[ 'IMAGE_DIRECTORY_ENTRY_SECURITY']].VirtualAddress #check if file is digitally signed if address == 0: return results signature = self.pe.write()[address + 8:] bio = BIO.MemoryBuffer(signature) if bio: swig_pkcs7 = m2.pkcs7_read_bio_der(bio.bio_ptr()) if swig_pkcs7: p7 = SMIME.PKCS7(swig_pkcs7) xst = p7.get0_signers(X509.X509_Stack()) results["digital_signers"] = [] if xst: for cert in xst: sn = cert.get_serial_number() sha1_fingerprint = cert.get_fingerprint( 'sha1').lower() md5_fingerprint = cert.get_fingerprint( 'md5').lower() subject_str = str(cert.get_subject()) cn = subject_str[subject_str.index("/CN=") + len("/CN="):] results["digital_signers"].append({ "sn": str(sn), "cn": cn, "sha1_fingerprint": sha1_fingerprint, "md5_fingerprint": md5_fingerprint }) return results
def rsa_gen_keys(): rsa = M2Crypto.RSA.gen_key(1024, 65537) bio = BIO.MemoryBuffer() rsa.save_pub_key_bio(bio) rsa.save_key_bio(bio, cipher=None) return bio
def key_to_pem(self): "Convert a key to the PEM format." bio = BIO.MemoryBuffer() self.ec.save_key_bio(bio, None, lambda *args: "") return bio.read_all()
def key_from_pem(self, pem): "Get the EC from a public PEM." return EC.load_pub_key_bio(BIO.MemoryBuffer(pem))
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 not privatekey.startswith("-----BEGIN RSA PRIVATE KEY-----"): # leer contenido desde archivo (evitar problemas Applink / MSVCRT) if os.path.exists(privatekey) and os.path.exists(cert): privatekey = open(privatekey).read() cert = open(cert).read() else: raise RuntimeError("Archivos no encontrados: %s, %s" % (privatekey, cert)) # crear buffers en memoria de la clave privada y certificado: key_bio = BIO.MemoryBuffer(privatekey.encode('utf8')) crt_bio = BIO.MemoryBuffer(cert.encode('utf8')) s.load_key_bio(key_bio, crt_bio, callback) # (desde buffer) 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().decode('utf8')) 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 try: if sys.platform.startswith("linux"): openssl = "openssl" else: if sys.maxsize <= 2**32: openssl = r"c:\OpenSSL-Win32\bin\openssl.exe" else: openssl = r"c:\OpenSSL-Win64\bin\openssl.exe" # NOTE: workaround if certificate is not already stored in a file # SECURITY WARNING: the private key will be exposed a bit in /tmp # (in theory only for the current user) if cert.startswith("-----BEGIN CERTIFICATE-----"): cert_f = NamedTemporaryFile() cert_f.write(cert.encode('utf-8')) cert_f.flush() cert = cert_f.name else: cert_f = None if privatekey.startswith("-----BEGIN RSA PRIVATE KEY-----"): key_f = NamedTemporaryFile() key_f.write(privatekey.encode('utf-8')) key_f.flush() privatekey = key_f.name else: key_f = None try: out = Popen([ openssl, "smime", "-sign", "-signer", cert, "-inkey", privatekey, "-outform", "DER", "-nodetach" ], stdin=PIPE, stdout=PIPE, stderr=PIPE).communicate(tra)[0] finally: # close temp files to delete them (just in case): if cert_f: cert_f.close() if key_f: key_f.close() return b64encode(out).decode("utf8") except OSError as e: if e.errno == 2: warnings.warn( "El ejecutable de OpenSSL no esta disponible en el PATH") raise
def test_u2f_unsupported_openssl_missing_curve(self): """ Try registration with an OpenSSL missing the NIST P-256 curve and check the error messages """ skip_test = True # Only allow OpenSSL >=1.0.0 with missing EC support version_text = m2.OPENSSL_VERSION_TEXT match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text) if match is None: # Fail on unknown OpenSSL version string format self.fail("Could not detect OpenSSL version - unknown version string format: '%s'" % version_text) else: if match.group('version')[0] != '0': # Only run test on missing NIST P-256 curve support try: EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM)) except ValueError: skip_test = False if skip_test: self.skipTest( "This test can only be run with OpenSSL missing the " "NIST P-256 curve!" ) # Initial token registration step response_registration1 = self.get_json_body(self._registration1()) # check for status and value self.assertIn('result', response_registration1, "Response: %r" % response_registration1) self.assertIn('status', response_registration1['result'], "Response: %r" % response_registration1) self.assertTrue(response_registration1['result']['status']) self.assertIn('value', response_registration1['result'], "Response: %r" % response_registration1) self.assertTrue(response_registration1['result']['value']) # check detail object containing serial and registerrequest self.assertIn('detail', response_registration1, "Response: %r" % response_registration1) # check for correct serial self.assertIn('serial', response_registration1['detail'], "Response: %r" % response_registration1) self.assertEqual(response_registration1['detail']['serial'][:3], "U2F") # check for correct registerrequest object self.assertIn('registerrequest', response_registration1['detail'], "Response: %r" % response_registration1) self.assertIn('challenge', response_registration1['detail']['registerrequest'], "Response: %r" % response_registration1) # check for non-empty and correctly-padded challenge self.assertNotEqual(response_registration1['detail']['registerrequest']['challenge'], '') self.assertEqual(len(response_registration1['detail']['registerrequest']['challenge']) % 4, 0) self.assertIn('version', response_registration1['detail']['registerrequest'], "Response: %r" % response_registration1) # only U2F_V2 is supported right now self.assertEqual(response_registration1['detail']['registerrequest']['version'], "U2F_V2") self.assertIn('appId', response_registration1['detail']['registerrequest'], "Response: %r" % response_registration1) self.assertEqual(response_registration1['detail']['registerrequest']['appId'], self.origin) challenge_registration = response_registration1['detail']['registerrequest']['challenge'] self.serial = response_registration1['detail']['serial'] self.serials.add(self.serial) client_data_registration = self._createClientDataObject('registration', challenge_registration, ) # Since we have no supported OpenSSL version to calculate the registration response # we use a hard-coded correctly-formed fake registration response registration_response = binascii.unhexlify(self.FAKE_REGISTRATION_DATA_HEX) registration_response_message = { 'registrationData': base64.urlsafe_b64encode(registration_response), 'clientData': base64.urlsafe_b64encode(client_data_registration) } # Complete the token registration response_registration2 = self.get_json_body( self._registration2(json.dumps(registration_response_message)) ) # Registration must fail # check for status and value self.assertIn('result', response_registration2, "Response: %r" % response_registration2) self.assertIn('status', response_registration2['result'], "Response: %r" % response_registration2) self.assertFalse(response_registration2['result']['status']) # check explicitly, that no "value: true" is responded if 'value' in response_registration2['result']: self.assertFalse(response_registration2['result']['value']) # Check for correct error messages self.assertIn('error', response_registration2['result'], "Response: %r" % response_registration2) self.assertIn('message', response_registration2['result']['error'], "Response: %r" % response_registration2) self.assertIn("missing ECDSA support for the NIST P-256 curve in OpenSSL", response_registration2['result']['error']['message'])
def as_der(self): buf = BIO.MemoryBuffer() m2.i2d_ssl_session(buf.bio_ptr(), self.session) return buf.read_all()
def PubKeyFromCert(cert): pub_key = cert.get_pubkey().get_rsa() bio = BIO.MemoryBuffer() pub_key.save_pub_key_bio(bio) return bio.read_all()
def PUT(self): global sm_obj, device_list HIGH = '[1;31m' LOW = '[0;32m' NORMAL = '[0;39m' i = web.data() pl = readPlistFromString(i) if 'HTTP_MDM_SIGNATURE' in web.ctx.environ: raw_sig = web.ctx.environ['HTTP_MDM_SIGNATURE'] cooked_sig = '\n'.join(raw_sig[pos:pos + 76] for pos in xrange(0, len(raw_sig), 76)) signature = '\n-----BEGIN PKCS7-----\n%s\n-----END PKCS7-----\n' % cooked_sig # Verify client signature - necessary? buf = BIO.MemoryBuffer(signature) p7 = SMIME.load_pkcs7_bio(buf) data_bio = BIO.MemoryBuffer(i) try: v = sm_obj.verify(p7, data_bio) if v: print "Client signature verified." except: print "*** INVALID CLIENT MESSAGE SIGNATURE ***" print "%sReceived %4d bytes: %s" % (HIGH, len(web.data()), NORMAL), if pl.get('Status') == 'Idle': print HIGH + "Idle Status" + NORMAL print "*FETCHING CMD TO BE SENT FROM DEVICE:", pl['UDID'] rd = device_list[pl['UDID']].sendCommand() # If no commands in queue, return empty string to avoid infinite idle loop if (not rd): return '' print "%sSent: %s%s" % (HIGH, rd['Command']['RequestType'], NORMAL) elif pl.get('MessageType') == 'TokenUpdate': print HIGH + "Token Update" + NORMAL rd = do_TokenUpdate(pl) print HIGH + "Device Enrolled!" + NORMAL elif pl.get('Status') == 'Acknowledged': print HIGH + "Acknowledged" + NORMAL rd = dict() # A command has returned a response # Add the response to the given device print "*CALLING ADD RESPONSE TO CMD:", pl['CommandUUID'] device_list[pl['UDID']].addResponse(pl['CommandUUID'], pl) # If we grab device information, we should also update the device info if pl.get('QueryResponses'): print "DeviceInformation should update here..." p = pl['QueryResponses'] device_list[pl['UDID']].updateInfo(p['DeviceName'], p['ModelName'], p['OSVersion']) # Update pickle file with new response store_devices() else: rd = dict() if pl.get('MessageType') == 'Authenticate': print HIGH + "Authenticate" + NORMAL elif pl.get('MessageType') == 'CheckOut': print HIGH + "Device leaving MDM" + NORMAL elif pl.get('Status') == 'Error': print "*CALLING ADD RESPONSE WITH ERROR TO CMD:", pl[ 'CommandUUID'] device_list[pl['UDID']].addResponse(pl['CommandUUID'], pl) else: print HIGH + "(other)" + NORMAL print HIGH, pl, NORMAL log_data(pl) log_data(rd) out = writePlistToString(rd) #print LOW, out, NORMAL return out
s = SMIME.SMIME() # Load target cert to encrypt to. x509 = X509.load_cert('certificate.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) print(out.read()) with open("encrypt.p7", 'wb') as f: f.write(out.read()) # Save the PRNG's state. Rand.save_file('randpool.dat') # Instantiate an SMIME object. s = SMIME.SMIME()
import httplib, urlparse from M2Crypto import BIO, Rand, SMIME, X509 # Make a MemoryBuffer of the message. buf = BIO.MemoryBuffer( """Content-Type: application/xml <customer name="bill"/> """) # 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('src/main/resources/cert.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) out = BIO.MemoryBuffer() s.write(out, p7)
import httplib, urlparse from M2Crypto import BIO, SMIME, X509 conn = httplib.HTTPConnection("localhost:9095") conn.request("GET", "/smime/encrypted") res = conn.getresponse() if res.status != 200: print res.status raise Exception("Failed to connect") contentType = res.getheader("content-type") data = res.read() # Need to reconstruct a Mail message with content type # as SMIME wants it in that format bio = BIO.MemoryBuffer("Content-Type: ") bio.write(contentType) bio.write("\r\n\r\n") bio.write(data) s = SMIME.SMIME() s.load_key('src/main/resources/private.pem', 'src/main/resources/cert.pem') p7, d = SMIME.smime_load_pkcs7_bio(bio) out = s.decrypt(p7) print "--- Received Data ---" # It may contain headers like Content-Type, so you'll have to parse it print out
def makebuf(): buf = BIO.MemoryBuffer(ptxt) return buf
def dencrypt(self,regCode,public_key): pub_bio = BIO.MemoryBuffer(public_key) rsa = RSA.load_pub_key_bio(pub_bio) #pub_key = EVP.load_key_string(public) machine_code = rsa.public_decrypt(b64decode(regCode),RSA.pkcs1_padding) return machine_code
def PUT(self): global current_command, last_result HIGH = '[1;31m' LOW = '[0;32m' NORMAL = '[0;30m' i = web.data() pl = readPlistFromString(i) if 'HTTP_MDM_SIGNATURE' in web.ctx.environ: raw_sig = web.ctx.environ['HTTP_MDM_SIGNATURE'] cooked_sig = '\n'.join(raw_sig[pos:pos + 76] for pos in xrange(0, len(raw_sig), 76)) signature = """ -----BEGIN PKCS7----- %s -----END PKCS7----- """ % cooked_sig #print i #print signature buf = BIO.MemoryBuffer(signature) p7 = SMIME.load_pkcs7_bio(buf) data_bio = BIO.MemoryBuffer(i) try: v = sm_obj.verify(p7, data_bio) if v: print "Client signature verified." except: print "*** INVALID CLIENT MESSAGE SIGNATURE ***" print "%sReceived %4d bytes: %s" % (HIGH, len(web.data()), NORMAL), if pl.get('Status') == 'Idle': print HIGH + "Idle Status" + NORMAL rd = current_command print "%sSent: %s%s" % (HIGH, rd['Command']['RequestType'], NORMAL) # print HIGH, rd, NORMAL elif pl.get('MessageType') == 'TokenUpdate': print HIGH + "Token Update" + NORMAL rd = do_TokenUpdate(pl) print HIGH + "Device Enrolled!" + NORMAL elif pl.get('Status') == 'Acknowledged': print HIGH + "Acknowledged" + NORMAL rd = dict() else: rd = dict() if pl.get('MessageType') == 'Authenticate': print HIGH + "Authenticate" + NORMAL elif pl.get('MessageType') == 'CheckOut': print HIGH + "Device leaving MDM" + NORMAL else: print HIGH + "(other)" + NORMAL print HIGH, pl, NORMAL log_data(pl) log_data(rd) out = writePlistToString(rd) # print LOW, out, NORMAL q = pl.get('QueryResponses') if q: redact_list = ('UDID', 'BluetoothMAC', 'SerialNumber', 'WiFiMAC', 'IMEI', 'ICCID', 'SerialNumber') for resp in redact_list: if q.get(resp): pl['QueryResponses'][resp] = '--redacted--' for top in ('UDID', 'Token', 'PushMagic', 'UnlockToken'): if pl.get(top): pl[top] = '--redacted--' last_result = pprint.pformat(pl) return out
def makebuf(text): return BIO.MemoryBuffer(text)
def test_load_pkcs7_bio_der(self): with open(self.filename_der, 'rb') as f: buf = BIO.MemoryBuffer(f.read()) self.assertEqual(SMIME.load_pkcs7_bio_der(buf).type(), SMIME.PKCS7_SIGNED)
def x509_name_entry2tuple(entry): bio = BIO.MemoryBuffer() m2.asn1_string_print(bio._ptr(), m2.x509_name_entry_get_data(entry._ptr())) return (m2.obj_obj2txt(m2.x509_name_entry_get_object(entry._ptr()), 0), bio.getvalue())
def __bytes__(self): # type: () -> bytes buf = BIO.MemoryBuffer() m2.asn1_string_print(buf.bio_ptr(), self.asn1str) return buf.read_all()
def test_sign_unknown_digest(self): buf = BIO.MemoryBuffer(self.cleartext) s = SMIME.SMIME() s.load_key('tests/signer_key.pem', 'tests/signer.pem') self.assertRaises(SMIME.SMIME_Error, s.sign, buf, SMIME.PKCS7_DETACHED, 'invalid digest name')
def genPubKey(privkey): """ 生成公钥 """ bio=BIO.MemoryBuffer(privkey) key=EVP.load_key_bio(bio, util.no_passphrase_callback) return key.get_rsa().as_pem()
def test_crlf(self): self.assertEqual(SMIME.text_crlf(b'foobar'), b'Content-Type: text/plain\r\n\r\nfoobar') self.assertEqual(SMIME.text_crlf_bio( BIO.MemoryBuffer(b'foobar')).read(), b'Content-Type: text/plain\r\n\r\nfoobar')
def key_to_pem(self): "Convert a key to the PEM format." bio = BIO.MemoryBuffer() self.ec.save_pub_key_bio(bio) return bio.read_all()