示例#1
0
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
示例#2
0
def start_generate(server_name, headers, server_modulus):
    global global_tlsver
    global global_use_gzip
    global global_use_slowaes

    print("server_name:", server_name)
    session_id = ''.join(
        random.choice(string.ascii_lowercase + string.digits)
        for x in range(10))
    tlsn_session = shared.TLSNClientSession(server_name, tlsver=global_tlsver)
    tlsn_session.server_modulus = shared.ba2int(server_modulus)
    tlsn_session.server_mod_length = shared.bi2ba(len(server_modulus))

    print('Preparing encrypted pre-master secret')
    prepare_pms(tlsn_session, session_id)

    for i in range(10):
        try:
            print('Performing handshake with server')
            tls_sock = shared.create_sock(tlsn_session.server_name,
                                          tlsn_session.ssl_port)
            tlsn_session.start_handshake(tls_sock)
            retval = negotiate_crippled_secrets(tlsn_session, tls_sock,
                                                session_id)
            if not retval == 'success':
                raise shared.TLSNSSLError('Failed to negotiate secrets: ' +
                                          retval)
            print('Getting data from server')
            #
            response = make_tlsn_request(headers, tlsn_session, tls_sock)
            #prefix response with number of to-be-ignored records,
            #note: more than 256 unexpected records will cause a failure of audit. Just as well!
            response = shared.bi2ba(
                tlsn_session.unexpected_server_app_data_count,
                fixed=1) + response
            break
        except shared.TLSNSSLError:
            shared.ssl_dump(tlsn_session)
            raise
        except Exception as e:
            print(
                'Exception caught while getting data from server, retrying...',
                e)
            if i == 9:
                raise Exception('Notarization failed')
            continue

    # commit its own hash, get auditor's secrets
    ok, commit_hash, pms2, signature, audit_time = commit_session(
        tlsn_session, response, session_id)
    if not ok:
        return ok, "commit hash to auditor failed"
# no need to verify signatures
    msg = sha256(commit_hash + pms2 +
                 shared.bi2ba(tlsn_session.server_modulus) +
                 audit_time).digest()
    oracle_ba_modulus = binascii.unhexlify(oracle_modulus)
    oracle_int_modulus = shared.ba2int(oracle_ba_modulus)
    print(msg)
    print(signature)
    if not shared.verify_signature(msg, signature, oracle_int_modulus):
        raise Exception("Notarization FAILED, notary signature invalid.")

    ok, result = decrypt_html(pms2, tlsn_session)
    if not ok:
        return ok, result
    html = result

    print('Verified OK')

    host_line = "host: " + server_name + "\r\n"
    readable = host_line
    b = """""" ""

    b = """<meta[ ]+http-equiv=["']?content-type["']?[ ]+content=["']?text/html;[ ]*charset=([0-9-a-zA-Z]+)["']?"""
    B = re.compile(b, re.IGNORECASE)
    encodings = B.search(html)
    #    print("encoding:")
    if encodings != None:
        encoding = encodings.group(1)
        if encoding.lower() == 'gb231' or encoding.lower() == 'gb2312':
            html = html.decode('gb18030')
            #        print(html)
        else:
            html = html.decode(encoding)
    else:
        html.decode('utf-8')

    print("html len:", len(html))
    html = "response:\r\n" + html + '\r\n-----PROOF BINARY DATA-----\r\n'
    #    print(html)
    #    readable += html.decode().encode('utf-8')
    readable += html
    # chosen_cipher_suite
    audit_data = shared.bi2ba(tlsn_session.chosen_cipher_suite,
                              fixed=2)  # 2 bytes
    # client_random, server_random
    audit_data += tlsn_session.client_random + tlsn_session.server_random  # 64 bytes
    # pre_master_key, two parts, each generated by auditee or auditor
    audit_data += tlsn_session.pms1 + pms2  #48 bytes
    # length of server_cert, sent by TLS Server, why fix 3 ?
    audit_data += shared.bi2ba(len(tlsn_session.server_certificate.certs),
                               fixed=3)
    # server_certs, it's very hard to verify these babies on-chain.
    audit_data += tlsn_session.server_certificate.certs
    # tls version
    audit_data += tlsn_session.tlsver  #2 bytes
    # proposed tls version in ClientHello?
    #    audit_data += tlsn_session.initial_tlsver #2 bytes
    # length of response
    audit_data += shared.bi2ba(len(response), fixed=8)  #8 bytes
    # response data
    audit_data += response  #note that it includes unexpected pre-request app data, 10s of kB
    # IV_after_finished used by RC4, necessory to authenticate response
    IV = tlsn_session.IV_after_finished if tlsn_session.chosen_cipher_suite in [47,53] \
                else shared.rc4_state_to_bytearray(tlsn_session.IV_after_finished)
    # length of IV, should be before IV ?
    audit_data += shared.bi2ba(len(IV), fixed=2)  #2 bytes
    # IV
    audit_data += IV  #16 bytes or 258 bytes for RC4.
    # length of auditor's public key, in modulus formate
    audit_data += shared.bi2ba(len(oracle_ba_modulus), fixed=2)
    # auditor's signature
    audit_data += signature  #512 bytes RSA PKCS 1 v1.5 padding
    # hash that auditee commits to auditor
    audit_data += commit_hash  #32 bytes sha256 hash
    # auditor's public key
    audit_data += oracle_ba_modulus
    # timestamp used to make signature unique
    audit_data += audit_time
    #    audit_data = bytearray(readable.encode('utf-8')) + audit_data

    date = time_str = time.strftime('%d-%b-%Y-%H-%M-%S-', time.gmtime())
    filename = date + session_id + ".pgsg"
    #    print("proof file name:",filename)
    proofpath = join(PROOF_DIR, filename)
    with open(proofpath, "w") as f:
        f.write(readable)
        f.write(audit_data)

    return True, filename
     global_use_gzip = False   
 
 audit_data = extract_audit_data(audit_filename)
 #1. Verify notary pubkey - done in extract_audit_data
 print ('Notary pubkey OK')
 #2. Verify signature
 #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
 audit_session = shared.TLSNClientSession(ccs=audit_data['cipher_suite'],tlsver=audit_data['initial_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)
 print ('Processing data for server: ', audit_session.server_name)
 data_to_be_verified = audit_data['commit_hash'] + audit_data['pms2'] + shared.bi2ba(server_mod)
 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):
     print ('Audit FAILED. Signature is not verified.')
     exit()        
 print ('Notary signature OK')
 #3. Verify commitment hash.
 if not sha256(audit_data['response']).digest() == audit_data['commit_hash']:
     print ('Audit FAILED. Commitment hash does not match encrypted server response.')
     exit()
 print ('Commitment hash OK')
 #4 Decrypt html and check for mac errors.
 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']
示例#4
0
 #1. Verify notary pubkey - done in extract_audit_data
 print('Notary pubkey OK')
 #2. Verify signature
 #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
 audit_session = shared.TLSNClientSession(
     ccs=audit_data['cipher_suite'], tlsver=audit_data['initial_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)
 print('Processing data for server: ', audit_session.server_name)
 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):
     print('Audit FAILED. Signature is not verified.')
     exit()
 print('Notary signature OK')
 #3. Verify commitment hash.
 if not sha256(
         audit_data['response']).digest() == audit_data['commit_hash']:
     print(
         'Audit FAILED. Commitment hash does not match encrypted server response.'
     )
     exit()
 print('Commitment hash OK')
 #4 Decrypt html and check for mac errors.
 audit_session.unexpected_server_app_data_count = shared.ba2int(
     audit_data['response'][0])
 audit_session.tlsver = audit_data['tlsver']