Files
Odin/tests/benchmark/crypto/benchmark_rsa.odin
2026-07-12 06:17:08 +09:00

161 lines
4.0 KiB
Odin

package benchmark_core_crypto
import "base:runtime"
import "core:log"
import "core:testing"
import "core:text/table"
import "core:time"
import "core:crypto"
import "core:crypto/rsa"
// RSA key generation is time consuming and high variance, so it takes
// an unreasonable amount of time to get a semi-sensible value, so this
// is skipped by default.
RSA_BENCH_KEYGEN: bool : #config(ODIN_BENCHMARK_RSA_KEYGEN, false)
@(private = "file")
KEYGEN_ITERS :: 100
@(private = "file")
SIGN_ITERS :: 5000
@(private = "file")
ENCRYPT_ITERS :: 5000
@(test)
benchmark_crypto_rsa :: proc(t: ^testing.T) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
tbl: table.Table
table.init(&tbl)
defer table.destroy(&tbl)
table.caption(&tbl, "RSA")
table.aligned_header_of_values(&tbl, .Right, "Operation", "Avg. Time")
if RSA_BENCH_KEYGEN {
bench_keygen_2048(&tbl)
table.row_of_values(&tbl)
}
bench_pkcs1_2048(&tbl)
table.row_of_values(&tbl)
bench_pss_2048(&tbl)
table.row_of_values(&tbl)
bench_oaep_2048(&tbl)
log_table(&tbl)
}
@(private="file")
bench_keygen_2048 :: proc(tbl: ^table.Table) {
if !crypto.HAS_RAND_BYTES {
log.warnf("rsa: keygen benchmarks skipped, no system entropy source")
}
priv_key: rsa.Private_Key
start := time.tick_now()
for _ in 0 ..< KEYGEN_ITERS {
ok := rsa.private_key_generate(&priv_key, 2048)
assert(ok, "keygen should succeed")
}
taken := time.tick_since(start) / KEYGEN_ITERS
append_tbl(tbl, "Keygen/2048", taken)
}
@(private="file")
bench_pkcs1_2048 :: proc(tbl: ^table.Table) {
priv_key: rsa.Private_Key
_ = rsa.private_key_set_insecure_test(&priv_key)
msg_bytes := transmute([]byte)(SIG_MSG)
sig_bytes: [2048 >> 3]byte
start := time.tick_now()
for _ in 0 ..< SIGN_ITERS {
ok := rsa.sign_pkcs1(&priv_key, .SHA256, msg_bytes, sig_bytes[:])
assert(ok, "signing should succeed")
}
taken := time.tick_since(start) / SIGN_ITERS
append_tbl(tbl, "PKCS1/2048/SHA256/sign", taken)
start = time.tick_now()
for _ in 0 ..< KEYGEN_ITERS {
ok := rsa.verify_pkcs1(&priv_key._pub_key, .SHA256, msg_bytes, sig_bytes[:])
assert(ok, "verify should succeed")
}
taken = time.tick_since(start) / SIGN_ITERS
append_tbl(tbl, "PKCS1/2048/SHA256/verify", taken)
}
@(private="file")
bench_pss_2048 :: proc(tbl: ^table.Table) {
priv_key: rsa.Private_Key
_ = rsa.private_key_set_insecure_test(&priv_key)
msg_bytes := transmute([]byte)(SIG_MSG)
sig_bytes: [2048 >> 3]byte
start := time.tick_now()
for _ in 0 ..< SIGN_ITERS {
ok := rsa.sign_pss(&priv_key, .SHA256, 32, msg_bytes, sig_bytes[:])
assert(ok, "signing should succeed")
}
taken := time.tick_since(start) / SIGN_ITERS
append_tbl(tbl, "PSS/2048/SHA256/sign", taken)
start = time.tick_now()
for _ in 0 ..< KEYGEN_ITERS {
ok := rsa.verify_pss(&priv_key._pub_key, .SHA256, 32, msg_bytes, sig_bytes[:])
assert(ok, "verify should succeed")
}
taken = time.tick_since(start) / SIGN_ITERS
append_tbl(tbl, "PSS/2048/SHA256/verify", taken)
}
@(private="file")
bench_oaep_2048 :: proc(tbl: ^table.Table) {
if !crypto.HAS_RAND_BYTES {
log.info("rand_bytes not supported - skipping")
return
}
priv_key: rsa.Private_Key
_ = rsa.private_key_set_insecure_test(&priv_key)
msg_bytes := transmute([]byte)(SIG_MSG)
ciphertext_bytes: [2048 >> 3]byte
buf: [32]byte
start := time.tick_now()
for _ in 0 ..< SIGN_ITERS {
ok := rsa.encrypt_oaep(&priv_key._pub_key, .SHA256, msg_bytes, ciphertext_bytes[:])
assert(ok, "encryption should succeed")
}
taken := time.tick_since(start) / ENCRYPT_ITERS
append_tbl(tbl, "OAEP/2048/SHA256/encrypt", taken)
start = time.tick_now()
for _ in 0 ..< KEYGEN_ITERS {
_, ok := rsa.decrypt_oaep(&priv_key, .SHA256, ciphertext_bytes[:], buf[:])
assert(ok, "decrypt should succeed")
}
taken = time.tick_since(start) / ENCRYPT_ITERS
append_tbl(tbl, "OAEP/2048/SHA256/decrypt", taken)
}
@(private="file")
append_tbl :: proc(tbl: ^table.Table, op_name: string, avg_time: time.Duration) {
table.aligned_row_of_values(
tbl,
.Right,
op_name,
table.format(tbl, "%8M", avg_time),
)
}