mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
test/benchmarks/crypto: Improve benchmarks
- Use text/table for results - Add more benchmarks
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:crypto"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:text/table"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
import "core:crypto/aead"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
ITERS :: 10000
|
||||||
|
@(private = "file")
|
||||||
|
SIZES := []int{64, 1024, 65536}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_crypto_aead :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
tbl: table.Table
|
||||||
|
table.init(&tbl)
|
||||||
|
defer table.destroy(&tbl)
|
||||||
|
|
||||||
|
table.caption(&tbl, "AEAD")
|
||||||
|
table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput")
|
||||||
|
|
||||||
|
for algo, i in aead.Algorithm {
|
||||||
|
if algo == .Invalid {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i > 1 {
|
||||||
|
table.row(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
algo_name := aead.ALGORITHM_NAMES[algo]
|
||||||
|
key_sz := aead.KEY_SIZES[algo]
|
||||||
|
|
||||||
|
key := make([]byte, key_sz, context.temp_allocator)
|
||||||
|
crypto.rand_bytes(key)
|
||||||
|
|
||||||
|
// TODO: Benchmark all available imlementations?
|
||||||
|
ctx: aead.Context
|
||||||
|
aead.init(&ctx, algo, key)
|
||||||
|
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = aead.IV_SIZES[algo] + sz,
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_aead,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
context.user_ptr = &ctx
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
algo_name,
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_table(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_aead :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
tag_: [aead.MAX_TAG_SIZE]byte
|
||||||
|
|
||||||
|
ctx := (^aead.Context)(context.user_ptr)
|
||||||
|
iv_sz := aead.iv_size(ctx)
|
||||||
|
|
||||||
|
iv := options.input[:iv_sz]
|
||||||
|
buf := options.input[iv_sz:]
|
||||||
|
tag := tag_[:aead.tag_size(ctx)]
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
aead.seal_ctx(ctx, buf, tag, iv, nil, buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * (options.bytes - iv_sz)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -1,552 +0,0 @@
|
|||||||
package benchmark_core_crypto
|
|
||||||
|
|
||||||
import "base:runtime"
|
|
||||||
import "core:encoding/hex"
|
|
||||||
import "core:fmt"
|
|
||||||
import "core:log"
|
|
||||||
import "core:strings"
|
|
||||||
import "core:testing"
|
|
||||||
import "core:time"
|
|
||||||
|
|
||||||
import "core:crypto/aegis"
|
|
||||||
import "core:crypto/aes"
|
|
||||||
import "core:crypto/chacha20"
|
|
||||||
import "core:crypto/chacha20poly1305"
|
|
||||||
import "core:crypto/deoxysii"
|
|
||||||
import "core:crypto/ed25519"
|
|
||||||
import "core:crypto/poly1305"
|
|
||||||
import "core:crypto/x25519"
|
|
||||||
import "core:crypto/x448"
|
|
||||||
|
|
||||||
// Cryptographic primitive benchmarks.
|
|
||||||
|
|
||||||
@(test)
|
|
||||||
benchmark_crypto :: proc(t: ^testing.T) {
|
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
|
||||||
|
|
||||||
str: strings.Builder
|
|
||||||
strings.builder_init(&str, context.allocator)
|
|
||||||
defer {
|
|
||||||
log.info(strings.to_string(str))
|
|
||||||
strings.builder_destroy(&str)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
name := "AES256-CTR 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_aes256_ctr,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "AES256-CTR 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "AES256-CTR 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name := "ChaCha20 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_chacha20,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "ChaCha20 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "ChaCha20 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name := "Poly1305 64 zero bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_poly1305,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "Poly1305 1024 zero bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name := "chacha20poly1305 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_chacha20poly1305,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "chacha20poly1305 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "chacha20poly1305 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name := "AES256-GCM 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_aes256_gcm,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
key := [aes.KEY_SIZE_256]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
ctx: aes.Context_GCM
|
|
||||||
aes.init_gcm(&ctx, key[:])
|
|
||||||
|
|
||||||
context.user_ptr = &ctx
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "AES256-GCM 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "AES256-GCM 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name := "AEGIS-256 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_aegis_256,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
key := [aegis.KEY_SIZE_256]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
ctx: aegis.Context
|
|
||||||
aegis.init(&ctx, key[:])
|
|
||||||
|
|
||||||
context.user_ptr = &ctx
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "AEGIS-256 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "AEGIS-256 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name := "Deoxys-II-256 64 bytes"
|
|
||||||
options := &time.Benchmark_Options {
|
|
||||||
rounds = 1_000,
|
|
||||||
bytes = 64,
|
|
||||||
setup = _setup_sized_buf,
|
|
||||||
bench = _benchmark_deoxysii_256,
|
|
||||||
teardown = _teardown_sized_buf,
|
|
||||||
}
|
|
||||||
|
|
||||||
key := [aegis.KEY_SIZE_256]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
ctx: deoxysii.Context
|
|
||||||
deoxysii.init(&ctx, key[:])
|
|
||||||
|
|
||||||
context.user_ptr = &ctx
|
|
||||||
|
|
||||||
err := time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "Deoxys-II-256 1024 bytes"
|
|
||||||
options.bytes = 1024
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
|
|
||||||
name = "Deoxys-II-256 65536 bytes"
|
|
||||||
options.bytes = 65536
|
|
||||||
err = time.benchmark(options, context.allocator)
|
|
||||||
testing.expect(t, err == nil, name)
|
|
||||||
benchmark_print(&str, name, options)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
iters :: 10000
|
|
||||||
|
|
||||||
priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
|
||||||
priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator)
|
|
||||||
priv_key: ed25519.Private_Key
|
|
||||||
start := time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes)
|
|
||||||
assert(ok, "private key should deserialize")
|
|
||||||
}
|
|
||||||
elapsed := time.since(start)
|
|
||||||
fmt.sbprintfln(&str,
|
|
||||||
"ed25519.private_key_set_bytes: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
|
|
||||||
pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing"
|
|
||||||
pub_key: ed25519.Public_Key
|
|
||||||
start = time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:])
|
|
||||||
assert(ok, "public key should deserialize")
|
|
||||||
}
|
|
||||||
elapsed = time.since(start)
|
|
||||||
fmt.sbprintfln(&str,
|
|
||||||
"ed25519.public_key_set_bytes: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
|
|
||||||
msg := "Got a job for you, 621."
|
|
||||||
sig_bytes: [ed25519.SIGNATURE_SIZE]byte
|
|
||||||
msg_bytes := transmute([]byte)(msg)
|
|
||||||
start = time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ed25519.sign(&priv_key, msg_bytes, sig_bytes[:])
|
|
||||||
}
|
|
||||||
elapsed = time.since(start)
|
|
||||||
fmt.sbprintfln(&str,
|
|
||||||
"ed25519.sign: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
|
|
||||||
start = time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
ok := ed25519.verify(&pub_key, msg_bytes, sig_bytes[:])
|
|
||||||
assert(ok, "signature should validate")
|
|
||||||
}
|
|
||||||
elapsed = time.since(start)
|
|
||||||
fmt.sbprintfln(&str,
|
|
||||||
"ed25519.verify: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
|
||||||
scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
|
||||||
|
|
||||||
point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
|
|
||||||
scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
|
|
||||||
out: [x25519.POINT_SIZE]byte = ---
|
|
||||||
|
|
||||||
iters :: 10000
|
|
||||||
start := time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
x25519.scalarmult(out[:], scalar[:], point[:])
|
|
||||||
}
|
|
||||||
elapsed := time.since(start)
|
|
||||||
|
|
||||||
fmt.sbprintfln(&str,
|
|
||||||
"x25519.scalarmult: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
|
||||||
point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
|
||||||
scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
|
||||||
|
|
||||||
point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
|
|
||||||
scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
|
|
||||||
out: [x448.POINT_SIZE]byte = ---
|
|
||||||
|
|
||||||
iters :: 10000
|
|
||||||
start := time.now()
|
|
||||||
for i := 0; i < iters; i = i + 1 {
|
|
||||||
x448.scalarmult(out[:], scalar[:], point[:])
|
|
||||||
}
|
|
||||||
elapsed := time.since(start)
|
|
||||||
|
|
||||||
fmt.sbprintfln(&str,
|
|
||||||
"x448.scalarmult: ~%f us/op",
|
|
||||||
time.duration_microseconds(elapsed) / iters,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_setup_sized_buf :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
assert(options != nil)
|
|
||||||
|
|
||||||
options.input = make([]u8, options.bytes, allocator)
|
|
||||||
return nil if len(options.input) == options.bytes else .Allocation_Error
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_teardown_sized_buf :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
assert(options != nil)
|
|
||||||
|
|
||||||
delete(options.input)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_benchmark_chacha20 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [chacha20.KEY_SIZE]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
iv := [chacha20.IV_SIZE]byte {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx: chacha20.Context = ---
|
|
||||||
chacha20.init(&ctx, key[:], iv[:])
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
chacha20.xor_bytes(&ctx, buf, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_benchmark_poly1305 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [poly1305.KEY_SIZE]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
|
|
||||||
tag: [poly1305.TAG_SIZE]byte = ---
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
poly1305.sum(tag[:], buf, key[:])
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
//options.hash = u128(h)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_benchmark_chacha20poly1305 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [chacha20.KEY_SIZE]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
iv := [chacha20.IV_SIZE]byte {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx: chacha20poly1305.Context = ---
|
|
||||||
chacha20poly1305.init(&ctx, key[:]) // Basically 0 overhead.
|
|
||||||
|
|
||||||
tag: [chacha20poly1305.TAG_SIZE]byte = ---
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
chacha20poly1305.seal(&ctx, buf, tag[:], iv[:], nil, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_benchmark_aes256_ctr :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
key := [aes.KEY_SIZE_256]byte {
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
||||||
}
|
|
||||||
iv := [aes.CTR_IV_SIZE]byte {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx: aes.Context_CTR = ---
|
|
||||||
aes.init_ctr(&ctx, key[:], iv[:])
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
aes.xor_bytes_ctr(&ctx, buf, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_aes256_gcm :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
iv: [aes.GCM_IV_SIZE]byte
|
|
||||||
tag: [aes.GCM_TAG_SIZE]byte = ---
|
|
||||||
|
|
||||||
ctx := (^aes.Context_GCM)(context.user_ptr)
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
aes.seal_gcm(ctx, buf, tag[:], iv[:], nil, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_aegis_256 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
iv: [aegis.IV_SIZE_256]byte
|
|
||||||
tag: [aegis.TAG_SIZE_128]byte = ---
|
|
||||||
|
|
||||||
ctx := (^aegis.Context)(context.user_ptr)
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
aegis.seal(ctx, buf, tag[:], iv[:], nil, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_benchmark_deoxysii_256 :: proc(
|
|
||||||
options: ^time.Benchmark_Options,
|
|
||||||
allocator := context.allocator,
|
|
||||||
) -> (
|
|
||||||
err: time.Benchmark_Error,
|
|
||||||
) {
|
|
||||||
buf := options.input
|
|
||||||
iv: [deoxysii.IV_SIZE]byte
|
|
||||||
tag: [deoxysii.TAG_SIZE]byte = ---
|
|
||||||
|
|
||||||
ctx := (^deoxysii.Context)(context.user_ptr)
|
|
||||||
|
|
||||||
for _ in 0 ..= options.rounds {
|
|
||||||
deoxysii.seal(ctx, buf, tag[:], iv[:], nil, buf)
|
|
||||||
}
|
|
||||||
options.count = options.rounds
|
|
||||||
options.processed = options.rounds * options.bytes
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
benchmark_print :: proc(str: ^strings.Builder, name: string, options: ^time.Benchmark_Options, loc := #caller_location) {
|
|
||||||
fmt.sbprintfln(str, "[%v] %v rounds, %v bytes processed in %v ns\n\t\t%5.3f rounds/s, %5.3f MiB/s\n",
|
|
||||||
name,
|
|
||||||
options.rounds,
|
|
||||||
options.processed,
|
|
||||||
time.duration_nanoseconds(options.duration),
|
|
||||||
options.rounds_per_second,
|
|
||||||
options.megabytes_per_second,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:encoding/hex"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:text/table"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
import "core:crypto/ed25519"
|
||||||
|
import "core:crypto/x25519"
|
||||||
|
import "core:crypto/x448"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
ECDH_ITERS :: 10000
|
||||||
|
@(private = "file")
|
||||||
|
DSA_ITERS :: 10000
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_crypto_ecc :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
bench_ecdh()
|
||||||
|
bench_dsa()
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
bench_ecdh :: proc() {
|
||||||
|
tbl: table.Table
|
||||||
|
table.init(&tbl)
|
||||||
|
defer table.destroy(&tbl)
|
||||||
|
|
||||||
|
table.caption(&tbl, "ECDH")
|
||||||
|
table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Scalar-Basepoint", "Scalar-Point")
|
||||||
|
|
||||||
|
append_tbl := proc(tbl: ^table.Table, algo_name: string, bp, sc: time.Duration) {
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
tbl,
|
||||||
|
.Right,
|
||||||
|
algo_name,
|
||||||
|
table.format(tbl, "%8M", bp),
|
||||||
|
table.format(tbl, "%8M", sc),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar_bp, scalar := bench_x25519()
|
||||||
|
append_tbl(&tbl, "X25519", scalar_bp, scalar)
|
||||||
|
|
||||||
|
scalar_bp, scalar = bench_x448()
|
||||||
|
append_tbl(&tbl, "X448", scalar_bp, scalar)
|
||||||
|
|
||||||
|
log_table(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
bench_x25519 :: proc() -> (bp, sc: time.Duration) {
|
||||||
|
point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||||
|
scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
||||||
|
|
||||||
|
point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
|
||||||
|
scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
|
||||||
|
out: [x25519.POINT_SIZE]byte = ---
|
||||||
|
|
||||||
|
start := time.tick_now()
|
||||||
|
for _ in 0 ..< ECDH_ITERS {
|
||||||
|
x25519.scalarmult_basepoint(out[:], scalar[:])
|
||||||
|
}
|
||||||
|
bp = time.tick_since(start) / ECDH_ITERS
|
||||||
|
|
||||||
|
start = time.tick_now()
|
||||||
|
for _ in 0 ..< ECDH_ITERS {
|
||||||
|
x25519.scalarmult(out[:], scalar[:], point[:])
|
||||||
|
}
|
||||||
|
sc = time.tick_since(start) / ECDH_ITERS
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
bench_x448 :: proc() -> (bp, sc: time.Duration) {
|
||||||
|
point_str := "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||||
|
scalar_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
||||||
|
|
||||||
|
point, _ := hex.decode(transmute([]byte)(point_str), context.temp_allocator)
|
||||||
|
scalar, _ := hex.decode(transmute([]byte)(scalar_str), context.temp_allocator)
|
||||||
|
out: [x448.POINT_SIZE]byte = ---
|
||||||
|
|
||||||
|
start := time.tick_now()
|
||||||
|
for _ in 0 ..< ECDH_ITERS {
|
||||||
|
x448.scalarmult_basepoint(out[:], scalar[:])
|
||||||
|
}
|
||||||
|
bp = time.tick_since(start) / ECDH_ITERS
|
||||||
|
|
||||||
|
start = time.tick_now()
|
||||||
|
for _ in 0 ..< ECDH_ITERS {
|
||||||
|
x448.scalarmult(out[:], scalar[:], point[:])
|
||||||
|
}
|
||||||
|
sc = time.tick_since(start) / ECDH_ITERS
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
bench_dsa :: proc() {
|
||||||
|
tbl: table.Table
|
||||||
|
table.init(&tbl)
|
||||||
|
defer table.destroy(&tbl)
|
||||||
|
|
||||||
|
table.caption(&tbl, "ECDSA/EdDSA")
|
||||||
|
table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Op", "Time")
|
||||||
|
|
||||||
|
append_tbl := proc(tbl: ^table.Table, algo_name, op: string, t: time.Duration) {
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
tbl,
|
||||||
|
.Right,
|
||||||
|
algo_name,
|
||||||
|
op,
|
||||||
|
table.format(tbl, "%8M", t),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
sk, sig, verif := bench_ed25519()
|
||||||
|
append_tbl(&tbl, "ed25519", "private_key_set_bytes", sk)
|
||||||
|
append_tbl(&tbl, "ed25519", "sign", sig)
|
||||||
|
append_tbl(&tbl, "ed25519", "verify", verif)
|
||||||
|
|
||||||
|
log_table(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
bench_ed25519 :: proc() -> (sk, sig, verif: time.Duration) {
|
||||||
|
priv_str := "cafebabecafebabecafebabecafebabecafebabecafebabecafebabecafebabe"
|
||||||
|
priv_bytes, _ := hex.decode(transmute([]byte)(priv_str), context.temp_allocator)
|
||||||
|
priv_key: ed25519.Private_Key
|
||||||
|
start := time.tick_now()
|
||||||
|
for _ in 0 ..< DSA_ITERS {
|
||||||
|
ok := ed25519.private_key_set_bytes(&priv_key, priv_bytes)
|
||||||
|
assert(ok, "private key should deserialize")
|
||||||
|
}
|
||||||
|
sk = time.tick_since(start) / DSA_ITERS
|
||||||
|
|
||||||
|
pub_bytes := priv_key._pub_key._b[:] // "I know what I am doing"
|
||||||
|
pub_key: ed25519.Public_Key
|
||||||
|
ok := ed25519.public_key_set_bytes(&pub_key, pub_bytes[:])
|
||||||
|
assert(ok, "public key should deserialize")
|
||||||
|
|
||||||
|
msg := "Got a job for you, 621."
|
||||||
|
sig_bytes: [ed25519.SIGNATURE_SIZE]byte
|
||||||
|
msg_bytes := transmute([]byte)(msg)
|
||||||
|
start = time.tick_now()
|
||||||
|
for _ in 0 ..< DSA_ITERS {
|
||||||
|
ed25519.sign(&priv_key, msg_bytes, sig_bytes[:])
|
||||||
|
}
|
||||||
|
sig = time.tick_since(start) / DSA_ITERS
|
||||||
|
|
||||||
|
start = time.tick_now()
|
||||||
|
for _ in 0 ..< DSA_ITERS {
|
||||||
|
ok = ed25519.verify(&pub_key, msg_bytes, sig_bytes[:])
|
||||||
|
assert(ok, "signature should validate")
|
||||||
|
}
|
||||||
|
verif = time.tick_since(start) / DSA_ITERS
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:text/table"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
import "core:crypto/hash"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
ITERS :: 10000
|
||||||
|
@(private = "file")
|
||||||
|
SIZES := []int{64, 1024, 65536}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_crypto_hash :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
tbl: table.Table
|
||||||
|
table.init(&tbl)
|
||||||
|
defer table.destroy(&tbl)
|
||||||
|
|
||||||
|
table.caption(&tbl, "Hash")
|
||||||
|
table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput")
|
||||||
|
|
||||||
|
for algo, i in hash.Algorithm {
|
||||||
|
// Skip the sentinel value, and uncommon algorithms
|
||||||
|
#partial switch algo {
|
||||||
|
case .Invalid:
|
||||||
|
continue
|
||||||
|
case .Legacy_KECCAK_224, .Legacy_KECCAK_256, .Legacy_KECCAK_384, .Legacy_KECCAK_512:
|
||||||
|
// Skip: Legacy and not worth using over SHA3
|
||||||
|
continue
|
||||||
|
case .Insecure_MD5, .Insecure_SHA1:
|
||||||
|
// Skip: Legacy and not worth using at all
|
||||||
|
continue
|
||||||
|
case .SHA224, .SHA384, .SHA3_224, .SHA3_384:
|
||||||
|
// Skip: Uncommon SHA2/SHA3 variants
|
||||||
|
continue
|
||||||
|
case .SM3:
|
||||||
|
// Skip: Liberty Prime is online. All systems nominal.
|
||||||
|
// Weapons hot. Mission: the destruction of any and
|
||||||
|
// all Chinese communists.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if i > 1 {
|
||||||
|
table.row(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
algo_name := hash.ALGORITHM_NAMES[algo]
|
||||||
|
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = sz,
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_hash,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
tmp := algo
|
||||||
|
context.user_ptr = &tmp
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
algo_name,
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_table(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_hash :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
digest_: [hash.MAX_DIGEST_SIZE]byte
|
||||||
|
|
||||||
|
buf := options.input
|
||||||
|
algo := (^hash.Algorithm)(context.user_ptr)^
|
||||||
|
digest := digest_[:hash.DIGEST_SIZES[algo]]
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
hash.hash_bytes_to_buffer(algo, buf, digest)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * (options.bytes)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:text/table"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
import "core:crypto/hmac"
|
||||||
|
import "core:crypto/kmac"
|
||||||
|
import "core:crypto/poly1305"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
ITERS :: 10000
|
||||||
|
@(private = "file")
|
||||||
|
SIZES := []int{64, 1024, 65536}
|
||||||
|
@(private = "file")
|
||||||
|
KMAC_KEY_SIZES := []int{128, 256}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_crypto_mac :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
tbl: table.Table
|
||||||
|
table.init(&tbl)
|
||||||
|
defer table.destroy(&tbl)
|
||||||
|
|
||||||
|
table.caption(&tbl, "MAC")
|
||||||
|
table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput")
|
||||||
|
|
||||||
|
{
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = sz,
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_hmac_sha_256,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
"HMAC-SHA256",
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.row(&tbl)
|
||||||
|
|
||||||
|
for key_sz, i in KMAC_KEY_SIZES {
|
||||||
|
if i > 0 {
|
||||||
|
table.row(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = sz,
|
||||||
|
processed = key_sz, // Pls ignore.
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_kmac,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
table.format(&tbl, "KMAC%d", key_sz),
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.row(&tbl)
|
||||||
|
|
||||||
|
{
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = sz,
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_poly1305,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
"poly1305",
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_table(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_hmac_sha_256 :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
key := [32]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
|
||||||
|
tag: [32]byte = ---
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
hmac.sum(.SHA256, tag[:], buf, key[:])
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_kmac :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
key := [kmac.MIN_KEY_SIZE_256]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
sec_strength := options.processed
|
||||||
|
|
||||||
|
tag: [32]byte = ---
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
kmac.sum(sec_strength, tag[:sec_strength/8], buf, key[:], nil)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_poly1305 :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
buf := options.input
|
||||||
|
key := [poly1305.KEY_SIZE]byte {
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||||
|
}
|
||||||
|
|
||||||
|
tag: [poly1305.TAG_SIZE]byte = ---
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
poly1305.sum(tag[:], buf, key[:])
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "base:runtime"
|
||||||
|
import "core:crypto"
|
||||||
|
import "core:testing"
|
||||||
|
import "core:text/table"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
import "core:crypto/aes"
|
||||||
|
import "core:crypto/chacha20"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
ITERS :: 10000
|
||||||
|
@(private = "file")
|
||||||
|
SIZES := []int{64, 1024, 65536}
|
||||||
|
@(private = "file")
|
||||||
|
AES_CTR_KEY_SIZES := []int{128, 192, 256}
|
||||||
|
|
||||||
|
@(test)
|
||||||
|
benchmark_crypto_stream :: proc(t: ^testing.T) {
|
||||||
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
|
||||||
|
|
||||||
|
tbl: table.Table
|
||||||
|
table.init(&tbl)
|
||||||
|
defer table.destroy(&tbl)
|
||||||
|
|
||||||
|
table.caption(&tbl, "Stream Cipher")
|
||||||
|
table.aligned_header_of_values(&tbl, .Right, "Algorithm", "Size", "Time", "Throughput")
|
||||||
|
|
||||||
|
for key_sz, i in AES_CTR_KEY_SIZES {
|
||||||
|
if i > 0 {
|
||||||
|
table.row(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
key := make([]byte, key_sz/8, context.temp_allocator)
|
||||||
|
iv := make([]byte, aes.CTR_IV_SIZE, context.temp_allocator)
|
||||||
|
crypto.rand_bytes(key)
|
||||||
|
crypto.rand_bytes(iv)
|
||||||
|
|
||||||
|
ctx: aes.Context_CTR
|
||||||
|
aes.init_ctr(&ctx, key, iv)
|
||||||
|
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = sz,
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_aes_ctr,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
context.user_ptr = &ctx
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
table.format(&tbl, "AES%d-CTR", key_sz),
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.row(&tbl)
|
||||||
|
|
||||||
|
{
|
||||||
|
key := make([]byte, chacha20.KEY_SIZE, context.temp_allocator)
|
||||||
|
iv := make([]byte, chacha20.IV_SIZE, context.temp_allocator)
|
||||||
|
crypto.rand_bytes(key)
|
||||||
|
crypto.rand_bytes(iv)
|
||||||
|
|
||||||
|
ctx: chacha20.Context
|
||||||
|
chacha20.init(&ctx, key, iv)
|
||||||
|
|
||||||
|
for sz, _ in SIZES {
|
||||||
|
options := &time.Benchmark_Options{
|
||||||
|
rounds = ITERS,
|
||||||
|
bytes = sz,
|
||||||
|
setup = setup_sized_buf,
|
||||||
|
bench = do_bench_chacha20,
|
||||||
|
teardown = teardown_sized_buf,
|
||||||
|
}
|
||||||
|
context.user_ptr = &ctx
|
||||||
|
|
||||||
|
err := time.benchmark(options, context.allocator)
|
||||||
|
testing.expect(t, err == nil)
|
||||||
|
|
||||||
|
time_per_iter := options.duration / ITERS
|
||||||
|
table.aligned_row_of_values(
|
||||||
|
&tbl,
|
||||||
|
.Right,
|
||||||
|
"chacha20",
|
||||||
|
table.format(&tbl, "%d", sz),
|
||||||
|
table.format(&tbl, "%8M", time_per_iter),
|
||||||
|
table.format(&tbl, "%5.3f MiB/s", options.megabytes_per_second),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_table(&tbl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_aes_ctr :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
ctx := (^aes.Context_CTR)(context.user_ptr)
|
||||||
|
|
||||||
|
buf := options.input
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
aes.xor_bytes_ctr(ctx, buf, buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
do_bench_chacha20 :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
ctx := (^chacha20.Context)(context.user_ptr)
|
||||||
|
|
||||||
|
buf := options.input
|
||||||
|
|
||||||
|
for _ in 0 ..= options.rounds {
|
||||||
|
chacha20.xor_bytes(ctx, buf, buf)
|
||||||
|
}
|
||||||
|
options.count = options.rounds
|
||||||
|
options.processed = options.rounds * options.bytes
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package benchmark_core_crypto
|
||||||
|
|
||||||
|
import "core:crypto"
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:log"
|
||||||
|
import "core:strings"
|
||||||
|
import "core:text/table"
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
log_table :: #force_inline proc(tbl: ^table.Table) {
|
||||||
|
sb := strings.builder_make()
|
||||||
|
defer strings.builder_destroy(&sb)
|
||||||
|
|
||||||
|
wr := strings.to_writer(&sb)
|
||||||
|
|
||||||
|
fmt.sbprintln(&sb)
|
||||||
|
table.write_plain_table(wr, tbl)
|
||||||
|
|
||||||
|
log.info(strings.to_string(sb))
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
setup_sized_buf :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
assert(options != nil)
|
||||||
|
|
||||||
|
options.input = make([]u8, options.bytes, allocator)
|
||||||
|
if len(options.input) > 0 {
|
||||||
|
crypto.rand_bytes(options.input)
|
||||||
|
}
|
||||||
|
return nil if len(options.input) == options.bytes else .Allocation_Error
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
teardown_sized_buf :: proc(
|
||||||
|
options: ^time.Benchmark_Options,
|
||||||
|
allocator := context.allocator,
|
||||||
|
) -> (
|
||||||
|
err: time.Benchmark_Error,
|
||||||
|
) {
|
||||||
|
assert(options != nil)
|
||||||
|
|
||||||
|
delete(options.input)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user