From f5145f80eafc35f7b4ae5927993cd450ec3889a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Eng=C3=A9libert?= Date: Fri, 19 Dec 2025 16:50:56 +0100 Subject: [PATCH] crawl, fixes --- README.md | 44 ++++++++++++++++++- crawler.py | 94 ++++++++++++++++++++++++++++++++++++++++ exp.py | 113 +++++++++++++++++++++++++++++++++++-------------- exp_proxies.py | 2 +- plots.py | 113 +++++++++++++++++++++++++++++++++++++++++-------- profile.py | 16 +++---- servers.txt | 2 + 7 files changed, 326 insertions(+), 58 deletions(-) create mode 100644 crawler.py create mode 100644 servers.txt diff --git a/README.md b/README.md index a223fff..7341b38 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,33 @@ sudo make install * https://www.haproxy.com/blog/state-of-ssl-stacks * 2025 * OpenSSL +* https://ieeexplore.ieee.org/abstract/document/5983970 + * TLS and energy consumption on a mobile device: A measurement study + * 2011 + * TLS + * Nokia phone +* https://dspace.mit.edu/handle/1721.1/111861 + * Energy-efficient protocols and hardware architectures for transport layer security + * 2017 +* https://dl.acm.org/doi/abs/10.1145/871506.871518 + * Analyzing the energy consumption of security protocols + * 2003 + * SSL +* https://ieeexplore.ieee.org/abstract/document/1563998 + * A study of the energy consumption characteristics of cryptographic algorithms and security protocols + * 2003 + * SSL +* https://ieeexplore.ieee.org/abstract/document/8598334 + * Energy and Processing Demand Analysis of TLS Protocol in Internet of Things Applications + * 2016 + * TLS +* https://dl.acm.org/doi/10.1145/3345768.3355924 + * A Comprehensive Empirical Analysis of TLS Handshake and Record Layer on IoT Platforms + * 2019 + * IoT, TLS +* https://hal.science/hal-04197885/document + * Empreinte carbone de la transmission de données sur le backbone RENATER + * 2021 ## Sources @@ -290,11 +317,12 @@ sudo chmod +s /sbin/sa Install OpenSSL with debug symbols: ```bash -#./Configure --release -g # Options from Debian build # Debian package libssl3t64 -> Developer Information -> buildd reproducibility -> trixie rbuild # https://tests.reproducible-builds.org/debian/rb-pkg/trixie/amd64/openssl.html /usr/bin/perl ./Configure --release -g --prefix=/usr --openssldir=/usr/lib/ssl --libdir=lib/x86_64-linux-gnu shared no-idea no-mdc2 no-rc5 no-ssl3 no-ssl3-method enable-rfc3779 enable-cms no-capieng no-rdrand enable-tfo enable-zstd enable-zlib enable-fips enable-ec_nistp_64_gcc_128 +# Or, if OpenSSL 1.1: +/usr/bin/perl ./Configure --release -g --prefix=/usr --openssldir=/usr/lib/ssl --libdir=lib/x86_64-linux-gnu shared no-idea no-mdc2 no-rc5 no-ssl3 no-ssl3-method enable-rfc3779 enable-cms no-capieng no-rdrand enable-zlib enable-ec_nistp_64_gcc_128 linux-x86_64 ``` Backup your system's `libcrypto.so` and `libssl.so` and replace them with the new ones. @@ -330,3 +358,17 @@ Avant d'enregistrer le trafic, il faut observer les domaines utilisés puis gén CertVerify est l'extension dans le ServerHello qui signe la discussion passée avec la clé secrète du certificat. Il a fallu désactiver la réutilisation de session, qui en TLS1.3 passe par le PSK, pour pouvoir mesurer le CertVerify. + +## Size overhead and usage survey + +```bash +openssl s_server -port 8000 -cert /dev/shm/exp/certs/prime256v1/wikipedia.org.crt -key /dev/shm/exp/certs/prime256v1/wikipedia.org.key +curl https://wikipedia.org --tlsv1.3 --curves x25519 --connect-to wikipedia.org:443:127.0.0.1:8000 -k +``` + +Get the most used domains here https://www.akamai.com/fr/security-research/akarank + +```bash +python crawler.py crawl /dev/shm/top1K.csv +python crawler.py stat /dev/shm/crawl.json +``` diff --git a/crawler.py b/crawler.py new file mode 100644 index 0000000..b6704ba --- /dev/null +++ b/crawler.py @@ -0,0 +1,94 @@ +import json,re, subprocess, sys, threading, time + +BATCH = 50 +TIMEOUT = 4 +CAPTURES = { + "read_bytes": "SSL handshake has read (\\d+) bytes and written \\d+ bytes\n", + "written_bytes": "SSL handshake has read \\d+ bytes and written (\\d+) bytes\n", + "cert_sig": "Peer signature type: ([a-zA-Z0-9_.-]+)\n", + "cert_pk_size": "Server public key is (\\d+) bit\n", + "kx": "(?:Negotiated TLS1\\.3 group|Peer Temp Key): ([a-zA-Z0-9_.-]+)(?:\n|,)", + "cipher": "Cipher is ([a-zA-Z0-9_.-]+)\n", + "protocol": "Protocol: ([a-zA-Z0-9_.-]+)\n", +} + +lock = threading.Lock() +results = {} +subs = [] + +def probe(domain, ossl): + # End of input data, cleanly stops the session and the process + ossl.stdin.write(b"") + ossl.stdin.close() + + results[domain] = output = ossl.stdout.read().decode() + + ossl.kill() + +if __name__ == "__main__": + if sys.argv[1] == "crawl": + threads = [] + f = open(sys.argv[2], "r") + for line in f.readlines()[1:]: + #line = line.removesuffix("\n") + line = line[:line.find(",")-1] + print("start", line) + addr = f"{line}:443" + ossl = subprocess.Popen(["openssl", "s_client", "-no-interactive", addr], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + t = threading.Thread(target=probe, args=(line, ossl,)) + threads.append((t, ossl, time.time())) + time.sleep(0.05) + t.start() + if len(threads) >= BATCH: + print("wait") + for (t, ossl, start) in threads: + t.join(max(0, TIMEOUT - (time.time() - start))) + try: + ossl.kill() + except: + pass + threads.clear() + print("waited") + f.close() + + for (t, ossl, start) in threads: + t.join(max(0, TIMEOUT - (time.time() - start))) + try: + ossl.kill() + except: + pass + threads.clear() + + print("finished") + + f = open("/dev/shm/crawl.json", "w") + json.dump(results, f) + f.close() + + print("written") + + sys.exit(0) + elif sys.argv[1] == "stat": + regexes = {} + for r in CAPTURES: + regexes[r] = re.compile(CAPTURES[r]) + stats = {} + f = open(sys.argv[2], "r") + c = json.load(f) + for domain in c: + for r in CAPTURES: + try: + val = regexes[r].finditer(c[domain]).__next__().group(1) + #print(r, val) + if r in ["domain", "read_bytes", "written_bytes"]: + continue + if not r in stats: + stats[r] = {} + if not val in stats[r]: + stats[r][val] = 1 + else: + stats[r][val] += 1 + except StopIteration: + pass + #print("Not found:", line, r) + print(stats) diff --git a/exp.py b/exp.py index 6aacece..c4d9acf 100644 --- a/exp.py +++ b/exp.py @@ -2,18 +2,49 @@ import os, sys, subprocess CONFIGS = { - # placid -> pi3 - "pi": { + # i7-4790 local + "local": { "experiments": [ "impl-cipher-ver", "impl-cert-ver", "impl-kex-ver", ], + "setups": [ + "none-local", + "client-local", + "server-local", + ], + "records": [ + { "filename": "youtube", "repeat": 1 }, + ], + "repodir": "/home/tuxmain/reps/tlsbench", + "expdir": "/dev/shm/exp", + "log_backup_dir": "/home/tuxmain", + "p2_hostname": "localhost", + "p2_addr": "127.0.0.1", + "p2_repodir": "/home/tuxmain/reps/tlsbench", + "wattmeter": False, + "perf": True, + "perf_dir": "/home/tuxmain/.cache/exp", + "p3_suffix": ".localhost", + "p3_port_plain": 8080, + "p3_port_tls": 8443, + }, + # i7-4790 -> pi3 + "pi3": { + "experiments": [ + #"impl-cipher-ver", + "impl-cert-ver", + #"impl-kex-ver", + ], "setups": [ "none", "client", "server", ], + "records": [ + { "filename": "youtube", "repeat": 100 }, + ], "repodir": "/home/tuxmain/reps/tlsbench", "expdir": "/dev/shm/exp", "log_backup_dir": "/home/tuxmain", @@ -29,8 +60,7 @@ CONFIGS = { "p3_port_tls": 443, "idle": "idle - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 -", }, - # placid local - "local": { + "pi3-local": { "experiments": [ "impl-cipher-ver", "impl-cert-ver", @@ -41,21 +71,24 @@ CONFIGS = { "client-local", "server-local", ], - "repodir": "/home/tuxmain/reps/tlsbench", + "records": [ + { "filename": "wikipedia", "repeat": 5 }, + ], + "repodir": "/home/exp/exp", "expdir": "/dev/shm/exp", - "log_backup_dir": "/home/tuxmain", + "log_backup_dir": "/home/exp", "p2_hostname": "localhost", "p2_addr": "127.0.0.1", - "p2_repodir": "/home/tuxmain/reps/tlsbench", + "p2_repodir": "/home/exp/exp", "wattmeter": False, "perf": True, - "perf_dir": "/home/tuxmain/.cache/exp", + "perf_dir": "/home/exp/.cache/exp", "p3_suffix": ".localhost", "p3_port_plain": 8080, "p3_port_tls": 8443, }, - # placid -> pifou - "pifou": { + # i7-4790 -> core2 + "core2": { "experiments": [ "impl-cipher-ver", "impl-cert-ver", @@ -66,13 +99,17 @@ CONFIGS = { "client", "server", ], + "records": [ + { "filename": "wikipedia", "repeat": 400 }, + { "filename": "youtube", "repeat": 100 }, + ], "repodir": "/home/tuxmain/reps/tlsbench", "expdir": "/dev/shm/exp", "log_backup_dir": "/home/tuxmain", "p2_hostname": "192.168.3.3", "p2_addr": "192.168.3.3", "p2_ssh": "exp@192.168.3.3", - "p2_psw": "exp", + "p2_psw": None, "p2_repodir": "/home/exp/exp", "wattmeter": True, "perf": False, @@ -81,8 +118,7 @@ CONFIGS = { "p3_port_tls": 443, "idle": "idle - - - - - - 600.0001013278961 0.0 735 4942 1.7759999999999962 -", }, - # placid local - "pifou-local": { + "core2-local": { "experiments": [ "impl-cipher-ver", "impl-cert-ver", @@ -93,6 +129,9 @@ CONFIGS = { "client-local", "server-local", ], + "records": [ + { "filename": "wikipedia", "repeat": 10 }, + ], "repodir": "/home/exp/exp", "expdir": "/dev/shm/exp", "log_backup_dir": "/home/exp", @@ -132,13 +171,6 @@ DOMAINS_ = [ "videos.domainepublic.net", ] -RECORDS = [ - #{ "filename": "youtube", "repeat": 100 }, - #{ "filename": "peertube", "repeat": 10 }, - { "filename": "wikipedia", "repeat": 400 }, - #{ "filename": "apple", "repeat": 1000 }, - #{ "filename": "google", "repeat": 1000 }, -] CERT_SIGN_ALGS = [ "prime256v1", # widely used "secp384r1", # rarely used but supported by browsers because it's NIST standard @@ -146,7 +178,7 @@ CERT_SIGN_ALGS = [ "rsa2048", "rsa3072", "rsa4096", # widely used ] IMPLS = [ - "aws_lc_rs", # Amazon's Rust crypto widely used in Rust stuff + "aws_lc", # Amazon's Rust crypto widely used in Rust stuff "boring", # Google's fork of OpenSSL used in Chrome and Android "openssl", # widely used "ring", # used in most Rust stuff @@ -171,6 +203,9 @@ KEXES = [ "X25519", "SECP256R1", "SECP384R1", + "X25519MLKEM768", + "SECP256R1MLKEM768", + "MLKEM768", ] # Testing all combinations would be too much. Instead we isolate independent parts. @@ -178,7 +213,6 @@ EXPERIMENTS = { # Compare ciphers among implementations and TLS versions "impl-cipher-ver": { "impls": IMPLS, - "records": RECORDS, "ciphers": [ "AES_128_GCM_SHA256", "AES_256_GCM_SHA384", @@ -193,7 +227,6 @@ EXPERIMENTS = { # Compare signatures among implementations and TLS versions "impl-cert-ver": { "impls": IMPLS, - "records": RECORDS, "ciphers": [ "AES_128_GCM_SHA256", #"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256", @@ -210,17 +243,22 @@ EXPERIMENTS = { # Compare key exchange groups among implementations and TLS versions "impl-kex-ver": { "impls": IMPLS, - "records": RECORDS, "ciphers": [ "AES_128_GCM_SHA256", #"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256", ], - "kexes": ["X25519", "SECP256R1", "SECP384R1"], + "kexes": [ + "X25519", + "SECP256R1", + "SECP384R1", + "X25519MLKEM768", + "SECP256R1MLKEM768", + "MLKEM768", + ], "cert": ["prime256v1"], }, "debug": { "impls": IMPLS, - "records": RECORDS, "ciphers": [ "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256", #"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", @@ -230,6 +268,16 @@ EXPERIMENTS = { }, } +# Some algorithms are not available in all implementations +def alg_filter(kex, cert, cipher, impl): + if "MLKEM" in kex and impl != "openssl" and impl != "aws_lc": + return False + if kex == "SECP256R1MLKEM768" and impl == "openssl": + return False + if cert == "secp384r1" and impl == "boring": + return False + return True + DOMAINS = [] for domain in DOMAINS_: if not domain in DOMAINS: @@ -644,11 +692,13 @@ def run_exp(config, only_record=None, idle=False): ssh_run(ssh, f"python {p2_path}/exp.py cert {config_name} {alg}") for kex in exp["kexes"]: for cipher in exp["ciphers"]: + if not alg_filter(kex, alg, cipher, impl): + continue for setup in config["setups"]: if SETUPS[setup]["tls_invariant"] and not first_set: continue setupdir = expdir+"setups/"+setup - for record in exp["records"]: + for record in config["records"]: print(f"EXPERIMENT {expname}: {impl} {alg} {kex} {cipher} {setup}") p2_rpxy_config = SETUPS[setup]["rpxy_config"] vars = {"CIPHERS": cipher, "KEXES": kex, "RUST_LOG": "warning"} @@ -703,7 +753,7 @@ def run_exp(config, only_record=None, idle=False): #time.sleep(30) #sh("killall netreplay") try: - ssh_run(ssh, f"rm /dev/shm/access.log /dev/shm/rpxy.log") + #ssh_run(ssh, f"rm /dev/shm/access.log /dev/shm/rpxy.log") pass except invoke.exceptions.UnexpectedExit as e: pass @@ -841,14 +891,15 @@ Run options: exps = 0 for expname in config["experiments"]: exp = config["experiments"][expname] - exps += len(exp["impls"]) * len(exp["cert"]) * len(exp["kexes"]) * len(exp["ciphers"]) * len(exp["records"]) + exps += len(exp["impls"]) * len(exp["cert"]) * len(exp["kexes"]) * len(exp["ciphers"]) * len(config["records"]) print("Experiments to make:", exps * len(config["setups"])) exit(0) import time - import invoke import re - import fabric + if "p2_ssh" in config: + import invoke + import fabric if config["wattmeter"]: import yoctopuce diff --git a/exp_proxies.py b/exp_proxies.py index 8b5b57b..4099a97 100644 --- a/exp_proxies.py +++ b/exp_proxies.py @@ -61,7 +61,7 @@ CERT_SIGN_ALGS = [ "rsa2048", "rsa3072", "rsa4096", # widely used ] IMPLS = [ - #"aws_lc_rs", # Amazon's Rust crypto widely used in Rust stuff + #"aws_lc", # Amazon's Rust crypto widely used in Rust stuff #"boring", # Google's fork of OpenSSL used in Chrome and Android #"openssl", # widely used "ring", # used in most Rust stuff diff --git a/plots.py b/plots.py index 4d7f39b..736191a 100644 --- a/plots.py +++ b/plots.py @@ -3,20 +3,23 @@ import profile # Nice labels for algorithms of all kinds ALG_LABEL = { - "AES_128_GCM_SHA256": "AES128", - "AES_256_GCM_SHA384": "AES256", - "CHACHA20_POLY1305_SHA256": "CHACHA20", - "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256": "AES128", - "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384": "AES256", - "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "CHACHA20", - "prime256v1": "prime256v1", - "secp384r1": "secp384r1", + "AES_128_GCM_SHA256": "aes128", + "AES_256_GCM_SHA384": "aes256", + "CHACHA20_POLY1305_SHA256": "chacha20", + "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256": "aes128", + "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384": "aes256", + "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "chacha20", + "prime256v1": "p256", + "secp384r1": "p384", "rsa2048": "rsa2048", "rsa3072": "rsa3072", "rsa4096": "rsa4096", - "X25519": "X25519", - "SECP256R1": "SECP256R1", - "SECP384R1": "SECP384R1" + "X25519": "x25519", + "SECP256R1": "p256", + "SECP384R1": "p384", + "X25519MLKEM768": "x25519mlkem", + "SECP256R1MLKEM768": "p256mlkem", + "MLKEM768": "mlkem", } # Nice labels for TLS versions using ciphers @@ -56,6 +59,10 @@ CRITERION_TITLE = { "kex": "key exchange" } +def impl_title(impl): + # Gnuplot does not escape underscores when generating tex + return impl.replace("_", "-") + # Where gnuplot files, data files and images are output PLOTS_DIR = "/dev/shm/plots" @@ -87,6 +94,9 @@ set grid y lt 1 lw .75 lc "gray" plot \ newhistogram "", "{plots_dir}/{object}_by_{criterion}_{side}_{record}.dat" using 2:xticlabels(1) notitle col, \ newhistogram "", "{plots_dir}/{object}_by_{criterion}_{side}_{record}.dat" using 3:xticlabels(1) title col{cluster} +set term cairolatex pdf +set output "{plots_dir}/{object}_by_{criterion}_{side}_{record}.tex" +replot """.format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs)) f.close() os.system("gnuplot {plots_dir}/{object}_by_{criterion}_{side}_{record}.gnuplot".format(plots_dir=PLOTS_DIR, **kwargs)) @@ -108,14 +118,23 @@ set style fill solid 1.0 border lt -1 set style histogram rowstacked set style data histograms set title font "CMU Sans Serif,12" "{object_title} by {criterion_title} ({record}, {side}{machine}) ({unit})" -set xtics border in scale 0,0 nomirror noenhanced rotate by -15 autojustify +set xtics border in scale 0,0 nomirror noenhanced rotate by 30 right +set lmargin 9 +set rmargin 1 +set bmargin 5 +set tmargin 2.5 set key fixed left top vertical Left noenhanced autotitle nobox invert reverse opaque set colorbox vertical origin screen 0.9, 0.2 size screen 0.05, 0.6 front noinvert bdefault set xrange [ * : * ] noreverse writeback set yrange [ 0 : * ] set grid y lt 1 lw .75 lc "gray" plot for [i=2:{nb_functions}] "{plots_dir}/{object}_by_{criterion}_{side}_{record}.dat" using i:xticlabels(1) title col -""".format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs)) +#set term cairolatex pdf +set term pict2e font ",10" +set output "{plots_dir}/{object}_by_{criterion}_{side}_{record}.tex" +set key font ",10" spacing 0.8 +replot +""".format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs).replace("aws_lc", "aws-lc")) f.close() os.system("gnuplot {plots_dir}/{object}_by_{criterion}_{side}_{record}.gnuplot".format(plots_dir=PLOTS_DIR, **kwargs)) @@ -145,19 +164,26 @@ def make_log_plot(logs, exp, criterion, side, obj, record, machine=None): if log["impl"] not in impls: impls.append(log["impl"]) impls.sort() - f.write("{} none {}\n".format(criterion, " ".join(impls))) + f.write("{} none {}\n".format(criterion, " ".join([impl_title(impl) for impl in impls]))) f.write(plain_line+" -"*len(impls)+"\n") for cipher in ciphers: for impl in impls: if impl not in ciphers[cipher]: ciphers[cipher][impl] = 0 - f.write("{}({}) - {}\n".format( + """f.write("{}({}) - {}\n".format( ALG_LABEL[cipher], VER_LABEL[log["cipher"]], " ".join([ str(ciphers[cipher][impl]) for impl in impls ]), + ))""" + f.write("{} - {}\n".format( + ALG_LABEL[cipher], + " ".join([ + str(ciphers[cipher][impl]) + for impl in impls + ]), )) f.close() gnuplot_histogram( @@ -186,7 +212,7 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m profile_results = profile.extract_from_file(svg_filename) except FileNotFoundError: print(f"Cannot read {svg_filename}") - return + continue print(profile_results) for function in profile_results: if function not in functions: @@ -198,7 +224,7 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m }) f.write("{} {}\n".format(criterion, " ".join(functions))) for run in runs: - f.write("\"{} {}({})\" {}\n".format( + """f.write("\"{} {}({})\" {}\n".format( run["impl"], ALG_LABEL[run[criterion]], VER_LABEL[log["cipher"]], @@ -206,6 +232,14 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m str(run["functions"][function][0]) for function in functions ]), + ))""" + f.write("\"{} {}\" {}\n".format( + impl_title(run["impl"]), + ALG_LABEL[run[criterion]], + " ".join([ + str(run["functions"][function][0]) + for function in functions + ]), )) f.close() gnuplot_stacked_histogram( @@ -220,6 +254,46 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m machine=machine ) +# Are CPU and energy proportional +def make_linear_regression(logs): + idle_cpu = None + idle_energy = None + for log in logs: + if log["exp"] == "idle": + idle_cpu = float(log["cpu"]) / float(log["time"]) + idle_energy = float(log["Wh"]) / float(log["time"]) + break + + samples_cpu = {"global":[]} + samples_energy = {"global":[]} + for log in logs: + if log["impl"] == "-": + continue + sample_cpu = float(log["cpu"]) - idle_cpu * float(log["time"]) + sample_energy = float(log["Wh"]) - idle_energy * float(log["time"]) + samples_cpu["global"].append(sample_cpu) + samples_energy["global"].append(sample_energy) + if log["impl"] not in samples_cpu: + samples_cpu[log["impl"]] = [] + samples_energy[log["impl"]] = [] + samples_cpu[log["impl"]].append(sample_cpu) + samples_energy[log["impl"]].append(sample_energy) + print("Pearson correlation coefficients (energy/cpu)") + results = {} + for impl in samples_cpu: + res = stats.linregress(samples_cpu[impl], samples_energy[impl]) + print(impl, "\t", res.rvalue) + results[impl] = res + if impl != "global": + plt.plot(samples_cpu[impl], samples_energy[impl], 'o', label=impl) + #plt.plot(samples_cpu["global"], samples_energy["global"], 'o', label='samples') + plt.plot(samples_cpu["global"], res.intercept + res.slope*np.array(samples_cpu["global"]), 'r', label='fitted line') + plt.xlabel("CPU (s)") + plt.ylabel("Energy (Wh)") + plt.legend() + #plt.show() + plt.savefig(f"{PLOTS_DIR}/correlation_energy_cpu.png") + def getargv(arg:str, default="", n:int=1, args:list=sys.argv): if arg in args and len(args) > args.index(arg)+n: return args[args.index(arg)+n] @@ -267,3 +341,8 @@ if __name__ == "__main__": make_profile_plot(logs, "impl-cipher-ver", "cipher", side, record, no_flamegraph=no_flamegraph, machine=machine) make_profile_plot(logs, "impl-cert-ver", "cert", side, record, no_flamegraph=no_flamegraph, machine=machine) make_profile_plot(logs, "impl-kex-ver", "kex", side, record, no_flamegraph=no_flamegraph, machine=machine) + elif cmd == "correl": + from scipy import stats + import matplotlib.pyplot as plt + import numpy as np + make_linear_regression(logs) diff --git a/profile.py b/profile.py index c0eeac6..1b591fd 100644 --- a/profile.py +++ b/profile.py @@ -7,27 +7,27 @@ FUNCTIONS = { "<[a-zA-Z0-9_:<>]+ as rustls::crypto::cipher::MessageEncrypter>::encrypt": "encrypt", - "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::Hkdf>::expander_for_okm": "hkdf", - - "<[a-zA-Z0-9_:<>]+ as rustls::crypto::SecureRandom>::fill": "rand", - - "<[a-zA-Z0-9_:<>]+ as rustls::crypto::SupportedKxGroup>::start": "kx", - "<[a-zA-Z0-9_:<>]+ as rustls::crypto::hash::Hash>::start": "hash", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::hash::Context>::finish": "hash", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::hash::Context>::update": "hash", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::hash::Context>::fork_finish": "hash", - "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::Hkdf>::extract_from_secret": "hkdf", - + "<[a-zA-Z0-9_:<>]+ as rustls::crypto::SupportedKxGroup>::start": "kx", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::ActiveKeyExchange>::complete": "kx", + "<[a-zA-Z0-9_:<>]+ as rustls::crypto::SupportedKxGroup>::start_and_complete": "kx", + "<[a-zA-Z0-9_:<>]+ as rustls::crypto::SupportedKxGroup>::start": "kx", + "<[a-zA-Z0-9_:<>]+ as rustls::crypto::SecureRandom>::fill": "rand", + + "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::Hkdf>::expander_for_okm": "hkdf", + "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::Hkdf>::extract_from_secret": "hkdf", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::HkdfExpander>::hash_len": "hkdf", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::HkdfExpander>::expand_slice": "hkdf", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::Hkdf>::extract_from_secret": "hkdf", "<[a-zA-Z0-9_:<>]+ as rustls::crypto::tls13::Hkdf>::hmac_sign": "hkdf", "ring::hkdf::fill_okm": "hkdf", + #"ring::hkdf::Salt::extract": "hkdf", "aws_lc_0_32_2_HKDF": "hkdf", #"rustls_openssl::tls13::::encrypter": "encrypt", diff --git a/servers.txt b/servers.txt new file mode 100644 index 0000000..f3b1528 --- /dev/null +++ b/servers.txt @@ -0,0 +1,2 @@ +domain_name,output_rank,date +google.com.,1,2025-12-18