Skip to content

Commit

Permalink
WIP: Benchmark redwood vs gpg
Browse files Browse the repository at this point in the history
Compile the Rust code in --release mode in the dev environment for more
accurate benchmarking.
  • Loading branch information
legoktm committed Oct 25, 2023
1 parent 9a949b3 commit 4affb8d
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 6 deletions.
8 changes: 2 additions & 6 deletions redwood/build-wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,8 @@

os.chdir(args.redwood)

if args.release:
flavor = "release"
cargo_flags = ["--release"]
else:
flavor = "debug"
cargo_flags = []
flavor = "release"
cargo_flags = ["--release"]

env = {"CARGO_TARGET_DIR": str(args.target), **os.environ}

Expand Down
124 changes: 124 additions & 0 deletions securedrop/benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/opt/venvs/securedrop-app-code/bin/python

import os
import sys
import tempfile
import timeit
from io import BytesIO
from pathlib import Path

import pretty_bad_protocol as gnupg

import redwood

os.environ["USERNAME"] = "www-data"

PASSPHRASE = "correcthorsebatterystaple"
COUNTER = 0
FAST = "--fast" in sys.argv


def format_time(dt):
"""Copied out of timeit.main()"""
units = {"nsec": 1e-9, "usec": 1e-6, "msec": 1e-3, "sec": 1.0}
precision = 3
scales = [(scale, unit) for unit, scale in units.items()]
scales.sort(reverse=True)
for scale, unit in scales:
if dt >= scale:
break

return "%.*g %s" % (precision, dt / scale, unit)


sizes = [
(5_000, "5KB"),
(50_000, "50KB"),
(500_000, "500KB"),
(5_000_000, "5MB"),
]
if not FAST:
sizes.extend(
[
(50_000_000, "50MB"),
(500_000_000, "500MB"),
]
)

r_public_key, r_secret_key, r_fingerprint = redwood.generate_source_key_pair(PASSPHRASE, "foobar")
with tempfile.TemporaryDirectory() as tmpdir:
tmpdir = Path(tmpdir)
gpg = gnupg.GPG(
binary="gpg2",
homedir=str(tmpdir),
options=["--pinentry-mode loopback", "--trust-model direct"],
)
g_fingerprint = gpg.gen_key(
gpg.gen_key_input(
passphrase=PASSPHRASE,
name_email="foobar",
key_type="RSA",
key_length=4096,
name_real="Source Key",
creation_date="2013-05-14",
expire_date="0",
)
).fingerprint
g_public_key = gpg.export_keys(g_fingerprint)
if not g_public_key:
raise RuntimeError("failed exporting public key")

for (input_bytes, human_bytes) in sizes:
loops = 10 if input_bytes >= 50_000_000 else 100
clean = input_bytes >= 50_000_000
plaintext = tmpdir / "message.txt"
plaintext.write_text("A" * input_bytes)
ciphertext = tmpdir / "message.asc"
if ciphertext.exists():
# Delete before we overwrite it.
ciphertext.unlink()
redwood.encrypt_stream([r_public_key, g_public_key], plaintext.open(mode="rb"), ciphertext)
ciphertext_bytes = ciphertext.read_bytes()

def redwood_encrypt(clean=False):
global COUNTER
COUNTER += 1
ciphertext = tmpdir / f"message-{COUNTER}.asc"

redwood.encrypt_stream([r_public_key], plaintext.open(mode="rb"), ciphertext)
if clean:
ciphertext.unlink()

def redwood_decrypt():
redwood.decrypt(ciphertext_bytes, r_secret_key, PASSPHRASE)

def gpg_encrypt(clean=False):
global COUNTER
COUNTER += 1
ciphertext = tmpdir / f"message-{COUNTER}.asc"
res = gpg.encrypt(
plaintext.open(mode="rb"),
g_fingerprint,
output=str(ciphertext),
always_trust=True,
armor=False,
)
if not res.ok:
raise RuntimeError("gpg encryption failed")
if clean:
ciphertext.unlink()

def gpg_decrypt():
res = gpg.decrypt_file(BytesIO(ciphertext_bytes), passphrase=PASSPHRASE)
if not res.ok:
raise RuntimeError(res.stderr)

print(f"== {human_bytes} ({loops} & 10 loops) ==")
r_duration = timeit.repeat(lambda: redwood_encrypt(clean), number=loops)
print(f"redwood encrypt: {[format_time(dt) for dt in r_duration]}")
g_duration = timeit.repeat(lambda: gpg_encrypt(clean), number=loops)
print(f"gpg encrypt : {[format_time(dt) for dt in g_duration]}")
r2_duration = timeit.repeat(redwood_decrypt, number=10)
print(f"redwood decrypt: {[format_time(dt) for dt in r2_duration]}")
g2_duration = timeit.repeat(gpg_decrypt, number=10)
print(f"gpg decrypt : {[format_time(dt) for dt in g2_duration]}")

0 comments on commit 4affb8d

Please sign in to comment.