From 142726c4fdf40e7d8e397eb920ee3c936f2c1024 Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Tue, 24 Jun 2014 15:34:44 +0200 Subject: [PATCH 1/7] count ECDH-RSA ciphers as ECDSA the ECDH parameters come from server certificate - the point on elliptic curve. The RSA comes from the signature on the certificate which comes from CA --- top1m/parse_results.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index bdcd304..d95d60c 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -151,7 +151,7 @@ for r,d,flist in os.walk(path): RSA = True """ save the key size """ - if 'ECDSA' in entry['cipher']: + if 'ECDSA' in entry['cipher'] or 'ECDH-RSA' in entry['cipher']: ECDSA = True tempecckeystats[entry['pubkey'][0]] = 1 elif 'DSS' in entry['cipher']: From 1b4dcc4393b7306f3fb0ff98ed1d5ffb7466a971 Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Mon, 30 Jun 2014 10:42:53 +0200 Subject: [PATCH 2/7] report ciphers causing incompatibility for Firefox It turns out that the situation is even more bleak for Firefox with regards to RC4, add it to report --- top1m/parse_results.py | 87 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index d95d60c..ec17f39 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -21,9 +21,38 @@ def natural_sort(l): alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] return sorted(l, key = alphanum_key) +""" list of ciphers offerred by Firefox 29 by default """ +firefox_ciphers=[ + 'ECDHE-ECDSA-AES128-GCM-SHA256', + 'ECDHE-RSA-AES128-GCM-SHA256', + 'ECDHE-ECDSA-AES256-SHA', + 'ECDHE-ECDSA-AES128-SHA', + 'ECDHE-RSA-AES128-SHA', + 'ECDHE-RSA-AES256-SHA', + 'ECDHE-RSA-DES-CBC3-SHA', + 'ECDHE-ECDSA-RC4-SHA', + 'ECDHE-RSA-RC4-SHA', + 'DHE-RSA-AES128-SHA', + 'DHE-DSS-AES128-SHA', + 'DHE-RSA-CAMELLIA128-SHA', + 'DHE-RSA-AES256-SHA', + 'DHE-DSS-AES256-SHA', + 'DHE-RSA-CAMELLIA256-SHA', + 'EDH-RSA-DES-CBC3-SHA', + 'AES128-SHA', + 'CAMELLIA128-SHA', + 'AES256-SHA', + 'CAMELLIA256-SHA', + 'DES-CBC3-SHA', + 'RC4-SHA', + 'RC4-MD5'] + report_untrused=False cipherstats = defaultdict(int) +FF_RC4_Only_cipherstats = defaultdict(int) +FF_RC4_preferred_cipherstats = defaultdict(int) +FF_incompatible_cipherstats = defaultdict(int) pfsstats = defaultdict(int) protocolstats = defaultdict(int) handshakestats = defaultdict(int) @@ -53,6 +82,11 @@ for r,d,flist in os.walk(path): DES3 = False CAMELLIA = False RC4 = False + """ the following depends on FF_compat, so by default it can be True """ + RC4_Only_FF = True + FF_compat = False + temp_FF_incompat = {} + FF_RC4_Pref = None ADH = False DHE = False AECDH = False @@ -92,6 +126,20 @@ for r,d,flist in os.walk(path): if 'False' in entry['trusted'] and report_untrused == False: continue + # check if the advertised ciphers are not effectively RC4 Only + # for firefox or incompatible with firefox + if entry['cipher'] in firefox_ciphers: + # if this is first cipher and we already are getting RC4 + # then it means that RC4 is preferred + if not FF_compat: + if 'RC4' in entry['cipher']: + FF_RC4_Pref = True + FF_compat = True + if not 'RC4' in entry['cipher']: + RC4_Only_FF = False + else: + temp_FF_incompat[entry['cipher']] = 1 + """ store the ciphers supported """ if 'ADH' in entry['cipher'] or 'AECDH' in entry['cipher']: ciphertypes += 1 @@ -269,6 +317,20 @@ for r,d,flist in os.walk(path): cipherstats['RC4 forced in TLS1.1+'] += 1 cipherstats['RC4 Preferred'] += 1 + if FF_compat: + if RC4_Only_FF and ciphertypes != 1: + cipherstats['x:FF 29 RC4 Only'] += 1 + for cipher in temp_FF_incompat: + FF_RC4_Only_cipherstats[cipher] += 1 + if FF_RC4_Pref and not 'RC4' in results['ciphersuite'][0]['cipher']: + cipherstats['x:FF 29 RC4 Preferred'] += 1 + for cipher in temp_FF_incompat: + FF_RC4_preferred_cipherstats[cipher] += 1 + else: + cipherstats['x:FF 29 incompatible'] += 1 + for cipher in temp_FF_incompat: + FF_incompatible_cipherstats[cipher] += 1 + for cipher in tempcipherstats: cipherstats[cipher] += 1 @@ -322,6 +384,13 @@ for r,d,flist in os.walk(path): #if total % 1999 == 0: # break +""" The 'x:FF 29 RC4 Preferred' counts only sites that effectively prefer + RC4 when using FF, to make reporting more readable, sum it with sites + that do that for all ciphers""" + +if "x:FF 29 RC4 Preferred" in cipherstats and "RC4 Preferred" in cipherstats: + cipherstats['x:FF 29 RC4 Preferred'] += cipherstats['RC4 Preferred'] + print("SSL/TLS survey of %i websites from Alexa's top 1 million" % total) if report_untrused == False: print("Stats only from connections that did provide valid certificates") @@ -334,6 +403,24 @@ for stat in sorted(cipherstats): percent = round(cipherstats[stat] / total * 100, 4) sys.stdout.write(stat.ljust(25) + " " + str(cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") +print("\nFF 29 RC4 Only other ciphers Count Percent") +print("-----------------------------+---------+------") +for stat in sorted(FF_RC4_Only_cipherstats): + percent = round(FF_RC4_Only_cipherstats[stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(FF_RC4_Only_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") + +print("\nFF 29 RC4 pref other ciphers Count Percent") +print("-----------------------------+---------+------") +for stat in sorted(FF_RC4_preferred_cipherstats): + percent = round(FF_RC4_preferred_cipherstats[stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(FF_RC4_preferred_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") + +print("\nFF 29 incompatible ciphers Count Percent") +print("-----------------------------+---------+------") +for stat in sorted(FF_incompatible_cipherstats): + percent = round(FF_incompatible_cipherstats[stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(FF_incompatible_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") + print("\nSupported Handshakes Count Percent") print("-------------------------+---------+-------") for stat in sorted(handshakestats): From 42fa7d9ecbb2f10b02bc9968b8990a7f703eaefb Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Mon, 30 Jun 2014 21:34:56 +0200 Subject: [PATCH 3/7] report what ciphers Firefox would select while connecting to server --- top1m/parse_results.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index ec17f39..721aee7 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -53,6 +53,7 @@ cipherstats = defaultdict(int) FF_RC4_Only_cipherstats = defaultdict(int) FF_RC4_preferred_cipherstats = defaultdict(int) FF_incompatible_cipherstats = defaultdict(int) +FF_selected_cipherstats = defaultdict(int) pfsstats = defaultdict(int) protocolstats = defaultdict(int) handshakestats = defaultdict(int) @@ -87,6 +88,7 @@ for r,d,flist in os.walk(path): FF_compat = False temp_FF_incompat = {} FF_RC4_Pref = None + FF_selected = None ADH = False DHE = False AECDH = False @@ -132,6 +134,7 @@ for r,d,flist in os.walk(path): # if this is first cipher and we already are getting RC4 # then it means that RC4 is preferred if not FF_compat: + FF_selected = entry['cipher'] if 'RC4' in entry['cipher']: FF_RC4_Pref = True FF_compat = True @@ -318,6 +321,13 @@ for r,d,flist in os.walk(path): cipherstats['RC4 Preferred'] += 1 if FF_compat: + if 'ECDHE' in FF_selected: + FF_selected_cipherstats['x:ECDHE'] += 1 + elif 'DHE' in FF_selected or 'EDH' in FF_selected: + FF_selected_cipherstats['x:DHE'] += 1 + else: + FF_selected_cipherstats['x:kRSA'] += 1 + FF_selected_cipherstats[FF_selected] += 1 if RC4_Only_FF and ciphertypes != 1: cipherstats['x:FF 29 RC4 Only'] += 1 for cipher in temp_FF_incompat: @@ -403,6 +413,12 @@ for stat in sorted(cipherstats): percent = round(cipherstats[stat] / total * 100, 4) sys.stdout.write(stat.ljust(25) + " " + str(cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") +print("\nFF 29 selected ciphers Count Percent") +print("-----------------------------+---------+------") +for stat in sorted(FF_selected_cipherstats): + percent = round(FF_selected_cipherstats[stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(FF_selected_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") + print("\nFF 29 RC4 Only other ciphers Count Percent") print("-----------------------------+---------+------") for stat in sorted(FF_RC4_Only_cipherstats): From c82bc44558b963ac6aadf10ee313710d4e91adab Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Tue, 1 Jul 2014 00:01:32 +0200 Subject: [PATCH 4/7] report cipher ordering in scanning stats, use it to simulate handshakes since now we know if server honours client order or not, we can use it to properly simulate handshakes for a given client, also report the general stats of this server configuration variable --- top1m/parse_results.py | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index 721aee7..0ac7c4f 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -54,6 +54,7 @@ FF_RC4_Only_cipherstats = defaultdict(int) FF_RC4_preferred_cipherstats = defaultdict(int) FF_incompatible_cipherstats = defaultdict(int) FF_selected_cipherstats = defaultdict(int) +cipherordering = defaultdict(int) pfsstats = defaultdict(int) protocolstats = defaultdict(int) handshakestats = defaultdict(int) @@ -87,6 +88,7 @@ for r,d,flist in os.walk(path): RC4_Only_FF = True FF_compat = False temp_FF_incompat = {} + list_of_ciphers = [] FF_RC4_Pref = None FF_selected = None ADH = False @@ -128,15 +130,13 @@ for r,d,flist in os.walk(path): if 'False' in entry['trusted'] and report_untrused == False: continue + list_of_ciphers.append(entry['cipher']) + # check if the advertised ciphers are not effectively RC4 Only # for firefox or incompatible with firefox if entry['cipher'] in firefox_ciphers: # if this is first cipher and we already are getting RC4 # then it means that RC4 is preferred - if not FF_compat: - FF_selected = entry['cipher'] - if 'RC4' in entry['cipher']: - FF_RC4_Pref = True FF_compat = True if not 'RC4' in entry['cipher']: RC4_Only_FF = False @@ -270,6 +270,32 @@ for r,d,flist in os.walk(path): if dualstack: dsarsastack += 1 + """ save cipher ordering """ + if 'serverside' in results: + if results['serverside'] == "False": + cipherordering['Client side'] += 1 + else: + cipherordering['Server side'] += 1 + else: + cipherordering['Unknown'] += 1 + + """ simulate handshake with Firefox """ + if FF_compat: + if 'serverside' in results and results['serverside'] == "False": + for cipher in firefox_ciphers: + if cipher in list_of_ciphers: + FF_selected = cipher + if 'RC4' in cipher: + FF_RC4_Pref = True + break + else: + for cipher in list_of_ciphers: + if cipher in firefox_ciphers: + FF_selected = cipher + if 'RC4' in cipher: + FF_RC4_Pref = True + break + for s in tempsigstats: sigalg[s] += 1 @@ -413,6 +439,12 @@ for stat in sorted(cipherstats): percent = round(cipherstats[stat] / total * 100, 4) sys.stdout.write(stat.ljust(25) + " " + str(cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") +print("\nCipher ordering Count Percent") +print("-------------------------+---------+-------") +for stat in sorted(cipherordering): + percent = round(cipherordering[stat] / total * 100, 4) + sys.stdout.write(stat.ljust(25) + " " + str(cipherordering[stat]).ljust(10) + str(percent).ljust(4) + "\n") + print("\nFF 29 selected ciphers Count Percent") print("-----------------------------+---------+------") for stat in sorted(FF_selected_cipherstats): From 76d791fcbe8edd80b894d67ad04d7f3c72b6bc6a Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Sun, 12 Oct 2014 20:24:56 +0200 Subject: [PATCH 5/7] make cipher selection simulation generic it's relatively easy to make the cipher selection generic, so that adding different clients is as easy as converting their client hello cipher ordering to openssl cipher names --- top1m/parse_results.py | 192 ++++++++++++++++++++++++----------------- 1 file changed, 111 insertions(+), 81 deletions(-) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index 0ac7c4f..50ee271 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -21,8 +21,10 @@ def natural_sort(l): alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] return sorted(l, key = alphanum_key) -""" list of ciphers offerred by Firefox 29 by default """ -firefox_ciphers=[ +""" client config cipher simulation """ +client_ciphers={} +""" list of ciphers offered by Firefox 29 by default """ +client_ciphers['FF 29']=[ 'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-ECDSA-AES256-SHA', @@ -50,10 +52,19 @@ firefox_ciphers=[ report_untrused=False cipherstats = defaultdict(int) -FF_RC4_Only_cipherstats = defaultdict(int) -FF_RC4_preferred_cipherstats = defaultdict(int) -FF_incompatible_cipherstats = defaultdict(int) -FF_selected_cipherstats = defaultdict(int) + +# stats about different client performance +# ciphers selected by them, unsupported, etc. +client_RC4_Only_cipherstats={} +client_RC4_preferred_cipherstats={} +client_incompatible_cipherstats={} +client_selected_cipherstats={} +for client_name in client_ciphers: + client_RC4_Only_cipherstats[client_name] = defaultdict(int) + client_RC4_preferred_cipherstats[client_name] = defaultdict(int) + client_incompatible_cipherstats[client_name] = defaultdict(int) + client_selected_cipherstats[client_name] = defaultdict(int) + cipherordering = defaultdict(int) pfsstats = defaultdict(int) protocolstats = defaultdict(int) @@ -84,13 +95,22 @@ for r,d,flist in os.walk(path): DES3 = False CAMELLIA = False RC4 = False - """ the following depends on FF_compat, so by default it can be True """ - RC4_Only_FF = True - FF_compat = False - temp_FF_incompat = {} + """ variables to support handshake simulation for different clients """ + client_RC4_Only={} + client_compat={} + temp_client_incompat={} + client_RC4_Pref={} + client_selected={} + for client_name in client_ciphers: + # the following depends on client_compat, so by default it can be True + client_RC4_Only[client_name]=True + client_compat[client_name]=False + temp_client_incompat[client_name]={} + client_RC4_Pref[client_name]=None + client_selected[client_name]=None + + """ server side list of supported ciphers """ list_of_ciphers = [] - FF_RC4_Pref = None - FF_selected = None ADH = False DHE = False AECDH = False @@ -133,15 +153,17 @@ for r,d,flist in os.walk(path): list_of_ciphers.append(entry['cipher']) # check if the advertised ciphers are not effectively RC4 Only - # for firefox or incompatible with firefox - if entry['cipher'] in firefox_ciphers: - # if this is first cipher and we already are getting RC4 - # then it means that RC4 is preferred - FF_compat = True - if not 'RC4' in entry['cipher']: - RC4_Only_FF = False - else: - temp_FF_incompat[entry['cipher']] = 1 + # for clients or incompatible with them + for client_name in client_ciphers: + if entry['cipher'] in client_ciphers[client_name]: + # if this is first cipher and we already are getting RC4 + # then it means that RC4 is preferred (and client is + # compatible with server) + client_compat[client_name]=True + if not 'RC4' in entry['cipher']: + client_RC4_Only[client_name] = False + else: + temp_client_incompat[client_name][entry['cipher']] = 1 """ store the ciphers supported """ if 'ADH' in entry['cipher'] or 'AECDH' in entry['cipher']: @@ -279,22 +301,23 @@ for r,d,flist in os.walk(path): else: cipherordering['Unknown'] += 1 - """ simulate handshake with Firefox """ - if FF_compat: - if 'serverside' in results and results['serverside'] == "False": - for cipher in firefox_ciphers: - if cipher in list_of_ciphers: - FF_selected = cipher - if 'RC4' in cipher: - FF_RC4_Pref = True - break - else: - for cipher in list_of_ciphers: - if cipher in firefox_ciphers: - FF_selected = cipher - if 'RC4' in cipher: - FF_RC4_Pref = True - break + """ simulate handshake with clients """ + for client_name in client_ciphers: + if client_compat[client_name]: + if 'serverside' in results and results['serverside'] == "False": + for cipher in client_ciphers[client_name]: + if cipher in list_of_ciphers: + client_selected[client_name] = cipher + if 'RC4' in cipher: + client_RC4_Pref[client_name] = True + break + else: + for cipher in list_of_ciphers: + if cipher in client_ciphers[client_name]: + client_selected[client_name] = cipher + if 'RC4' in cipher: + client_RC4_Pref[client_name] = True + break for s in tempsigstats: sigalg[s] += 1 @@ -346,26 +369,29 @@ for r,d,flist in os.walk(path): cipherstats['RC4 forced in TLS1.1+'] += 1 cipherstats['RC4 Preferred'] += 1 - if FF_compat: - if 'ECDHE' in FF_selected: - FF_selected_cipherstats['x:ECDHE'] += 1 - elif 'DHE' in FF_selected or 'EDH' in FF_selected: - FF_selected_cipherstats['x:DHE'] += 1 + for client_name in client_ciphers: + if client_compat[client_name]: + if 'ECDHE' in client_selected[client_name]: + client_selected_cipherstats[client_name]['x:ECDHE'] += 1 + elif 'DHE' in client_selected[client_name]: + client_selected_cipherstats[client_name]['x:DHE'] += 1 + else: + client_selected_cipherstats[client_name]['x:kRSA'] += 1 + + client_selected_cipherstats[client_name][client_selected[client_name]] += 1 + + if client_RC4_Only[client_name] and ciphertypes != 1: + cipherstats['x:' + client_name + ' RC4 Only'] += 1 + for cipher in temp_client_incompat[client_name]: + client_RC4_Only_cipherstats[client_name][cipher] += 1 + if client_RC4_Pref[client_name] and not 'RC4' in results['ciphersuite'][0]['cipher']: + cipherstats['x:' + client_name + ' RC4 Preferred'] += 1 + for cipher in temp_client_incompat[client_name]: + client_RC4_preferred_cipherstats[client_name][cipher] += 1 else: - FF_selected_cipherstats['x:kRSA'] += 1 - FF_selected_cipherstats[FF_selected] += 1 - if RC4_Only_FF and ciphertypes != 1: - cipherstats['x:FF 29 RC4 Only'] += 1 - for cipher in temp_FF_incompat: - FF_RC4_Only_cipherstats[cipher] += 1 - if FF_RC4_Pref and not 'RC4' in results['ciphersuite'][0]['cipher']: - cipherstats['x:FF 29 RC4 Preferred'] += 1 - for cipher in temp_FF_incompat: - FF_RC4_preferred_cipherstats[cipher] += 1 - else: - cipherstats['x:FF 29 incompatible'] += 1 - for cipher in temp_FF_incompat: - FF_incompatible_cipherstats[cipher] += 1 + cipherstats['x:' + client_name + ' incompatible'] += 1 + for cipher in temp_client_incompat[client_name]: + client_incompatible_cipherstats[client_name][cipher] += 1 for cipher in tempcipherstats: cipherstats[cipher] += 1 @@ -420,12 +446,13 @@ for r,d,flist in os.walk(path): #if total % 1999 == 0: # break -""" The 'x:FF 29 RC4 Preferred' counts only sites that effectively prefer - RC4 when using FF, to make reporting more readable, sum it with sites - that do that for all ciphers""" +""" The 'x:' + client_name + ' RC4 Preferred' counts only sites that + effectively prefer RC4 when using given client, to make reporting more + readable, sum it with sites that do that for all ciphers""" -if "x:FF 29 RC4 Preferred" in cipherstats and "RC4 Preferred" in cipherstats: - cipherstats['x:FF 29 RC4 Preferred'] += cipherstats['RC4 Preferred'] +for client_name in client_ciphers: + if 'x:' + client_name + ' RC4 Preferred' in cipherstats and 'RC4 Preferred' in cipherstats: + cipherstats['x:' + client_name + ' RC4 Preferred'] += cipherstats['RC4 Preferred'] print("SSL/TLS survey of %i websites from Alexa's top 1 million" % total) if report_untrused == False: @@ -445,29 +472,32 @@ for stat in sorted(cipherordering): percent = round(cipherordering[stat] / total * 100, 4) sys.stdout.write(stat.ljust(25) + " " + str(cipherordering[stat]).ljust(10) + str(percent).ljust(4) + "\n") -print("\nFF 29 selected ciphers Count Percent") -print("-----------------------------+---------+------") -for stat in sorted(FF_selected_cipherstats): - percent = round(FF_selected_cipherstats[stat] / total * 100, 4) - sys.stdout.write(stat.ljust(30) + " " + str(FF_selected_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") +print("\nCLIENT specific statistics\n") -print("\nFF 29 RC4 Only other ciphers Count Percent") -print("-----------------------------+---------+------") -for stat in sorted(FF_RC4_Only_cipherstats): - percent = round(FF_RC4_Only_cipherstats[stat] / total * 100, 4) - sys.stdout.write(stat.ljust(30) + " " + str(FF_RC4_Only_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") +for client_name in client_ciphers: + print("\n" + client_name + " selected ciphers Count Percent") + print("-----------------------------+---------+------") + for stat in sorted(client_selected_cipherstats[client_name]): + percent = round(client_selected_cipherstats[client_name][stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(client_selected_cipherstats[client_name][stat]).ljust(10) + str(percent).ljust(4) + "\n") -print("\nFF 29 RC4 pref other ciphers Count Percent") -print("-----------------------------+---------+------") -for stat in sorted(FF_RC4_preferred_cipherstats): - percent = round(FF_RC4_preferred_cipherstats[stat] / total * 100, 4) - sys.stdout.write(stat.ljust(30) + " " + str(FF_RC4_preferred_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") + print("\n" + client_name + " RC4 Only other ciphers Count Percent") + print("-----------------------------+---------+------") + for stat in sorted(client_RC4_Only_cipherstats[client_name]): + percent = round(client_RC4_Only_cipherstats[client_name][stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(client_RC4_Only_cipherstats[client_name][stat]).ljust(10) + str(percent).ljust(4) + "\n") -print("\nFF 29 incompatible ciphers Count Percent") -print("-----------------------------+---------+------") -for stat in sorted(FF_incompatible_cipherstats): - percent = round(FF_incompatible_cipherstats[stat] / total * 100, 4) - sys.stdout.write(stat.ljust(30) + " " + str(FF_incompatible_cipherstats[stat]).ljust(10) + str(percent).ljust(4) + "\n") + print("\n" + client_name + " RC4 pref other ciphers Count Percent") + print("-----------------------------+---------+------") + for stat in sorted(client_RC4_preferred_cipherstats[client_name]): + percent = round(client_RC4_preferred_cipherstats[client_name][stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(client_RC4_preferred_cipherstats[client_name][stat]).ljust(10) + str(percent).ljust(4) + "\n") + + print("\n" + client_name + " incompatible ciphers Count Percent") + print("-----------------------------+---------+------") + for stat in sorted(client_incompatible_cipherstats[client_name]): + percent = round(client_incompatible_cipherstats[client_name][stat] / total * 100, 4) + sys.stdout.write(stat.ljust(30) + " " + str(client_incompatible_cipherstats[client_name][stat]).ljust(10) + str(percent).ljust(4) + "\n") print("\nSupported Handshakes Count Percent") print("-------------------------+---------+-------") From af2e25ec897584014678abf9c9efe6915178d81c Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Sat, 25 Oct 2014 16:11:18 +0200 Subject: [PATCH 6/7] fix EDH checking old ciphers have names that use EDH instead of DHE so we need check for both names --- top1m/parse_results.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index 50ee271..fd92bbf 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -373,8 +373,9 @@ for r,d,flist in os.walk(path): if client_compat[client_name]: if 'ECDHE' in client_selected[client_name]: client_selected_cipherstats[client_name]['x:ECDHE'] += 1 - elif 'DHE' in client_selected[client_name]: - client_selected_cipherstats[client_name]['x:DHE'] += 1 + elif 'DHE' in client_selected[client_name] or \ + 'EDH' in client_selected[client_name]: + client_selected_cipherstats[client_name]['x:DHE'] += 1 else: client_selected_cipherstats[client_name]['x:kRSA'] += 1 From 29c739faa98fe7688c3f97a663e0cb57ec5e7e37 Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Sat, 25 Oct 2014 16:23:41 +0200 Subject: [PATCH 7/7] count EDH-DES as PFS too in general stats --- top1m/parse_results.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/top1m/parse_results.py b/top1m/parse_results.py index fd92bbf..0da5e42 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -276,7 +276,8 @@ for r,d,flist in os.walk(path): """ done with this file, storing the stats """ if DHE or ECDHE: pfsstats['Support PFS'] += 1 - if 'DHE-' in results['ciphersuite'][0]['cipher']: + if 'DHE-' in results['ciphersuite'][0]['cipher'] or \ + 'EDH-' in results['ciphersuite'][0]['cipher']: pfsstats['Prefer PFS'] += 1 pfsstats['Prefer ' + results['ciphersuite'][0]['pfs']] += 1 for s in temppfsstats: