def decrypt_html(pms2, tlsn_session): '''Receive correct server mac key and then decrypt server response (html), (includes authentication of response). Submit resulting html for browser for display (optionally render by stripping http headers).''' print("\nStarting decryption of content, may take a few seconds...") try: tlsn_session.auditor_secret = pms2[:tlsn_session.n_auditor_entropy] tlsn_session.set_auditor_secret() tlsn_session.set_master_secret_half( ) #without arguments sets the whole MS tlsn_session.do_key_expansion( ) #also resets encryption connection state except shared.TLSNSSLError: shared.ssl_dump(tlsn_session) raise #either using slowAES or a RC4 ciphersuite try: plaintext, bad_mac = tlsn_session.process_server_app_data_records() # print(plaintext) except shared.TLSNSSLError: shared.ssl_dump(tlsn_session) raise if bad_mac: return False, "ERROR! Audit not valid! Plaintext is not authenticated." # if http data chunked, dechunk plaintext = shared.dechunk_http(plaintext) if global_use_gzip: plaintext = shared.gunzip_http(plaintext) return True, plaintext
def decrypt_html_stage2(plaintext, tlsn_session, sf): plaintext = shared.dechunk_http(plaintext) if global_use_gzip: plaintext = shared.gunzip_http(plaintext) #write a session dump for checking even in case of success with open(join(current_session_dir, 'session_dump' + sf), 'wb') as f: f.write(tlsn_session.dump()) commit_dir = join(current_session_dir, 'commit') html_path = join(commit_dir, 'html-' + sf) with open(html_path, 'wb') as f: f.write('\xef\xbb\xbf' + plaintext) #see "Byte order mark" if not int(shared.config.get("General", "prevent_render")): htm = l_path = join(commit_dir, 'forbrowser-' + sf + '.html') with open(html_path, 'wb') as f: f.write('\r\n\r\n'.join(plaintext.split('\r\n\r\n')[1:])) print("Decryption complete.") return ('success', html_path)
def review(audit_filename): review_result = "" try: ok, result = extract_audit_data(audit_filename) if not ok: # print(result) review_result += "Valid proof file format: False\n" return False, review_result, None else: review_result += "Valid Proof File Format: True\n" audit_data = result except Exception as e: review_result += "Valid proof file format: False\n" return False, review_result, None #1. Verify TLS Server's pubkey # to-do: verify cert signed by trusted root CA # to-do: extrct pubkey from ca certificate, compare with pubkey in pgsg try: audit_session = shared.TLSNClientSession( ccs=audit_data['cipher_suite'], tlsver=audit_data['tlsver']) first_cert_len = shared.ba2int(audit_data['certs'][:3]) cert_bi = audit_data['certs'][3:3 + first_cert_len] cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_ASN1, cert_bi) cert_cn = cert.get_subject().CN print(cert.get_subject().get_components()) print("cert CN:", cert.get_subject().commonName) # server_name = cert.get_subject().CN print("audit_data server:", audit_data['host']) server_name = audit_data['host'] # print("is rsapublickey:",isinstance(cert.get_pubkey().to_cryptography_key(), cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey)) server_mod = cert.get_pubkey().to_cryptography_key().public_numbers().n # print("extrct public_key mod:", server_mod) if cert_cn.startswith("*."): cert_cn = cert_cn[2:] if cert_cn.endswith(".cn"): cert_cn = cert_cn[:-3] if cert_cn.startswith("www."): cert_cn = cert_cn[4:] print("cert CN:", cert_cn) if "." in cert_cn: cert_cn_arrays = cert_cn.split(".") cert_cn = cert_cn_arrays[-2] print("cert CN:", cert_cn) # if not server_name.endswith(cert_cn): # if cert_cn not in server_name: # review_result += "Valid Host name: False\n" # return False, review_result, None # else: # review_result += "Valid Host name: True\n" print('Processing data for server:', server_name) # if server_name.strip() != audit_data['host'].strip(): # return False, "host name not match" public_hex = binascii.hexlify(shared.bi2ba(server_mod)) # if server_name.startswith("*."): # short = server_name[2:] # url_openssl = "free-api."+short # print ('Processing data for server:', server_name) cipher_key = audit_data['cipher_suite'] cipher_suites = shared.tlsn_cipher_suites chosen_cipher = cipher_suites[cipher_key][0] print("chosen cipher suite:", chosen_cipher) tls_ver = "-tls1_1" if audit_data['tlsver'] == bytearray('\x03\x01'): tls_ver = "-tls1" print("tls ver:", tls_ver) cmd = "echo |openssl s_client " + tls_ver + " -cipher " + chosen_cipher + " -connect " + server_name + ":443 2>&1 | openssl x509 -pubkey -modulus -noout 2>&1 | grep 'Modulus' | sed 's/Modulus=//g' " print("cmd:", cmd) import subprocess public_openssl = subprocess.check_output(cmd, shell=True).strip('\n') print("hex:" + public_hex.upper().lower()) print("openssl:" + public_openssl.upper().lower()) if public_hex.upper().lower() == public_openssl.upper().lower(): review_result += "Valid server pub key: True\n" else: review_result += "Valid server pub key: False\n" return False, review_result, None except Exception as e: review_result += "Valid server pub key: False\n" return False, review_result, None try: check_cert = os.system("echo |openssl s_client " + tls_ver + " -cipher " + chosen_cipher + " -connect " + server_name + ":443") print("check_cert result:", check_cert) if check_cert == 0: review_result += "Valid server certificate chain: True\n" else: review_result += "Valid server certificate chain: False\n" return False, review_result, None except Exception as e: review_result += "Valid server certificate chain: False\n" return False, review_result, None # to-do check if openssl cmd return 0 #2. Verify Proof from the Auditor Side # the partial proof from auditor is signed by auditor #First, extract the cert in DER form from the notarization file #Then, extract from the cert the modulus and server name (common name field) #To do this, we need to initialise the TLSNClientSession try: audit_session = shared.TLSNClientSession( ccs=audit_data['cipher_suite'], tlsver=audit_data['tlsver']) first_cert_len = shared.ba2int(audit_data['certs'][:3]) # server_mod, server_exp = audit_session.extract_mod_and_exp(certDER=audit_data['certs'][3:3+first_cert_len], sn=True) data_to_be_verified = audit_data['commit_hash'] + audit_data[ 'pms2'] + shared.bi2ba(server_mod) + audit_data['audit_time'] data_to_be_verified = sha256(data_to_be_verified).digest() if not shared.verify_signature(data_to_be_verified, audit_data['signature'], oracle_int_modulus): review_result += "Valid Auditor Signature: False\n" return False, review_result, None else: review_result += "Valid Auditor Signature: True\n" #3. Verify commitment hash. if not sha256(audit_data['response'] + audit_data['certs']).digest( ) == audit_data['commit_hash']: review_result += "Valid server response: False\n" return False, review_result, None else: review_result += "Valid encrypted server response: True\n" except Exception as e: review_result += "Valid server response: False\n" print(e) return False, review_result, None #4 Decrypt html and check for mac errors. Response data and MAC code from auditee will be checked by the MAC key from Auditor try: audit_session.unexpected_server_app_data_count = shared.ba2int( audit_data['response'][0]) audit_session.tlsver = audit_data['tlsver'] audit_session.client_random = audit_data['client_random'] audit_session.server_random = audit_data['server_random'] audit_session.pms1 = audit_data['pms1'] audit_session.pms2 = audit_data['pms2'] audit_session.p_auditee = shared.tls_10_prf( 'master secret' + audit_session.client_random + audit_session.server_random, first_half=audit_session.pms1)[0] audit_session.p_auditor = shared.tls_10_prf( 'master secret' + audit_session.client_random + audit_session.server_random, second_half=audit_session.pms2)[1] audit_session.set_master_secret_half() audit_session.do_key_expansion() audit_session.store_server_app_data_records(audit_data['response'][1:]) audit_session.IV_after_finished = (map(ord,audit_data['IV'][:256]),ord(audit_data['IV'][256]), \ ord(audit_data['IV'][257])) if audit_data['cipher_suite'] in [4,5] else audit_data['IV'] print("start to decrypt") plaintext, bad_mac = audit_session.process_server_app_data_records( is_for_auditor=True) print("decrypt done") if bad_mac: review_result += "Valid decrypted response content: False\n" return False, review_result, None plaintext = shared.dechunk_http(plaintext) plaintext = shared.gunzip_http(plaintext) if plaintext == audit_data['html']: review_result += "Valid decrypted response content: True\n" else: review_result += "Valid decrypted response content: False\n" return False, review_result, None except Exception as e: review_result += "Valid decrypted response content: False\n" return False, review_result, None #5 Display html + success. # with open(join(current_session_dir,'audited.html'),'wb') as f: # f.write(plaintext) #print out the info about the domain # n_hexlified = binascii.hexlify(shared.bi2ba(server_mod)) # print("pubkey string:"+n_hexlified) # #pubkey in the format 09 56 23 .... # n_write = " ".join(n_hexlified[i:i+2] for i in range(0, len(n_hexlified), 2)) # with open(join(current_session_dir,'domain_data.txt'), 'wb') as f: # f.write('Server name: '+audit_session.server_name + '\n\n'+'Server pubkey:' + '\n\n' + n_write+'\n') return True, review_result, plaintext
audit_session.pms2 = audit_data['pms2'] audit_session.p_auditee = shared.tls_10_prf('master secret'+audit_session.client_random+audit_session.server_random, first_half=audit_session.pms1)[0] audit_session.p_auditor = shared.tls_10_prf('master secret'+audit_session.client_random+audit_session.server_random, second_half=audit_session.pms2)[1] audit_session.set_master_secret_half() audit_session.do_key_expansion() audit_session.store_server_app_data_records(audit_data['response'][1:]) audit_session.IV_after_finished = (map(ord,audit_data['IV'][:256]),ord(audit_data['IV'][256]), \ ord(audit_data['IV'][257])) if audit_data['cipher_suite'] in [4,5] else audit_data['IV'] plaintext, bad_mac = audit_session.process_server_app_data_records(is_for_auditor=True) if bad_mac: print ('Audit FAILED. Decrypted data has bad HMACs.') print ('HTML decryption with correct HMACs OK.') plaintext = shared.dechunk_http(plaintext) plaintext = shared.gunzip_http(plaintext) #5 Display html + success. with open(join(current_session_dir,'audited.html'),'wb') as f: f.write(plaintext) #print out the info about the domain n_hexlified = binascii.hexlify(shared.bi2ba(server_mod)) #pubkey in the format 09 56 23 .... n_write = " ".join(n_hexlified[i:i+2] for i in range(0, len(n_hexlified), 2)) with open(join(current_session_dir,'domain_data.txt'), 'wb') as f: f.write('Server name: '+audit_session.server_name + '\n\n'+'Server pubkey:' + '\n\n' + n_write+'\n') print ("Audit passed! You can read the html at: ", join(current_session_dir,'audited.html'), 'and check the server certificate with the data provided in ', join(current_session_dir,'domain_data.txt'))
audit_session.p_auditor = shared.tls_10_prf( 'master secret' + audit_session.client_random + audit_session.server_random, second_half=audit_session.pms2)[1] audit_session.set_master_secret_half() audit_session.do_key_expansion() audit_session.store_server_app_data_records(audit_data['response'][1:]) audit_session.IV_after_finished = (map(ord,audit_data['IV'][:256]),ord(audit_data['IV'][256]), \ ord(audit_data['IV'][257])) if audit_data['cipher_suite'] in [4,5] else audit_data['IV'] plaintext, bad_mac = audit_session.process_server_app_data_records( is_for_auditor=True) if bad_mac: print('Audit FAILED. Decrypted data has bad HMACs.') print('HTML decryption with correct HMACs OK.') plaintext = shared.dechunk_http(plaintext) plaintext = shared.gunzip_http(plaintext) #5 Display html + success. with open(join(current_session_dir, 'audited.html'), 'wb') as f: f.write(plaintext) #print out the info about the domain n_hexlified = binascii.hexlify(shared.bi2ba(server_mod)) #pubkey in the format 09 56 23 .... n_write = " ".join(n_hexlified[i:i + 2] for i in range(0, len(n_hexlified), 2)) with open(join(current_session_dir, 'domain_data.txt'), 'wb') as f: f.write('Server name: ' + audit_session.server_name + '\n\n' + 'Server pubkey:' + '\n\n' + n_write + '\n') print("Audit passed! You can read the html at: ", join(current_session_dir, 'audited.html'), 'and check the server certificate with the data provided in ',