From 6ec1e62ca5b645681a94a829ba834f51c4da9e7f Mon Sep 17 00:00:00 2001 From: TheHertaEnjoyer247 Date: Fri, 28 Nov 2025 19:34:53 +0700 Subject: [PATCH 1/5] Merge 'dev1linux' to 'master' (#16) * Add SPHINCS+ implementation with testing framework and timing metrics * Fix bugs and warnings * Add hybrid running for Windows and Linux * Fix timing, output and makefile * Add message len output and adjust NTESTS to 1000 for default * Update minor things * Refactor test files * Add CHANGELOG.md and adjust README.md --- .vscode/c_cpp_properties.json | 24 +++ .vscode/settings.json | 3 + CHANGELOG.md | 30 ++++ README.md | 15 ++ ref/.gitignore | 2 + ref/Makefile | 47 ++++-- ref/PQCgenKAT_sign.exe | Bin 0 -> 183902 bytes ref/api.h | 22 +++ ref/cpu_used_test.sh | 23 +++ ref/randombytes_win.c | 20 +++ ref/sha2.c | 11 +- ref/sign.c | 109 ++++++++++-- ref/sign.c.old | 309 ++++++++++++++++++++++++++++++++++ ref/test/input.txt | 0 ref/test/test_sphincsplus.c | 93 ++++++++++ 15 files changed, 675 insertions(+), 33 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/settings.json create mode 100644 CHANGELOG.md create mode 100644 ref/PQCgenKAT_sign.exe create mode 100644 ref/cpu_used_test.sh create mode 100644 ref/randombytes_win.c create mode 100644 ref/sign.c.old create mode 100644 ref/test/input.txt create mode 100644 ref/test/test_sphincsplus.c diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..236a34ae --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,24 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "${workspaceFolder}/ref", + "${workspaceFolder}/ref/params" + + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE", + "PARAMS=sphincs-sha2-128f" // default value + ], + "compilerPath": "C:\\msys64\\ucrt64\\bin\\gcc.exe", + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "windows-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..06b08423 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.dimInactiveRegions": false +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..edbd7862 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.html). + +### Summary +This version introduces modifications to the `ref` implementation for performance analysis and benchmarking purposes. The core cryptographic logic of the original SPHINCS+ algorithm remains unchanged. All modifications are confined to the `ref` directory, supplementary testing scripts, and configuration files. + +### Added +- **Performance Benchmarking Framework:** + - Introduced a `timing_info_t` struct in `ref/api.h` to capture execution time for key generation, signing, and verification steps. + - Added `print_timing_info()` function prototype in `ref/api.h` to display aggregated timing results. + - Added `run_test` function prototype in `ref/api.h` to facilitate running tests multiple times for stable performance metrics. +- **Automated Testing Support:** + - Added `ref/test/input.txt` to provide a consistent sample input for testing and debugging. +- **VS Code Configuration Support:** + - Added `.vscode/c_cpp_properties.json` to enhance development experience with debugging, code suggestions, and to fix all warnings. + - Configured include paths for all implementations (`ref`, `haraka-aesni`, `shake-avx2`, `sha2-avx2`) and parameter files. + - Defined default `PARAMS` macro for easier switching between parameter sets in the editor (note: this macro is only for code suggestions and does not affect the actual `make` process). + +### Changed +- **Makefile Adjustments:** + - Updated `Makefile` in `ref` to support new benchmarking and testing options. + +### Removed +- No changes in this version. + +This project is a fork of the official [SPHINCS+](https://github.com/sphincs/sphincsplus) repository. The modifications, available at [quannguyen247/sphincsplus-dev](https://github.com/quannguyen247/sphincsplus-dev), are focused on performance analysis, benchmarking, and development tooling. The core cryptographic logic of the original public domain implementation of SPHINCS+ remains unchanged. \ No newline at end of file diff --git a/README.md b/README.md index 5948b7d0..df97ec8f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,18 @@ +# Custom SPHINCS+ Implementation for PQC Research & Benchmarking + +This repository is a fork of the official [SPHINCS+](https://github.com/sphincs/sphincsplus) implementation, customized by **quannguyen247** for the purpose of experimenting with, modifying, and benchmarking Post-Quantum Cryptography (PQC) algorithms. + +## Purpose +The primary goal of this fork is to provide a flexible framework for research and detailed performance analysis. Key objectives include: +- **Algorithmic Experimentation:** Facilitating modifications to core components such as hash functions and tree structures to study their impact on security and efficiency. +- **Comparative Analysis:** Enabling side-by-side performance comparisons of different implementation strategies and optimizations. +- **Performance Metrics:** Precise execution time measurement for key generation, signing, and verification. + +## Key Modifications +Significant changes have been made to the `ref` implementation to support these goals. For a detailed list of all modifications, please refer to the [CHANGELOG.md](CHANGELOG.md) file. + +--- + ## SPHINCS+ This repository contains the software that accompanies the [SPHINCS+ submission](https://sphincs.org/) to [NIST's Post-Quantum Cryptography](https://csrc.nist.gov/Projects/Post-Quantum-Cryptography) project. diff --git a/ref/.gitignore b/ref/.gitignore index 67bcef99..ab2061cf 100644 --- a/ref/.gitignore +++ b/ref/.gitignore @@ -3,3 +3,5 @@ test/* PQCsignKAT_*.rsp PQCsignKAT_*.req PQCgenKAT_sign +!test/input.txt +test/output.txt \ No newline at end of file diff --git a/ref/Makefile b/ref/Makefile index a3aabad2..dade112f 100644 --- a/ref/Makefile +++ b/ref/Makefile @@ -1,10 +1,23 @@ -PARAMS = sphincs-haraka-128f -THASH = robust - -CC=/usr/bin/gcc -CFLAGS=-Wall -Wextra -Wpedantic -O3 -std=c99 -Wconversion -Wmissing-prototypes -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) +PARAMS = sphincs-sha2-128f +THASH = simple + +CC = gcc +CFLAGS= -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \ + -Wshadow -Wpointer-arith -Wconversion -O3 -DPARAMS=$(PARAMS) $(EXTRA_CFLAGS) -z noexecstack +ifeq ($(THASH),robust) + CFLAGS += -DSPX_ROBUST=1 +endif +LDLIBS = -lcrypto + +# OS-specific adjustments for randombytes +ifeq ($(OS),Windows_NT) + RANDOMBYTES_SRC = randombytes_win.c + LDLIBS += -lbcrypt +else + RANDOMBYTES_SRC = randombytes.c +endif -SOURCES = address.c randombytes.c merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c +SOURCES = address.c $(RANDOMBYTES_SRC) merkle.c wots.c wotsx1.c utils.c utilsx1.c fors.c sign.c HEADERS = params.h address.h randombytes.h merkle.h wots.h wotsx1.h utils.h utilsx1.h fors.h api.h hash.h thash.h ifneq (,$(findstring shake,$(PARAMS))) @@ -20,7 +33,8 @@ ifneq (,$(findstring sha2,$(PARAMS))) HEADERS += sha2.h endif -DET_SOURCES = $(SOURCES:randombytes.%=rng.%) +# For deterministic KAT generation, replace randombytes with rng.c +DET_SOURCES = $(filter-out $(RANDOMBYTES_SRC),$(SOURCES)) rng.c DET_HEADERS = $(HEADERS:randombytes.%=rng.%) TESTS = test/fors \ @@ -30,6 +44,9 @@ BENCHMARK = test/benchmark .PHONY: clean test benchmark +test_sphincsplus: test/test_sphincsplus.c $(SOURCES) $(HEADERS) Makefile + $(CC) $(CFLAGS) -o test/$@ $(SOURCES) $< $(LDLIBS) + default: PQCgenKAT_sign all: PQCgenKAT_sign tests benchmarks @@ -42,17 +59,17 @@ benchmarks: $(BENCHMARK) benchmark: $(BENCHMARK:=.exec) -PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) +PQCgenKAT_sign: PQCgenKAT_sign.c $(DET_SOURCES) $(DET_HEADERS) Makefile $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< -lcrypto -test/benchmark: test/benchmark.c test/cycles.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ test/cycles.c $(SOURCES) $< $(LDLIBS) +test/benchmark: test/benchmark.c test/cycles.c $(DET_SOURCES) $(DET_HEADERS) Makefile + $(CC) $(CFLAGS) -o $@ test/cycles.c $(DET_SOURCES) $< $(LDLIBS) -test/%: test/%.c $(SOURCES) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(SOURCES) $< $(LDLIBS) +test/%: test/%.c $(DET_SOURCES) $(DET_HEADERS) Makefile + $(CC) $(CFLAGS) -o $@ $(DET_SOURCES) $< $(LDLIBS) -test/haraka: test/haraka.c $(filter-out haraka.c,$(SOURCES)) $(HEADERS) - $(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(SOURCES)) $< $(LDLIBS) +test/haraka: test/haraka.c $(filter-out haraka.c,$(DET_SOURCES)) $(DET_HEADERS) + $(CC) $(CFLAGS) -o $@ $(filter-out haraka.c,$(DET_SOURCES)) $< $(LDLIBS) test/%.exec: test/% @$< @@ -62,4 +79,4 @@ clean: -$(RM) $(BENCHMARK) -$(RM) PQCgenKAT_sign -$(RM) PQCsignKAT_*.rsp - -$(RM) PQCsignKAT_*.req + -$(RM) PQCsignKAT_*.req \ No newline at end of file diff --git a/ref/PQCgenKAT_sign.exe b/ref/PQCgenKAT_sign.exe new file mode 100644 index 0000000000000000000000000000000000000000..7e7812bf71fc602ba8f2caf15ab90a99d7b0119f GIT binary patch literal 183902 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

6rkGsO>1hw(10@TShJU>tPfPr&sjV5)z( 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 Ys6RWWbS`dv%-?mg#&PZS*;A+g4?pxpfB*mh literal 0 HcmV?d00001 diff --git a/ref/api.h b/ref/api.h index d57a148f..5801cac2 100644 --- a/ref/api.h +++ b/ref/api.h @@ -6,6 +6,10 @@ #include "params.h" +// define macros +#define str(s) #s +#define xstr(s) str(s) + #define CRYPTO_ALGNAME "SPHINCS+" #define CRYPTO_SECRETKEYBYTES SPX_SK_BYTES @@ -74,4 +78,22 @@ int crypto_sign_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk); +// Timing struct for benchmarking +typedef struct { + double keygen; + double sign; + double verify; + double all; + double temp; +} timing_info_t; + +// Expose global timing variable for test aggregation +extern timing_info_t g_time; + +// Print and return timing info +timing_info_t print_timing_info(void); + +// add prototypes +void run_test(const unsigned char *m, unsigned long long mlen, int test_idx); + #endif diff --git a/ref/cpu_used_test.sh b/ref/cpu_used_test.sh new file mode 100644 index 00000000..c59afa70 --- /dev/null +++ b/ref/cpu_used_test.sh @@ -0,0 +1,23 @@ +#!/bin/bash +#use chmod +x cpu_used_test.sh then ./cpu_used_test.sh + +total_cpu=0 +count=0 + +for i in {1..1000} +do + # Extract the numeric value (removes the % sign) + cpu=$( /usr/bin/time -v test_sphincsplus.exe 2>&1 | grep "Percent of CPU this job got" | grep -o ' [0-9]\+' ) + + if [[ -n "$cpu" ]]; then + total_cpu=$((total_cpu + cpu)) + count=$((count + 1)) + fi +done + +if [ "$count" -gt 0 ]; then + average_cpu=$(echo "scale=2; $total_cpu / $count" | bc) + echo "Average CPU percent used: $average_cpu" +else + echo "Could not extract any CPU percent values!" +fi \ No newline at end of file diff --git a/ref/randombytes_win.c b/ref/randombytes_win.c new file mode 100644 index 00000000..927e2172 --- /dev/null +++ b/ref/randombytes_win.c @@ -0,0 +1,20 @@ +/* + * This is the Windows-specific implementation of randombytes, using BCryptGenRandom. + */ + +#include +#include +#include /* For fprintf, stderr */ +#include /* For exit */ +#include "randombytes.h" + +//#pragma comment(lib, "bcrypt.lib") + +void randombytes(unsigned char *x, unsigned long long xlen) +{ + NTSTATUS status = BCryptGenRandom(NULL, x, (ULONG)xlen, BCRYPT_USE_SYSTEM_PREFERRED_RNG); + if (status != 0) { /* STATUS_SUCCESS is 0 */ + fprintf(stderr, "Fatal error: BCryptGenRandom failed.\n"); + exit(1); + } +} diff --git a/ref/sha2.c b/ref/sha2.c index ef730470..8f54af1d 100644 --- a/ref/sha2.c +++ b/ref/sha2.c @@ -286,7 +286,8 @@ static size_t crypto_hashblocks_sha256(uint8_t *statebytes, return inlen; } -static int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) +// fix from int to unsigned long long +static unsigned long long crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen) { uint64_t state[8]; uint64_t a; @@ -635,13 +636,13 @@ void mgf1_256(unsigned char *out, unsigned long outlen, /* While we can fit in at least another full block of SHA256 output.. */ for (i = 0; (i+1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); + u32_to_bytes(inbuf + inlen, (uint32_t)i); sha256(out, inbuf, inlen + 4); out += SPX_SHA256_OUTPUT_BYTES; } /* Until we cannot anymore, and we fill the remainder. */ if (outlen > i*SPX_SHA256_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); + u32_to_bytes(inbuf + inlen, (uint32_t)i); sha256(outbuf, inbuf, inlen + 4); memcpy(out, outbuf, outlen - i*SPX_SHA256_OUTPUT_BYTES); } @@ -661,13 +662,13 @@ void mgf1_512(unsigned char *out, unsigned long outlen, /* While we can fit in at least another full block of SHA512 output.. */ for (i = 0; (i+1)*SPX_SHA512_OUTPUT_BYTES <= outlen; i++) { - u32_to_bytes(inbuf + inlen, i); + u32_to_bytes(inbuf + inlen, (uint32_t)i); sha512(out, inbuf, inlen + 4); out += SPX_SHA512_OUTPUT_BYTES; } /* Until we cannot anymore, and we fill the remainder. */ if (outlen > i*SPX_SHA512_OUTPUT_BYTES) { - u32_to_bytes(inbuf + inlen, i); + u32_to_bytes(inbuf + inlen, (uint32_t)i); sha512(outbuf, inbuf, inlen + 4); memcpy(out, outbuf, outlen - i*SPX_SHA512_OUTPUT_BYTES); } diff --git a/ref/sign.c b/ref/sign.c index a8e0c3c3..668ca50b 100644 --- a/ref/sign.c +++ b/ref/sign.c @@ -1,7 +1,9 @@ +#define _POSIX_C_SOURCE 199309L // POSIX compliance +#include #include #include #include - +#include #include "api.h" #include "params.h" #include "wots.h" @@ -13,6 +15,9 @@ #include "utils.h" #include "merkle.h" +// global timing struct now defined in api.h +timing_info_t g_time = {0}; + /* * Returns the length of a secret key, in bytes */ @@ -55,7 +60,7 @@ int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, { spx_ctx ctx; - /* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */ + //printf("[STEP 2] Initialize SK_SEED, SK_PRF and PUB_SEED from seed.\n"); memcpy(sk, seed, CRYPTO_SEEDBYTES); memcpy(pk, sk + 2*SPX_N, SPX_N); @@ -67,9 +72,10 @@ int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, preparation or computation it needs, based on the public seed. */ initialize_hash_function(&ctx); - /* Compute root node of the top-most subtree. */ + //printf("[STEP 3] Compute root node of the top-most subtree 'pub_root'.\n"); merkle_gen_root(sk + 3*SPX_N, &ctx); + //printf("[STEP 4] Assemble the secret key and public key according to the required format.\n"); memcpy(pk + SPX_N, sk + 3*SPX_N, SPX_N); return 0; @@ -82,11 +88,22 @@ int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, */ int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { - unsigned char seed[CRYPTO_SEEDBYTES]; - randombytes(seed, CRYPTO_SEEDBYTES); - crypto_sign_seed_keypair(pk, sk, seed); + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + + //printf("\n=========== KEY GENERATION STAGE ===========\n\n"); + //printf("[STEP 1] Generate random seed with randombytes\n"); + unsigned char seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + //printf("[DONE] Key generation completed successfully.\n"); - return 0; + clock_gettime(CLOCK_MONOTONIC, &end); + double t = (double)(end.tv_sec - start.tv_sec) + ((double)(end.tv_nsec - start.tv_nsec)) / 1e9; + g_time.keygen += t; + g_time.all += t; + + return 0; } /** @@ -95,6 +112,9 @@ int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) int crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk) { + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + spx_ctx ctx; const unsigned char *sk_prf = sk + SPX_N; @@ -122,21 +142,24 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, /* Optionally, signing can be made non-deterministic using optrand. This can help counter side-channel attacks that would benefit from getting a large number of traces when the signer uses the same nodes. */ + //printf("\n============== SIGNING STAGE ==============\n\n"); + //printf("[STEP 1] Generate random value R for message digest randomization.\n"); randombytes(optrand, SPX_N); - /* Compute the digest randomization value. */ + //printf("[STEP 2] Compute the digest randomization value.\n"); gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); - /* Derive the message digest and leaf index from R, PK and M. */ + //printf("[STEP 2] Derive the message digest and leaf index from R, PK and M.\n"); hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); sig += SPX_N; set_tree_addr(wots_addr, tree); set_keypair_addr(wots_addr, idx_leaf); - /* Sign the message hash using FORS. */ + //printf("[STEP 3] Sign the message hash using FORS.\n"); fors_sign(sig, root, mhash, &ctx, wots_addr); sig += SPX_FORS_BYTES; + //printf("[STEP 4] Initialize a for loop to sign the message hash across all layers of the Merkle tree.\n"); for (i = 0; i < SPX_D; i++) { set_layer_addr(tree_addr, i); set_tree_addr(tree_addr, tree); @@ -154,6 +177,10 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, *siglen = SPX_BYTES; + clock_gettime(CLOCK_MONOTONIC, &end); + double t = (double)(end.tv_sec - start.tv_sec) + ((double)(end.tv_nsec - start.tv_nsec)) / 1e9; + g_time.sign += t; + return 0; } @@ -163,6 +190,9 @@ int crypto_sign_signature(uint8_t *sig, size_t *siglen, int crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk) { + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + spx_ctx ctx; const unsigned char *pub_root = pk + SPX_N; unsigned char mhash[SPX_FORS_MSG_BYTES]; @@ -190,7 +220,7 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - /* Derive the message digest and leaf index from R || PK || M. */ + //printf("[STEP 1] Derive the message digest and leaf index from R || PK || M.\n"); /* The additional SPX_N is a result of the hash domain separator. */ hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); sig += SPX_N; @@ -199,10 +229,12 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, set_tree_addr(wots_addr, tree); set_keypair_addr(wots_addr, idx_leaf); + //printf("[STEP 2] Compute the FORS public key from the signature and message hash to verify.\n"); fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); sig += SPX_FORS_BYTES; /* For each subtree.. */ + //printf("[STEP 3] Initialize a for loop starting from the bottom layer up to the top layer of hypertree, for each Merkle subtree.\n"); for (i = 0; i < SPX_D; i++) { set_layer_addr(tree_addr, i); set_tree_addr(tree_addr, tree); @@ -231,8 +263,23 @@ int crypto_sign_verify(const uint8_t *sig, size_t siglen, tree = tree >> SPX_TREE_HEIGHT; } + + /* Print first 8 bytes of root and pub_root for debugging/visualization */ + /* printf("[Step 4] new_root (first 8 bytes): "); // recomputed root from signature + for (int i = 0; i < 8; i++) printf("%02X%s", root[i], i < 7 ? " " : ""); + printf(" ...\n"); + printf("[Step 4] pub_root (first 8 bytes): "); + for (int i = 0; i < 8; i++) printf("%02X%s", pub_root[i], i < 7 ? " " : ""); + printf(" ...\n"); */ + /* Check if the root node equals the root node in the public key. */ - if (memcmp(root, pub_root, SPX_N)) { + //printf("[STEP 4] Check if the root node equals the root node in the public key.\n"); + + clock_gettime(CLOCK_MONOTONIC, &end); + double t = (double)(end.tv_sec - start.tv_sec) + ((double)(end.tv_nsec - start.tv_nsec)) / 1e9; + g_time.verify += t; + + if (memcmp(root, pub_root, SPX_N)) { // timing ends before memcmp because memcmp is negligible return -1; } @@ -247,12 +294,21 @@ int crypto_sign(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk) { + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + size_t siglen; crypto_sign_signature(sm, &siglen, m, (size_t)mlen, sk); + //printf("[STEP 5] Append the message M to the signature to form the final output.\n"); memmove(sm + SPX_BYTES, m, mlen); *smlen = siglen + mlen; + //printf("[DONE] Signature generated successfully.\n"); + + clock_gettime(CLOCK_MONOTONIC, &end); + double t = (double)(end.tv_sec - start.tv_sec) + ((double)(end.tv_nsec - start.tv_nsec)) / 1e9; + g_time.all += t; return 0; } @@ -264,24 +320,51 @@ int crypto_sign_open(unsigned char *m, unsigned long long *mlen, const unsigned char *sm, unsigned long long smlen, const unsigned char *pk) { + //printf("\n============= VERIFYING STAGE =============\n\n"); /* The API caller does not necessarily know what size a signature should be but SPHINCS+ signatures are always exactly SPX_BYTES. */ + //printf("[Auxiliary] Check signature length\n"); if (smlen < SPX_BYTES) { memset(m, 0, smlen); *mlen = 0; return -1; } - *mlen = smlen - SPX_BYTES; + struct timespec start, end; + clock_gettime(CLOCK_MONOTONIC, &start); + *mlen = smlen - SPX_BYTES; if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, (size_t)*mlen, pk)) { memset(m, 0, smlen); *mlen = 0; + //printf("[DONE] Signature verification failed!\n"); + + clock_gettime(CLOCK_MONOTONIC, &end); + double t = (double)(end.tv_sec - start.tv_sec) + ((double)(end.tv_nsec - start.tv_nsec)) / 1e9; + g_time.all += t; + return -1; } /* If verification was successful, move the message to the right place. */ + //printf("[DONE] Signature verification successful!\n"); memmove(m, sm + SPX_BYTES, *mlen); + clock_gettime(CLOCK_MONOTONIC, &end); + double t = (double)(end.tv_sec - start.tv_sec) + ((double)(end.tv_nsec - start.tv_nsec)) / 1e9; + g_time.all += t; + return 0; } + +// For testing: print timing information and return timing struct +timing_info_t print_timing_info(void) +{ + g_time.temp = g_time.keygen + g_time.sign + g_time.verify; + /* printf("Total KeyGen time: %.6f seconds (%.2f ms)\n", g_time.keygen, g_time.keygen * 1000); + printf("Total Signing time: %.6f seconds (%.2f ms)\n", g_time.sign, g_time.sign * 1000); + printf("Total Verification time: %.6f seconds (%.2f ms)\n", g_time.verify, g_time.verify * 1000); + printf("Total time (not include packing and unpacking): %.6f seconds (%.2f ms)\n", g_time.temp, g_time.temp * 1000); + printf("Total time (NIST compliance): %.6f seconds (%.2f ms)\n", g_time.all, g_time.all * 1000); */ + return g_time; +} \ No newline at end of file diff --git a/ref/sign.c.old b/ref/sign.c.old new file mode 100644 index 00000000..ae23410e --- /dev/null +++ b/ref/sign.c.old @@ -0,0 +1,309 @@ +#include +#include +#include +#include +#include "api.h" +#include "params.h" +#include "wots.h" +#include "fors.h" +#include "hash.h" +#include "thash.h" +#include "address.h" +#include "randombytes.h" +#include "utils.h" +#include "merkle.h" + +/* + * Returns the length of a secret key, in bytes + */ +unsigned long long crypto_sign_secretkeybytes(void) +{ + return CRYPTO_SECRETKEYBYTES; +} + +/* + * Returns the length of a public key, in bytes + */ +unsigned long long crypto_sign_publickeybytes(void) +{ + return CRYPTO_PUBLICKEYBYTES; +} + +/* + * Returns the length of a signature, in bytes + */ +unsigned long long crypto_sign_bytes(void) +{ + return CRYPTO_BYTES; +} + +/* + * Returns the length of the seed required to generate a key pair, in bytes + */ +unsigned long long crypto_sign_seedbytes(void) +{ + return CRYPTO_SEEDBYTES; +} + +/* + * Generates an SPX key pair given a seed of length + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, + const unsigned char *seed) +{ + spx_ctx ctx; + + printf("[STEP 2] Initialize SK_SEED, SK_PRF and PUB_SEED from seed.\n"); + memcpy(sk, seed, CRYPTO_SEEDBYTES); + + memcpy(pk, sk + 2*SPX_N, SPX_N); + + memcpy(ctx.pub_seed, pk, SPX_N); + memcpy(ctx.sk_seed, sk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + printf("[STEP 3] Compute root node of the top-most subtree 'pub_root'.\n"); + merkle_gen_root(sk + 3*SPX_N, &ctx); + + printf("[STEP 4] Assemble the secret key and public key according to the required format.\n"); + memcpy(pk + SPX_N, sk + 3*SPX_N, SPX_N); + + return 0; +} + +/* + * Generates an SPX key pair. + * Format sk: [SK_SEED || SK_PRF || PUB_SEED || root] + * Format pk: [PUB_SEED || root] + */ +int crypto_sign_keypair(unsigned char *pk, unsigned char *sk) +{ + printf("\n=========== KEY GENERATION STAGE ===========\n\n"); + printf("[STEP 1] Generate random seed with randombytes\n"); + unsigned char seed[CRYPTO_SEEDBYTES]; + randombytes(seed, CRYPTO_SEEDBYTES); + crypto_sign_seed_keypair(pk, sk, seed); + printf("[DONE] Key generation completed successfully.\n"); + return 0; +} + +/** + * Returns an array containing a detached signature. + */ +int crypto_sign_signature(uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) +{ + spx_ctx ctx; + + const unsigned char *sk_prf = sk + SPX_N; + const unsigned char *pk = sk + 2*SPX_N; + + unsigned char optrand[SPX_N]; + unsigned char mhash[SPX_FORS_MSG_BYTES]; + unsigned char root[SPX_N]; + uint32_t i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + + memcpy(ctx.sk_seed, sk, SPX_N); + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + + /* Optionally, signing can be made non-deterministic using optrand. + This can help counter side-channel attacks that would benefit from + getting a large number of traces when the signer uses the same nodes. */ + printf("\n============== SIGNING STAGE ==============\n\n"); + printf("[STEP 1] Generate random value R for message digest randomization.\n"); + randombytes(optrand, SPX_N); + printf("[STEP 2] Compute the digest randomization value.\n"); + gen_message_random(sig, sk_prf, optrand, m, mlen, &ctx); + + printf("[STEP 2] Derive the message digest and leaf index from R, PK and M.\n"); + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + printf("[STEP 3] Sign the message hash using FORS.\n"); + fors_sign(sig, root, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + printf("[STEP 4] Initialize a for loop to sign the message hash across all layers of the Merkle tree.\n"); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + merkle_sign(sig, root, &ctx, wots_addr, tree_addr, idx_leaf); + sig += SPX_WOTS_BYTES + SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT)-1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + *siglen = SPX_BYTES; + + return 0; +} + +/** + * Verifies a detached signature and message under a given public key. + */ +int crypto_sign_verify(const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) +{ + spx_ctx ctx; + const unsigned char *pub_root = pk + SPX_N; + unsigned char mhash[SPX_FORS_MSG_BYTES]; + unsigned char wots_pk[SPX_WOTS_BYTES]; + unsigned char root[SPX_N]; + unsigned char leaf[SPX_N]; + unsigned int i; + uint64_t tree; + uint32_t idx_leaf; + uint32_t wots_addr[8] = {0}; + uint32_t tree_addr[8] = {0}; + uint32_t wots_pk_addr[8] = {0}; + + if (siglen != SPX_BYTES) { + return -1; + } + + memcpy(ctx.pub_seed, pk, SPX_N); + + /* This hook allows the hash function instantiation to do whatever + preparation or computation it needs, based on the public seed. */ + initialize_hash_function(&ctx); + + set_type(wots_addr, SPX_ADDR_TYPE_WOTS); + set_type(tree_addr, SPX_ADDR_TYPE_HASHTREE); + set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); + + printf("[STEP 1] Derive the message digest and leaf index from R || PK || M.\n"); + /* The additional SPX_N is a result of the hash domain separator. */ + hash_message(mhash, &tree, &idx_leaf, sig, pk, m, mlen, &ctx); + sig += SPX_N; + + /* Layer correctly defaults to 0, so no need to set_layer_addr */ + set_tree_addr(wots_addr, tree); + set_keypair_addr(wots_addr, idx_leaf); + + printf("[STEP 2] Compute the FORS public key from the signature and message hash to verify.\n"); + fors_pk_from_sig(root, sig, mhash, &ctx, wots_addr); + sig += SPX_FORS_BYTES; + + /* For each subtree.. */ + printf("[STEP 3] Initialize a for loop starting from the bottom layer up to the top layer of hypertree, for each Merkle subtree.\n"); + for (i = 0; i < SPX_D; i++) { + set_layer_addr(tree_addr, i); + set_tree_addr(tree_addr, tree); + + copy_subtree_addr(wots_addr, tree_addr); + set_keypair_addr(wots_addr, idx_leaf); + + copy_keypair_addr(wots_pk_addr, wots_addr); + + /* The WOTS public key is only correct if the signature was correct. */ + /* Initially, root is the FORS pk, but on subsequent iterations it is + the root of the subtree below the currently processed subtree. */ + wots_pk_from_sig(wots_pk, sig, root, &ctx, wots_addr); + sig += SPX_WOTS_BYTES; + + /* Compute the leaf node using the WOTS public key. */ + thash(leaf, wots_pk, SPX_WOTS_LEN, &ctx, wots_pk_addr); + + /* Compute the root node of this subtree. */ + compute_root(root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT, + &ctx, tree_addr); + sig += SPX_TREE_HEIGHT * SPX_N; + + /* Update the indices for the next layer. */ + idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT)-1)); + tree = tree >> SPX_TREE_HEIGHT; + } + + + /* Print first 8 bytes of root and pub_root for debugging/visualization */ + printf("[Step 4] new_root (first 8 bytes): "); // recomputed root from signature + for (int i = 0; i < 8; i++) printf("%02X%s", root[i], i < 7 ? " " : ""); + printf(" ...\n"); + printf("[Step 4] pub_root (first 8 bytes): "); + for (int i = 0; i < 8; i++) printf("%02X%s", pub_root[i], i < 7 ? " " : ""); + printf(" ...\n"); + + /* Check if the root node equals the root node in the public key. */ + printf("[STEP 4] Check if the root node equals the root node in the public key.\n"); + if (memcmp(root, pub_root, SPX_N)) { + return -1; + } + + return 0; +} + + +/** + * Returns an array containing the signature followed by the message. + */ +int crypto_sign(unsigned char *sm, unsigned long long *smlen, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk) +{ + size_t siglen; + + crypto_sign_signature(sm, &siglen, m, (size_t)mlen, sk); + + printf("[STEP 5] Append the message M to the signature to form the final output.\n"); + memmove(sm + SPX_BYTES, m, mlen); + *smlen = siglen + mlen; + printf("[DONE] Signature generated successfully.\n"); + return 0; +} + +/** + * Verifies a given signature-message pair under a given public key. + */ +int crypto_sign_open(unsigned char *m, unsigned long long *mlen, + const unsigned char *sm, unsigned long long smlen, + const unsigned char *pk) +{ + printf("\n============= VERIFYING STAGE =============\n\n"); + /* The API caller does not necessarily know what size a signature should be + but SPHINCS+ signatures are always exactly SPX_BYTES. */ + printf("[Auxiliary] Check signature length\n"); + if (smlen < SPX_BYTES) { + memset(m, 0, smlen); + *mlen = 0; + return -1; + } + + *mlen = smlen - SPX_BYTES; + if (crypto_sign_verify(sm, SPX_BYTES, sm + SPX_BYTES, (size_t)*mlen, pk)) { + memset(m, 0, smlen); + *mlen = 0; + printf("[DONE] Signature verification failed!\n"); + return -1; + } + + /* If verification was successful, move the message to the right place. */ + printf("[DONE] Signature verification successful!\n"); + memmove(m, sm + SPX_BYTES, *mlen); + + return 0; +} diff --git a/ref/test/input.txt b/ref/test/input.txt new file mode 100644 index 00000000..e69de29b diff --git a/ref/test/test_sphincsplus.c b/ref/test/test_sphincsplus.c new file mode 100644 index 00000000..12429693 --- /dev/null +++ b/ref/test/test_sphincsplus.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include "../api.h" +#include "../randombytes.h" + +#define MLEN 1200 // limit input for testing +#define NTESTS 1 // test count + +void run_test(const unsigned char *m, unsigned long long mlen, int test_idx) +{ + // KeyGen + unsigned char pk[CRYPTO_PUBLICKEYBYTES]; + unsigned char sk[CRYPTO_SECRETKEYBYTES]; + crypto_sign_keypair(pk, sk); + + /* fprintf(fout, "Test #%d\n", test_idx+1); + fprintf(fout, "KeyGen Stage:\n- Input: None\n- Output:\n"); + + fprintf(fout, "* Public Key: "); + for (int i = 0; i < CRYPTO_PUBLICKEYBYTES; i++) fprintf(fout, "%02x", pk[i]); + fprintf(fout, "\n* Secret Key: "); + for (int i = 0; i < CRYPTO_SECRETKEYBYTES; i++) fprintf(fout, "%02x", sk[i]); + fprintf(fout, "\n\n"); */ + + // Signing + unsigned char sm[MLEN + CRYPTO_BYTES]; + unsigned long long smlen = 0; + crypto_sign(sm, &smlen, m, mlen, sk); + + /* fprintf(fout, "Signing Stage:\n- Input: input.txt, sk\n- Output:\n"); + + fprintf(fout, "* Signed Message: "); + for (unsigned long long i = 0; i < smlen; i++) fprintf(fout, "%02x", sm[i]); + fprintf(fout, "\n\n"); */ + + // Open/Verify + unsigned char m2[MLEN + CRYPTO_BYTES] = {0}; + unsigned long long m2len = 0; + int valid = crypto_sign_open(m2, &m2len, sm, smlen, pk); + /* fprintf(fout, "Verifying Stage:\n- Input: signed message, pk\n- Output: %s\n", valid == 0 ? "Valid" : "Invalid"); + if (!valid) { + fprintf(fout, "* Opened Message: "); + for (unsigned long long i = 0; i < m2len; i++) fprintf(fout, "%02x", m2[i]); + fprintf(fout, "\n"); + } + fprintf(fout, "\n"); */ + (void)valid; + (void)test_idx; +} + +int main(void) +{ + FILE *fin = fopen("test/input.txt", "rb"); + //FILE *fout = fopen("output.txt", "w"); + if (!fin /*|| !fout*/) { + printf("File error\n"); + return 1; + } + + // Read message from input.txt only once + unsigned char m[MLEN + CRYPTO_BYTES] = {0}; + unsigned long long mlen = fread(m, 1, MLEN, fin); + fclose(fin); + + for (int test = 0; test < NTESTS; ++test) { + run_test(m, mlen, test); + } + //fclose(fout); + + // Print testing information + printf("\n[Testing Information - %d runs]\n\n", NTESTS); + timing_info_t t = print_timing_info(); + printf("Average KeyGen time: %.6fs (%.2f ms)\n", t.keygen / NTESTS, (t.keygen / NTESTS) * 1000); + printf("Average Signing time: %.6fs (%.2f ms)\n", t.sign / NTESTS, (t.sign / NTESTS) * 1000); + printf("Average Verification time: %.6fs (%.2f ms)\n", t.verify / NTESTS, (t.verify / NTESTS) * 1000); + //printf("Average sum time (3 stages): %.6fs (%.2f ms)\n", t.temp / NTESTS, (t.temp / NTESTS) * 1000); + printf("Average all time (NIST compliance): %.6fs (%.2f ms)\n", t.all / NTESTS, (t.all / NTESTS) * 1000); + printf("Public key bytes = %d\n", CRYPTO_PUBLICKEYBYTES); + printf("Secret key bytes = %d\n", CRYPTO_SECRETKEYBYTES); + printf("Signature bytes = %d\n", CRYPTO_BYTES); + printf("Message bytes = %llu\n", mlen); + + const char* thash_str; +#ifdef SPX_ROBUST + thash_str = "robust"; +#else + thash_str = "simple"; +#endif + printf("Parameters = %s-%s\n", xstr(PARAMS), thash_str); + + return 0; +} \ No newline at end of file From 33dd320a1ea62434b020af558e1158921fa1a5a6 Mon Sep 17 00:00:00 2001 From: quanne200679 Date: Sat, 9 May 2026 11:17:38 +0700 Subject: [PATCH 2/5] Add files via upload --- ref/test/Makefile | 112 +++++++ ref/test/cpucycles.c | 17 ++ ref/test/cpucycles.h | 33 +++ ref/test/speed_print.c | 51 ++++ ref/test/speed_print.h | 9 + ref/test/test_speed.c | 93 ++++++ ref/test/test_sphincsplus_client.c | 233 +++++++++++++++ ref/test/test_sphincsplus_keygen.c | 54 ++++ ref/test/test_sphincsplus_server.c | 462 +++++++++++++++++++++++++++++ ref/test/test_sphincsplus_stress.c | 346 +++++++++++++++++++++ ref/test/test_vectors.c | 67 +++++ 11 files changed, 1477 insertions(+) create mode 100644 ref/test/Makefile create mode 100644 ref/test/cpucycles.c create mode 100644 ref/test/cpucycles.h create mode 100644 ref/test/speed_print.c create mode 100644 ref/test/speed_print.h create mode 100644 ref/test/test_speed.c create mode 100644 ref/test/test_sphincsplus_client.c create mode 100644 ref/test/test_sphincsplus_keygen.c create mode 100644 ref/test/test_sphincsplus_server.c create mode 100644 ref/test/test_sphincsplus_stress.c create mode 100644 ref/test/test_vectors.c diff --git a/ref/test/Makefile b/ref/test/Makefile new file mode 100644 index 00000000..6fb5426c --- /dev/null +++ b/ref/test/Makefile @@ -0,0 +1,112 @@ +CC ?= gcc +CFLAGS ?= -Wall -Wextra -Wpedantic -Wmissing-prototypes -Wredundant-decls \ + -Wshadow -Wpointer-arith -O3 -fomit-frame-pointer + +ROOT := .. + +# SPHINCS+ parameters - adjust as needed +PARAMS ?= sphincs-sha2-128f +THASH ?= simple + +# OS-specific adjustments for randombytes +ifeq ($(OS),Windows_NT) + RANDOMBYTES_SRC = $(ROOT)/randombytes_win.c + LDLIBS += -lbcrypt +else + RANDOMBYTES_SRC = $(ROOT)/randombytes.c +endif + +SOURCES = $(ROOT)/address.c $(RANDOMBYTES_SRC) $(ROOT)/merkle.c $(ROOT)/wots.c $(ROOT)/wotsx1.c $(ROOT)/utils.c $(ROOT)/utilsx1.c $(ROOT)/fors.c $(ROOT)/sign.c +HEADERS = $(ROOT)/params.h $(ROOT)/address.h $(ROOT)/randombytes.h $(ROOT)/merkle.h $(ROOT)/wots.h $(ROOT)/wotsx1.h $(ROOT)/utils.h $(ROOT)/utilsx1.h $(ROOT)/fors.h $(ROOT)/api.h $(ROOT)/hash.h $(ROOT)/thash.h + +ifneq (,$(findstring shake,$(PARAMS))) + SOURCES += $(ROOT)/fips202.c $(ROOT)/hash_shake.c $(ROOT)/thash_shake_$(THASH).c + HEADERS += $(ROOT)/fips202.h +endif +ifneq (,$(findstring haraka,$(PARAMS))) + SOURCES += $(ROOT)/haraka.c $(ROOT)/hash_haraka.c $(ROOT)/thash_haraka_$(THASH).c + HEADERS += $(ROOT)/haraka.h +endif +ifneq (,$(findstring sha2,$(PARAMS))) + SOURCES += $(ROOT)/sha2.c $(ROOT)/hash_sha2.c $(ROOT)/thash_sha2_$(THASH).c + HEADERS += $(ROOT)/sha2.h +endif + +.PHONY: all run-server run-client stress keygen clean + +TARGET_IP ?= 192.168.4.85 +CONCURRENT_SESSIONS ?= 10 +BATCHES ?= 0 +BATCH_DELAY_SEC ?= 0 + +CLIENT_BIN := test_sphincsplus_client +SERVER_BIN := test_sphincsplus_server +STRESS_BIN := test_sphincsplus_stress +KEYGEN_BIN := test_sphincsplus_keygen +TEST_BIN := test_sphincsplus +SPEED_BIN := test_speed +VECTORS_BIN := test_vectors + +all: \ + test_sphincsplus_client \ + test_sphincsplus_server \ + test_sphincsplus_stress \ + test_sphincsplus_keygen \ + test_sphincsplus \ + test_speed \ + test_vectors + +test_sphincsplus_client: test_sphincsplus_client.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +test_sphincsplus_server: test_sphincsplus_server.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +test_sphincsplus_stress: test_sphincsplus_stress.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +test_sphincsplus_keygen: test_sphincsplus_keygen.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +test_sphincsplus: test_sphincsplus.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +test_speed: test_speed.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +test_vectors: test_vectors.c $(SOURCES) $(HEADERS) + $(CC) $(CFLAGS) -DPARAMS=$(PARAMS) -DSPX_ROBUST=0 \ + -o $@ $< $(SOURCES) $(LDLIBS) + +run-server: $(SERVER_BIN) + @echo "[RUN] Server on port 5000" + @./$(SERVER_BIN) + +run-client: $(CLIENT_BIN) + @echo "[RUN] Client -> $(TARGET_IP)" + @./$(CLIENT_BIN) $(TARGET_IP) + +stress: $(STRESS_BIN) + @echo "[STRESS] TARGET_IP=$(TARGET_IP) CONCURRENT=$(CONCURRENT_SESSIONS)" + @TARGET_IP=$(TARGET_IP) CONCURRENT_SESSIONS=$(CONCURRENT_SESSIONS) \ + BATCHES=$(BATCHES) BATCH_DELAY_SEC=$(BATCH_DELAY_SEC) \ + ./$(STRESS_BIN) + +keygen: $(KEYGEN_BIN) + @echo "[KEYGEN]" + @./$(KEYGEN_BIN) + +clean: + rm -f test_sphincsplus_client + rm -f test_sphincsplus_server + rm -f test_sphincsplus_stress + rm -f test_sphincsplus_keygen + rm -f test_sphincsplus + rm -f test_speed + rm -f test_vectors \ No newline at end of file diff --git a/ref/test/cpucycles.c b/ref/test/cpucycles.c new file mode 100644 index 00000000..c43923f1 --- /dev/null +++ b/ref/test/cpucycles.c @@ -0,0 +1,17 @@ +#include +#include "cpucycles.h" + +uint64_t cpucycles_overhead(void) { + uint64_t t0, t1, overhead = -1LL; + unsigned int i; + + for(i=0;i<100000;i++) { + t0 = cpucycles(); + __asm__ volatile(""); + t1 = cpucycles(); + if(t1 - t0 < overhead) + overhead = t1 - t0; + } + + return overhead; +} \ No newline at end of file diff --git a/ref/test/cpucycles.h b/ref/test/cpucycles.h new file mode 100644 index 00000000..9bc58b9e --- /dev/null +++ b/ref/test/cpucycles.h @@ -0,0 +1,33 @@ +#ifndef CPUCYCLES_H +#define CPUCYCLES_H + +#include + +#ifdef USE_RDPMC /* Needs echo 2 > /sys/devices/cpu/rdpmc */ + +static inline uint64_t cpucycles(void) { + const uint32_t ecx = (1U << 30) + 1; + uint64_t result; + + __asm__ volatile ("rdpmc; shlq $32,%%rdx; orq %%rdx,%%rax" + : "=a" (result) : "c" (ecx) : "rdx"); + + return result; +} + +#else + +static inline uint64_t cpucycles(void) { + uint64_t result; + + __asm__ volatile ("rdtsc; shlq $32,%%rdx; orq %%rdx,%%rax" + : "=a" (result) : : "%rdx"); + + return result; +} + +#endif + +uint64_t cpucycles_overhead(void); + +#endif \ No newline at end of file diff --git a/ref/test/speed_print.c b/ref/test/speed_print.c new file mode 100644 index 00000000..c0058f19 --- /dev/null +++ b/ref/test/speed_print.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include "cpucycles.h" +#include "speed_print.h" + +static int cmp_uint64(const void *a, const void *b) { + if(*(uint64_t *)a < *(uint64_t *)b) return -1; + if(*(uint64_t *)a > *(uint64_t *)b) return 1; + return 0; +} + +static uint64_t median(uint64_t *l, size_t llen) { + qsort(l,llen,sizeof(uint64_t),cmp_uint64); + + if(llen%2) return l[llen/2]; + else return (l[llen/2-1]+l[llen/2])/2; +} + +static uint64_t average(uint64_t *t, size_t tlen) { + size_t i; + uint64_t acc=0; + + for(i=0;i +#include + +void print_results(const char *s, uint64_t *t, size_t tlen); + +#endif \ No newline at end of file diff --git a/ref/test/test_speed.c b/ref/test/test_speed.c new file mode 100644 index 00000000..5a23e0b6 --- /dev/null +++ b/ref/test/test_speed.c @@ -0,0 +1,93 @@ +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#endif +#include "../api.h" + +#define NTESTS 100 + +static uint64_t get_time_ns(void) { +#ifdef _WIN32 + static LARGE_INTEGER freq = {0}; + LARGE_INTEGER counter; + + if (freq.QuadPart == 0) { + QueryPerformanceFrequency(&freq); + } + QueryPerformanceCounter(&counter); + return (uint64_t)(counter.QuadPart * 1000000000ULL / freq.QuadPart); +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)ts.tv_sec * 1000000000ULL + (uint64_t)ts.tv_nsec; +#endif +} + +static void print_results(const char *label, uint64_t *t, int ntests) { + uint64_t min = UINT64_MAX; + uint64_t max = 0; + uint64_t sum = 0; + + for (int i = 0; i < ntests; i++) { + if (t[i] < min) min = t[i]; + if (t[i] > max) max = t[i]; + sum += t[i]; + } + + double avg = (double)sum / ntests; + printf("%s\n", label); + printf(" Min: %llu ns\n", (unsigned long long)min); + printf(" Max: %llu ns\n", (unsigned long long)max); + printf(" Avg: %.2f ns\n", avg); + printf(" Cycles per second: %.2f\n", 1000000000.0 / avg); + printf("\n"); +} + +int main(void) { + uint64_t t[NTESTS]; + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t m[32] = {0}; // small message for speed test + unsigned long long siglen; + + printf("SPHINCS+ Speed Test\n"); + printf("Public Key bytes = %d\n", CRYPTO_PUBLICKEYBYTES); + printf("Secret Key bytes = %d\n", CRYPTO_SECRETKEYBYTES); + printf("Signature bytes = %d\n", CRYPTO_BYTES); + printf("Running %d tests...\n\n", NTESTS); + + // Key generation + for (int i = 0; i < NTESTS; i++) { + uint64_t start = get_time_ns(); + crypto_sign_keypair(pk, sk); + uint64_t end = get_time_ns(); + t[i] = end - start; + } + print_results("Key Generation:", t, NTESTS); + + // Signing + for (int i = 0; i < NTESTS; i++) { + uint64_t start = get_time_ns(); + crypto_sign_signature(sig, &siglen, m, sizeof(m), sk); + uint64_t end = get_time_ns(); + t[i] = end - start; + } + print_results("Signing:", t, NTESTS); + + // Verification + for (int i = 0; i < NTESTS; i++) { + uint64_t start = get_time_ns(); + int valid = crypto_sign_verify(sig, siglen, m, sizeof(m), pk); + uint64_t end = get_time_ns(); + t[i] = end - start; + (void)valid; // ignore result for speed test + } + print_results("Verification:", t, NTESTS); + + return 0; +} \ No newline at end of file diff --git a/ref/test/test_sphincsplus_client.c b/ref/test/test_sphincsplus_client.c new file mode 100644 index 00000000..2e41551a --- /dev/null +++ b/ref/test/test_sphincsplus_client.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../api.h" + +#define SERVER_PORT 5000 +#define BUFFER_SIZE 8192 +#define DEFAULT_TARGET_IP "192.168.4.85" +#define CLIENT_SK_PATH "client_sk.bin" +#define CLIENT_LOG_PATH "client.log" + +static uint64_t get_time_ms(void) { + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + return 0; + } + return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +} + +static int load_file_exact(const char *path, uint8_t *buf, size_t len) { + FILE *f = fopen(path, "rb"); + if (!f) { + return -1; + } + + size_t n = fread(buf, 1, len, f); + fclose(f); + + if (n != len) { + return -1; + } + + return 0; +} + +static int send_all(int sock, const uint8_t *buf, size_t len) { + size_t total = 0; + while (total < len) { + ssize_t sent = send(sock, (const char *)buf + total, (int)(len - total), 0); + if (sent < 0) { + if (errno == EINTR) { + continue; + } + return -1; + } + if (sent == 0) { + errno = ECONNRESET; + return -1; + } + total += (size_t)sent; + } + return 0; +} + +static int recv_all(int sock, uint8_t *buf, size_t len) { + size_t total = 0; + while (total < len) { + ssize_t recvd = recv(sock, (char *)buf + total, (int)(len - total), 0); + if (recvd == 0) { + errno = ECONNRESET; + return -1; + } + if (recvd < 0) { + if (errno == EINTR) { + continue; + } + return -1; + } + total += (size_t)recvd; + } + return 0; +} + +static int send_blob(int sock, const uint8_t *data, uint32_t data_len) { + uint32_t len_net = htonl(data_len); + if (send_all(sock, (const uint8_t *)&len_net, sizeof(len_net)) < 0) { + return -1; + } + if (data_len == 0) { + return 0; + } + return send_all(sock, data, data_len); +} + +static int recv_blob(int sock, uint8_t *buffer, uint32_t buffer_size, uint32_t *out_len) { + uint32_t len_net = 0; + if (recv_all(sock, (uint8_t *)&len_net, sizeof(len_net)) < 0) { + return -1; + } + + uint32_t payload_len = ntohl(len_net); + if (payload_len > buffer_size) { + errno = EMSGSIZE; + return -1; + } + + if (payload_len > 0 && recv_all(sock, buffer, payload_len) < 0) { + return -1; + } + + *out_len = payload_len; + return 0; +} + +static void log_result(const char *log_path, + int status, + uint32_t challenge_len, + size_t sig_len, + uint64_t elapsed_ms) { + struct rusage ru; + double user_ms = 0.0; + double sys_ms = 0.0; + long rss_kb = 0; + + if (getrusage(RUSAGE_SELF, &ru) == 0) { + user_ms = (double)ru.ru_utime.tv_sec * 1000.0 + (double)ru.ru_utime.tv_usec / 1000.0; + sys_ms = (double)ru.ru_stime.tv_sec * 1000.0 + (double)ru.ru_stime.tv_usec / 1000.0; + rss_kb = ru.ru_maxrss; + } + + FILE *f = fopen(log_path, "a"); + if (!f) { + return; + } + + fprintf(f, + "pid=%ld status=%s elapsed_ms=%llu cpu_user_ms=%.3f cpu_sys_ms=%.3f rss_kb=%ld challenge=%u sig=%zu\n", + (long)getpid(), + status == 0 ? "OK" : "FAIL", + (unsigned long long)elapsed_ms, + user_ms, + sys_ms, + rss_kb, + challenge_len, + sig_len); + fclose(f); +} + +int main(int argc, char *argv[]) { + int sock = -1; + struct sockaddr_in server_addr; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t challenge[BUFFER_SIZE]; + uint32_t challenge_len = 0; + uint8_t signature[CRYPTO_BYTES]; + size_t sig_len = 0; + + const char *ip = (argc > 1) ? argv[1] : DEFAULT_TARGET_IP; + + const char *log_path = getenv("CLIENT_LOG_PATH"); + if (!log_path || *log_path == '\0') { + log_path = CLIENT_LOG_PATH; + } + + if (load_file_exact(CLIENT_SK_PATH, sk, sizeof(sk)) < 0) { + fprintf(stderr, "Missing %s. Run test_sphincsplus_keygen first.\n", CLIENT_SK_PATH); + return 1; + } + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("socket failed"); + return 1; + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(SERVER_PORT); + if (inet_pton(AF_INET, ip, &server_addr.sin_addr) != 1) { + fprintf(stderr, "Invalid server IP: %s\n", ip); + close(sock); + return 1; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("connect failed"); + close(sock); + return 1; + } + printf("[+] Connected to %s\n", ip); + + uint64_t start_ms = get_time_ms(); + + printf("[*] Waiting for challenge from server...\n"); + if (recv_blob(sock, challenge, BUFFER_SIZE, &challenge_len) < 0) { + perror("recv() challenge failed"); + close(sock); + log_result(log_path, 1, challenge_len, 0, get_time_ms() - start_ms); + return 1; + } + printf("[+] Received challenge: %u bytes\n", challenge_len); + + printf("[*] Signing challenge...\n"); + if (crypto_sign_signature(signature, &sig_len, challenge, (size_t)challenge_len, sk) != 0) { + fprintf(stderr, "Signature failed\n"); + close(sock); + log_result(log_path, 1, challenge_len, 0, get_time_ms() - start_ms); + return 1; + } + + if (sig_len > UINT32_MAX) { + fprintf(stderr, "Signature too large: %zu bytes\n", sig_len); + close(sock); + log_result(log_path, 1, challenge_len, sig_len, get_time_ms() - start_ms); + return 1; + } + + printf("[*] Sending signature...\n"); + if (send_blob(sock, signature, (uint32_t)sig_len) < 0) { + perror("send() signature failed"); + close(sock); + log_result(log_path, 1, challenge_len, sig_len, get_time_ms() - start_ms); + return 1; + } + + printf("[DONE] SPHINCS+ process finished successfully.\n"); + close(sock); + log_result(log_path, 0, challenge_len, sig_len, get_time_ms() - start_ms); + return 0; +} \ No newline at end of file diff --git a/ref/test/test_sphincsplus_keygen.c b/ref/test/test_sphincsplus_keygen.c new file mode 100644 index 00000000..90ed2c16 --- /dev/null +++ b/ref/test/test_sphincsplus_keygen.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +#include "../api.h" + +#define CLIENT_SK_PATH "client_sk.bin" +#define CLIENT_PK_PATH "client_pk.bin" +#define SERVER_PK_PATH "server_pk.bin" + +static int write_file(const char *path, const uint8_t *buf, size_t len) { + FILE *f = fopen(path, "wb"); + if (!f) { + return -1; + } + if (fwrite(buf, 1, len, f) != len) { + fclose(f); + return -1; + } + fclose(f); + return 0; +} + +int main(void) { + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + + printf("[*] Generating SPHINCS+ keypair...\n"); + if (crypto_sign_keypair(pk, sk) != 0) { + fprintf(stderr, "Key generation failed\n"); + return 1; + } + + if (write_file(CLIENT_SK_PATH, sk, sizeof(sk)) < 0) { + fprintf(stderr, "Failed to write %s\n", CLIENT_SK_PATH); + return 1; + } + + if (write_file(CLIENT_PK_PATH, pk, sizeof(pk)) < 0) { + fprintf(stderr, "Failed to write %s\n", CLIENT_PK_PATH); + return 1; + } + + if (write_file(SERVER_PK_PATH, pk, sizeof(pk)) < 0) { + fprintf(stderr, "Failed to write %s\n", SERVER_PK_PATH); + return 1; + } + + printf("[OK] Wrote %s, %s, %s\n", CLIENT_SK_PATH, CLIENT_PK_PATH, SERVER_PK_PATH); + printf("Copy %s to the server machine before running the server.\n", SERVER_PK_PATH); + return 0; +} \ No newline at end of file diff --git a/ref/test/test_sphincsplus_server.c b/ref/test/test_sphincsplus_server.c new file mode 100644 index 00000000..cbd244cb --- /dev/null +++ b/ref/test/test_sphincsplus_server.c @@ -0,0 +1,462 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Platform-specific socket headers - must come before ../api.h to avoid macro conflicts */ +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #include + #include + #include + #define close(sock) closesocket(sock) + #define ssize_t int + /* Undefine potential macro conflicts that Windows headers define */ + #undef N + #undef D + #undef L +#else + #include + #include + #include + #include + #include + #include + #include +#endif + +/* SPHINCS+ headers - included after socket headers to avoid macro conflicts */ +#include "../api.h" + +/* Configuration */ +#define SERVER_PORT 5000 +#define CHALLENGE_MAX 8192 +#define CHALLENGE_PATH_PRIMARY "test/input.txt" +#define CHALLENGE_PATH_FALLBACK "input.txt" +#define SERVER_PK_PATH "server_pk.bin" +#define SERVER_LOG_PATH "server.log" + +/* Forward declarations */ +static uint64_t get_time_ms(void); +static int send_all(int sock, const uint8_t *buf, size_t len); +static int recv_all(int sock, uint8_t *buf, size_t len); +static int send_blob(int sock, const uint8_t *data, uint32_t data_len); +static int recv_blob(int sock, uint8_t *buf, uint32_t buf_size, uint32_t *out_len); +static int send_challenge(int sock, const uint8_t *challenge, size_t challenge_len); +static int receive_signature(int sock, uint8_t *signature, size_t *sig_len); +static int load_file_exact(const char *path, uint8_t *buf, size_t len); +static int load_public_key(const char *path, uint8_t *pk); +static void load_challenge(uint8_t *challenge, size_t *challenge_len); +static void log_result(const char *log_path, + const char *client_ip, + uint16_t client_port, + int verify_result, + size_t challenge_len, + size_t sig_len, + uint64_t elapsed_ms); +static int handle_client(int client_sock, const struct sockaddr_in *client_addr); + +static uint8_t g_pk[CRYPTO_PUBLICKEYBYTES]; +static uint8_t g_challenge[CHALLENGE_MAX]; +static size_t g_challenge_len = 0; + +/* Get current time in milliseconds */ +static uint64_t get_time_ms(void) { +#ifdef _WIN32 + return (uint64_t)GetTickCount64(); +#else + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + return 0; + } + return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +#endif +} + +static int send_all(int sock, const uint8_t *buf, size_t len) { + size_t total = 0; + while (total < len) { + ssize_t sent = send(sock, (const char *)buf + total, (int)(len - total), 0); + if (sent < 0) { +#ifndef _WIN32 + if (errno == EINTR) { + continue; + } +#endif + return -1; + } + if (sent == 0) { + errno = ECONNRESET; + return -1; + } + total += (size_t)sent; + } + return 0; +} + +static int recv_all(int sock, uint8_t *buf, size_t len) { + size_t total = 0; + while (total < len) { + ssize_t recvd = recv(sock, (char *)buf + total, (int)(len - total), 0); + if (recvd == 0) { + errno = ECONNRESET; + return -1; + } + if (recvd < 0) { +#ifndef _WIN32 + if (errno == EINTR) { + continue; + } +#endif + return -1; + } + total += (size_t)recvd; + } + return 0; +} + +static int send_blob(int sock, const uint8_t *data, uint32_t data_len) { + uint32_t len_net = htonl(data_len); + if (send_all(sock, (const uint8_t *)&len_net, sizeof(len_net)) < 0) { + return -1; + } + if (data_len == 0) { + return 0; + } + return send_all(sock, data, data_len); +} + +static int recv_blob(int sock, uint8_t *buf, uint32_t buf_size, uint32_t *out_len) { + uint32_t len_net = 0; + if (recv_all(sock, (uint8_t *)&len_net, sizeof(len_net)) < 0) { + return -1; + } + + uint32_t len = ntohl(len_net); + if (len > buf_size) { + errno = EMSGSIZE; + return -1; + } + + if (len > 0 && recv_all(sock, buf, len) < 0) { + return -1; + } + + *out_len = len; + return 0; +} + +static int load_file_exact(const char *path, uint8_t *buf, size_t len) { + FILE *f = fopen(path, "rb"); + if (!f) { + return -1; + } + + size_t n = fread(buf, 1, len, f); + fclose(f); + + if (n != len) { + return -1; + } + + return 0; +} + +static int load_public_key(const char *path, uint8_t *pk) { + if (load_file_exact(path, pk, CRYPTO_PUBLICKEYBYTES) < 0) { + fprintf(stderr, "Failed to load public key from %s\n", path); + return -1; + } + return 0; +} + +static void load_challenge(uint8_t *challenge, size_t *challenge_len) { + FILE *fin = fopen(CHALLENGE_PATH_PRIMARY, "rb"); + if (!fin) { + fin = fopen(CHALLENGE_PATH_FALLBACK, "rb"); + } + + if (!fin) { + const char *default_msg = "This is a test challenge message"; + size_t default_len = strlen(default_msg); + memcpy(challenge, default_msg, default_len); + *challenge_len = default_len; + printf("[WARNING] Cannot open input file, using default challenge\n"); + return; + } + + *challenge_len = fread(challenge, 1, CHALLENGE_MAX, fin); + fclose(fin); + + if (*challenge_len == 0) { + const char *default_msg = "This is a test challenge message"; + size_t default_len = strlen(default_msg); + memcpy(challenge, default_msg, default_len); + *challenge_len = default_len; + printf("[WARNING] Empty input file, using default challenge\n"); + } +} + +static void log_result(const char *log_path, + const char *client_ip, + uint16_t client_port, + int verify_result, + size_t challenge_len, + size_t sig_len, + uint64_t elapsed_ms) { + double user_ms = 0.0; + double sys_ms = 0.0; + long rss_kb = 0; + +#ifndef _WIN32 + struct rusage ru; + if (getrusage(RUSAGE_SELF, &ru) == 0) { + user_ms = (double)ru.ru_utime.tv_sec * 1000.0 + (double)ru.ru_utime.tv_usec / 1000.0; + sys_ms = (double)ru.ru_stime.tv_sec * 1000.0 + (double)ru.ru_stime.tv_usec / 1000.0; + rss_kb = ru.ru_maxrss; + } +#endif + + FILE *f = fopen(log_path, "a"); + if (!f) { + return; + } + + fprintf(f, + "client=%s:%u verify=%s elapsed_ms=%llu cpu_user_ms=%.3f cpu_sys_ms=%.3f rss_kb=%ld challenge=%zu sig=%zu\n", + client_ip ? client_ip : "unknown", + (unsigned int)client_port, + verify_result == 0 ? "OK" : "FAIL", + (unsigned long long)elapsed_ms, + user_ms, + sys_ms, + rss_kb, + challenge_len, + sig_len); + fclose(f); +} + +/* Send challenge message to client */ +static int send_challenge(int sock, const uint8_t *challenge, size_t challenge_len) { + printf("[*] Sending challenge to client (size: %zu bytes)...\n", challenge_len); + + if (challenge_len > UINT32_MAX) { + fprintf(stderr, "Challenge too large: %zu bytes\n", challenge_len); + return -1; + } + + if (send_blob(sock, challenge, (uint32_t)challenge_len) < 0) { + perror("send() challenge failed"); + return -1; + } + + printf("[+] Challenge sent successfully\n\n"); + return 0; +} + +/* Receive signature from client */ +static int receive_signature(int sock, uint8_t *signature, size_t *sig_len) { + printf("[*] Waiting for signature from client...\n"); + + uint32_t size = 0; + if (recv_blob(sock, signature, CRYPTO_BYTES, &size) < 0) { + perror("recv() signature failed"); + return -1; + } + + *sig_len = (size_t)size; + printf("[+] Signature received successfully (size: %zu bytes)\n\n", *sig_len); + return 0; +} + +static int handle_client(int client_sock, const struct sockaddr_in *client_addr) { + uint64_t total_start = get_time_ms(); + + uint8_t signature[CRYPTO_BYTES]; + size_t sig_len = 0; + + char client_ip[INET_ADDRSTRLEN] = "unknown"; + uint16_t client_port = 0; + if (client_addr) { + inet_ntop(AF_INET, &client_addr->sin_addr, client_ip, sizeof(client_ip)); + client_port = ntohs(client_addr->sin_port); + } + + /* ============ STAGE 1: Send Challenge ============ */ + printf("[STAGE 1] Sending challenge to client...\n"); + printf("- Challenge size: %zu bytes\n", g_challenge_len); + + uint64_t send_challenge_start = get_time_ms(); + if (send_challenge(client_sock, g_challenge, g_challenge_len) < 0) { + fprintf(stderr, "Failed to send challenge\n"); + return 1; + } + uint64_t send_challenge_end = get_time_ms(); + + printf("[+] Send challenge time: %llu ms\n\n", + (unsigned long long)(send_challenge_end - send_challenge_start)); + + /* ============ STAGE 2: Receive Signature ============ */ + printf("[STAGE 2] Receiving signature from client...\n"); + + uint64_t recv_sig_start = get_time_ms(); + if (receive_signature(client_sock, signature, &sig_len) < 0) { + fprintf(stderr, "Failed to receive signature\n"); + return 1; + } + uint64_t recv_sig_end = get_time_ms(); + + printf("- Signature size: %zu bytes\n", sig_len); + printf("[+] Receive signature time: %llu ms\n\n", + (unsigned long long)(recv_sig_end - recv_sig_start)); + + /* ============ STAGE 3: Verify Signature ============ */ + printf("[STAGE 3] Verifying signature...\n"); + + uint64_t verify_start = get_time_ms(); + int verify_result = crypto_sign_verify(signature, sig_len, g_challenge, g_challenge_len, + g_pk); + uint64_t verify_end = get_time_ms(); + + printf("- Verification result: %s\n", verify_result == 0 ? "VALID" : "INVALID"); + printf("[+] Verification time: %llu ms\n\n", + (unsigned long long)(verify_end - verify_start)); + + /* ============ TIMING SUMMARY ============ */ + uint64_t total_end = get_time_ms(); + + printf("===================================\n"); + printf("[TIMING SUMMARY]\n"); + printf("===================================\n"); + printf("Send Challenge Time: %llu ms\n", + (unsigned long long)(send_challenge_end - send_challenge_start)); + printf("Receive Signature Time: %llu ms\n", + (unsigned long long)(recv_sig_end - recv_sig_start)); + printf("Verification Time: %llu ms\n", + (unsigned long long)(verify_end - verify_start)); + printf("-----------------------------------\n"); + printf("Total Time (from start): %llu ms\n", + (unsigned long long)(total_end - total_start)); + printf("===================================\n\n"); + + printf("[KEY INFORMATION]\n"); + printf("- Signature Size: %zu bytes\n", sig_len); + printf("- Challenge Size: %zu bytes\n", g_challenge_len); + printf("===================================\n\n"); + + printf("[+] Signature verification %s.\n", verify_result == 0 ? "OK" : "FAILED"); + + log_result(SERVER_LOG_PATH, client_ip, client_port, verify_result, + g_challenge_len, sig_len, total_end - total_start); + + return verify_result == 0 ? 0 : 1; +} + +int main(void) { + int listen_sock = -1; + + printf("\n========== SPHINCS+ Server ==========\n"); + printf("Listening on port %d\n", SERVER_PORT); + printf("======================================\n\n"); + + /* Windows socket initialization */ +#ifdef _WIN32 + WSADATA wsa_data; + if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { + fprintf(stderr, "WSAStartup failed\n"); + return 1; + } +#else + signal(SIGCHLD, SIG_IGN); + signal(SIGPIPE, SIG_IGN); +#endif + + if (load_public_key(SERVER_PK_PATH, g_pk) < 0) { +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } + + load_challenge(g_challenge, &g_challenge_len); + + /* ============ STAGE 0: Create Socket & Listen ============ */ + listen_sock = socket(AF_INET, SOCK_STREAM, 0); + if (listen_sock < 0) { + perror("socket() failed"); +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } + + /* Allow socket address reuse */ + int reuse = 1; + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, sizeof(reuse)) < 0) { + perror("setsockopt() failed"); + close(listen_sock); +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } + + struct sockaddr_in server_addr; + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(SERVER_PORT); + + if (bind(listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("bind() failed"); + close(listen_sock); +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } + + if (listen(listen_sock, 10) < 0) { + perror("listen() failed"); + close(listen_sock); +#ifdef _WIN32 + WSACleanup(); +#endif + return 1; + } + + printf("[+] Server listening on port %d\n\n", SERVER_PORT); + + /* ============ Main Loop ============ */ + while (1) { + struct sockaddr_in client_addr; + socklen_t client_addr_len = sizeof(client_addr); + + printf("[*] Waiting for client connections...\n"); + int client_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &client_addr_len); + if (client_sock < 0) { + perror("accept() failed"); + continue; + } + + char client_ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip)); + uint16_t client_port = ntohs(client_addr.sin_port); + printf("[+] Client connected from %s:%u\n\n", client_ip, client_port); + + handle_client(client_sock, &client_addr); + + close(client_sock); + printf("[+] Client disconnected\n\n"); + } + + close(listen_sock); +#ifdef _WIN32 + WSACleanup(); +#endif + return 0; +} \ No newline at end of file diff --git a/ref/test/test_sphincsplus_stress.c b/ref/test/test_sphincsplus_stress.c new file mode 100644 index 00000000..8eeb7633 --- /dev/null +++ b/ref/test/test_sphincsplus_stress.c @@ -0,0 +1,346 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../api.h" + +#define SERVER_PORT 5000 +#define BUFFER_SIZE 8192 +#define DEFAULT_TARGET_IP "192.168.4.85" +#define DEFAULT_CONCURRENT 10 +#define DEFAULT_BATCHES 0 +#define DEFAULT_BATCH_DELAY_SEC 0 +#define CLIENT_SK_PATH "client_sk.bin" +#define CLIENT_LOG_PATH "client.log" + +static uint64_t get_time_ms(void) { + struct timespec ts; + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { + return 0; + } + return (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000; +} + +static unsigned int parse_uint_env(const char *name, unsigned int def_value) { + const char *val = getenv(name); + if (!val || *val == '\0') { + return def_value; + } + + char *end = NULL; + unsigned long parsed = strtoul(val, &end, 10); + if (!end || *end != '\0' || parsed > UINT_MAX) { + return def_value; + } + + return (unsigned int)parsed; +} + +static int load_file_exact(const char *path, uint8_t *buf, size_t len) { + FILE *f = fopen(path, "rb"); + if (!f) { + return -1; + } + + size_t n = fread(buf, 1, len, f); + fclose(f); + + if (n != len) { + return -1; + } + + return 0; +} + +static int send_all(int sock, const uint8_t *buf, size_t len) { + size_t total = 0; + while (total < len) { + ssize_t sent = send(sock, (const char *)buf + total, (int)(len - total), 0); + if (sent < 0) { + if (errno == EINTR) { + continue; + } + return -1; + } + if (sent == 0) { + errno = ECONNRESET; + return -1; + } + total += (size_t)sent; + } + return 0; +} + +static int recv_all(int sock, uint8_t *buf, size_t len) { + size_t total = 0; + while (total < len) { + ssize_t recvd = recv(sock, (char *)buf + total, (int)(len - total), 0); + if (recvd == 0) { + errno = ECONNRESET; + return -1; + } + if (recvd < 0) { + if (errno == EINTR) { + continue; + } + return -1; + } + total += (size_t)recvd; + } + return 0; +} + +static int send_blob(int sock, const uint8_t *data, uint32_t data_len) { + uint32_t len_net = htonl(data_len); + if (send_all(sock, (const uint8_t *)&len_net, sizeof(len_net)) < 0) { + return -1; + } + if (data_len == 0) { + return 0; + } + return send_all(sock, data, data_len); +} + +static int recv_blob(int sock, uint8_t *buffer, uint32_t buffer_size, uint32_t *out_len) { + uint32_t len_net = 0; + if (recv_all(sock, (uint8_t *)&len_net, sizeof(len_net)) < 0) { + return -1; + } + + uint32_t payload_len = ntohl(len_net); + if (payload_len > buffer_size) { + errno = EMSGSIZE; + return -1; + } + + if (payload_len > 0 && recv_all(sock, buffer, payload_len) < 0) { + return -1; + } + + *out_len = payload_len; + return 0; +} + +static void log_result(const char *log_path, + int status, + uint32_t challenge_len, + size_t sig_len, + uint64_t elapsed_ms) { + struct rusage ru; + double user_ms = 0.0; + double sys_ms = 0.0; + long rss_kb = 0; + + if (getrusage(RUSAGE_SELF, &ru) == 0) { + user_ms = (double)ru.ru_utime.tv_sec * 1000.0 + (double)ru.ru_utime.tv_usec / 1000.0; + sys_ms = (double)ru.ru_stime.tv_sec * 1000.0 + (double)ru.ru_stime.tv_usec / 1000.0; + rss_kb = ru.ru_maxrss; + } + + FILE *f = fopen(log_path, "a"); + if (!f) { + return; + } + + fprintf(f, + "pid=%ld status=%s elapsed_ms=%llu cpu_user_ms=%.3f cpu_sys_ms=%.3f rss_kb=%ld challenge=%u sig=%zu\n", + (long)getpid(), + status == 0 ? "OK" : "FAIL", + (unsigned long long)elapsed_ms, + user_ms, + sys_ms, + rss_kb, + challenge_len, + sig_len); + fclose(f); +} + +static int client_session(const char *ip, const uint8_t *sk) { + int sock = -1; + struct sockaddr_in server_addr; + uint8_t challenge[BUFFER_SIZE]; + uint32_t challenge_len = 0; + uint8_t signature[CRYPTO_BYTES]; + size_t sig_len = 0; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + perror("socket failed"); + return 1; + } + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(SERVER_PORT); + if (inet_pton(AF_INET, ip, &server_addr.sin_addr) != 1) { + fprintf(stderr, "Invalid server IP: %s\n", ip); + close(sock); + return 1; + } + + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + perror("connect failed"); + close(sock); + return 1; + } + + uint64_t start_ms = get_time_ms(); + + if (recv_blob(sock, challenge, BUFFER_SIZE, &challenge_len) < 0) { + perror("recv() challenge failed"); + close(sock); + return 1; + } + + if (crypto_sign_signature(signature, &sig_len, challenge, (size_t)challenge_len, sk) != 0) { + fprintf(stderr, "Signature failed\n"); + close(sock); + return 1; + } + + if (sig_len > UINT32_MAX) { + fprintf(stderr, "Signature too large: %zu bytes\n", sig_len); + close(sock); + return 1; + } + + if (send_blob(sock, signature, (uint32_t)sig_len) < 0) { + perror("send() signature failed"); + close(sock); + return 1; + } + + close(sock); + log_result(CLIENT_LOG_PATH, 0, challenge_len, sig_len, get_time_ms() - start_ms); + return 0; +} + +int main(int argc, char *argv[]) { + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + + const char *target_ip = getenv("TARGET_IP"); + if (!target_ip || *target_ip == '\0') { + target_ip = DEFAULT_TARGET_IP; + } + + unsigned int concurrent_sessions = parse_uint_env("CONCURRENT_SESSIONS", DEFAULT_CONCURRENT); + unsigned int batches = parse_uint_env("BATCHES", DEFAULT_BATCHES); + unsigned int batch_delay_sec = parse_uint_env("BATCH_DELAY_SEC", DEFAULT_BATCH_DELAY_SEC); + + if (load_file_exact(CLIENT_SK_PATH, sk, sizeof(sk)) < 0) { + fprintf(stderr, "Missing %s. Run test_sphincsplus_keygen first.\n", CLIENT_SK_PATH); + return 1; + } + + printf("[STRESS TEST] SPHINCS+ Client\n"); + printf("- Target IP: %s\n", target_ip); + printf("- Concurrent sessions: %u\n", concurrent_sessions); + printf("- Batches: %u\n", batches); + printf("- Batch delay: %u sec\n", batch_delay_sec); + printf("\n"); + + if (batches == 0) { + /* Single batch mode */ + pid_t *pids = calloc(concurrent_sessions, sizeof(pid_t)); + if (!pids) { + perror("calloc failed"); + return 1; + } + + uint64_t batch_start = get_time_ms(); + + for (unsigned int i = 0; i < concurrent_sessions; i++) { + pids[i] = fork(); + if (pids[i] < 0) { + perror("fork failed"); + return 1; + } else if (pids[i] == 0) { + /* Child process */ + exit(client_session(target_ip, sk)); + } + } + + int failed_count = 0; + for (unsigned int i = 0; i < concurrent_sessions; i++) { + int status; + if (waitpid(pids[i], &status, 0) < 0) { + perror("waitpid failed"); + return 1; + } + if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { + failed_count++; + } + } + + uint64_t batch_end = get_time_ms(); + printf("[BATCH] Completed in %llu ms, %u/%u succeeded\n", + (unsigned long long)(batch_end - batch_start), + concurrent_sessions - failed_count, concurrent_sessions); + + free(pids); + } else { + /* Multiple batches mode */ + for (unsigned int batch = 1; batch <= batches; batch++) { + printf("[BATCH %u/%u] Starting...\n", batch, batches); + + pid_t *pids = calloc(concurrent_sessions, sizeof(pid_t)); + if (!pids) { + perror("calloc failed"); + return 1; + } + + uint64_t batch_start = get_time_ms(); + + for (unsigned int i = 0; i < concurrent_sessions; i++) { + pids[i] = fork(); + if (pids[i] < 0) { + perror("fork failed"); + return 1; + } else if (pids[i] == 0) { + /* Child process */ + exit(client_session(target_ip, sk)); + } + } + + int failed_count = 0; + for (unsigned int i = 0; i < concurrent_sessions; i++) { + int status; + if (waitpid(pids[i], &status, 0) < 0) { + perror("waitpid failed"); + return 1; + } + if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { + failed_count++; + } + } + + uint64_t batch_end = get_time_ms(); + printf("[BATCH %u/%u] Completed in %llu ms, %u/%u succeeded\n", + batch, batches, + (unsigned long long)(batch_end - batch_start), + concurrent_sessions - failed_count, concurrent_sessions); + + free(pids); + + if (batch < batches && batch_delay_sec > 0) { + printf("[DELAY] Waiting %u seconds before next batch...\n", batch_delay_sec); + sleep(batch_delay_sec); + } + } + } + + return 0; +} \ No newline at end of file diff --git a/ref/test/test_vectors.c b/ref/test/test_vectors.c new file mode 100644 index 00000000..b75b3f8d --- /dev/null +++ b/ref/test/test_vectors.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include "../api.h" + +#define MLEN 32 +#define NVECTORS 100 + +int main(void) { + unsigned int i, j; + uint8_t pk[CRYPTO_PUBLICKEYBYTES]; + uint8_t sk[CRYPTO_SECRETKEYBYTES]; + uint8_t sig[CRYPTO_BYTES]; + uint8_t m[MLEN]; + unsigned long long siglen; + + printf("SPHINCS+ Test Vectors\n"); + printf("Public Key bytes = %d\n", CRYPTO_PUBLICKEYBYTES); + printf("Secret Key bytes = %d\n", CRYPTO_SECRETKEYBYTES); + printf("Signature bytes = %d\n", CRYPTO_BYTES); + printf("\n"); + + for(i = 0; i < NVECTORS; ++i) { + printf("count = %u\n", i); + + // Generate random message + for(j = 0; j < MLEN; ++j) { + m[j] = (uint8_t)(rand() & 0xFF); + } + printf("m = "); + for(j = 0; j < MLEN; ++j) + printf("%02x", m[j]); + printf("\n"); + + // Key generation + crypto_sign_keypair(pk, sk); + printf("pk = "); + for(j = 0; j < CRYPTO_PUBLICKEYBYTES; ++j) + printf("%02x", pk[j]); + printf("\n"); + printf("sk = "); + for(j = 0; j < CRYPTO_SECRETKEYBYTES; ++j) + printf("%02x", sk[j]); + printf("\n"); + + // Signing + crypto_sign_signature(sig, &siglen, m, MLEN, sk); + printf("sig = "); + for(j = 0; j < siglen; ++j) + printf("%02x", sig[j]); + printf("\n"); + + // Verification + int valid = crypto_sign_verify(sig, siglen, m, MLEN, pk); + printf("valid = %d\n", valid == 0 ? 1 : 0); + + if (valid == 0) { + printf("PASS\n"); + } else { + printf("FAIL\n"); + } + printf("\n"); + } + + return 0; +} \ No newline at end of file From 3dc39eeef54ace8726989a4350c7d37e0583fe28 Mon Sep 17 00:00:00 2001 From: quanne200679 Date: Sun, 10 May 2026 14:03:21 +0700 Subject: [PATCH 3/5] Add files via upload --- ref/test/test_sphincsplus_stress.c | 65 ++++++++---------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/ref/test/test_sphincsplus_stress.c b/ref/test/test_sphincsplus_stress.c index 8eeb7633..d6620915 100644 --- a/ref/test/test_sphincsplus_stress.c +++ b/ref/test/test_sphincsplus_stress.c @@ -252,8 +252,10 @@ int main(int argc, char *argv[]) { printf("- Batch delay: %u sec\n", batch_delay_sec); printf("\n"); - if (batches == 0) { - /* Single batch mode */ + unsigned int batch = 1; + while (batches == 0 || batch <= batches) { + printf("[BATCH %u/%s] Starting...\n", batch, batches == 0 ? "inf" : "fixed"); + pid_t *pids = calloc(concurrent_sessions, sizeof(pid_t)); if (!pids) { perror("calloc failed"); @@ -266,6 +268,7 @@ int main(int argc, char *argv[]) { pids[i] = fork(); if (pids[i] < 0) { perror("fork failed"); + free(pids); return 1; } else if (pids[i] == 0) { /* Child process */ @@ -278,6 +281,7 @@ int main(int argc, char *argv[]) { int status; if (waitpid(pids[i], &status, 0) < 0) { perror("waitpid failed"); + free(pids); return 1; } if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { @@ -286,60 +290,23 @@ int main(int argc, char *argv[]) { } uint64_t batch_end = get_time_ms(); - printf("[BATCH] Completed in %llu ms, %u/%u succeeded\n", + printf("[BATCH %u] Completed in %llu ms, %u/%u succeeded\n", + batch, (unsigned long long)(batch_end - batch_start), concurrent_sessions - failed_count, concurrent_sessions); free(pids); - } else { - /* Multiple batches mode */ - for (unsigned int batch = 1; batch <= batches; batch++) { - printf("[BATCH %u/%u] Starting...\n", batch, batches); - - pid_t *pids = calloc(concurrent_sessions, sizeof(pid_t)); - if (!pids) { - perror("calloc failed"); - return 1; - } - uint64_t batch_start = get_time_ms(); - - for (unsigned int i = 0; i < concurrent_sessions; i++) { - pids[i] = fork(); - if (pids[i] < 0) { - perror("fork failed"); - return 1; - } else if (pids[i] == 0) { - /* Child process */ - exit(client_session(target_ip, sk)); - } - } - - int failed_count = 0; - for (unsigned int i = 0; i < concurrent_sessions; i++) { - int status; - if (waitpid(pids[i], &status, 0) < 0) { - perror("waitpid failed"); - return 1; - } - if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { - failed_count++; - } - } - - uint64_t batch_end = get_time_ms(); - printf("[BATCH %u/%u] Completed in %llu ms, %u/%u succeeded\n", - batch, batches, - (unsigned long long)(batch_end - batch_start), - concurrent_sessions - failed_count, concurrent_sessions); - - free(pids); + if (batches != 0 && batch >= batches) { + break; + } - if (batch < batches && batch_delay_sec > 0) { - printf("[DELAY] Waiting %u seconds before next batch...\n", batch_delay_sec); - sleep(batch_delay_sec); - } + if (batch_delay_sec > 0) { + printf("[DELAY] Waiting %u seconds before next batch...\n", batch_delay_sec); + sleep(batch_delay_sec); } + + batch++; } return 0; From 4d69fa7d9fa20a51d347252fafc4010a3c1c1692 Mon Sep 17 00:00:00 2001 From: quanne200679 Date: Sun, 10 May 2026 17:16:33 +0700 Subject: [PATCH 4/5] Add files via upload --- ref/test/test_sphincsplus_server.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ref/test/test_sphincsplus_server.c b/ref/test/test_sphincsplus_server.c index cbd244cb..cfa9cdb1 100644 --- a/ref/test/test_sphincsplus_server.c +++ b/ref/test/test_sphincsplus_server.c @@ -448,9 +448,27 @@ int main(void) { uint16_t client_port = ntohs(client_addr.sin_port); printf("[+] Client connected from %s:%u\n\n", client_ip, client_port); - handle_client(client_sock, &client_addr); +#ifndef _WIN32 + pid_t pid = fork(); + if (pid == 0) { + close(listen_sock); + handle_client(client_sock, &client_addr); + close(client_sock); + _exit(0); + } + + if (pid < 0) { + perror("fork() failed"); + close(client_sock); + continue; + } close(client_sock); +#else + handle_client(client_sock, &client_addr); + close(client_sock); +#endif + printf("[+] Client disconnected\n\n"); } From 2af673c812ee12918ae4390238def749c3498293 Mon Sep 17 00:00:00 2001 From: quanne200679 Date: Tue, 19 May 2026 14:15:39 +0700 Subject: [PATCH 5/5] Add files via upload --- ref/test/log_sphincsplus_clientv2.txt | 618 ++++++++++++++++++++++++++ 1 file changed, 618 insertions(+) create mode 100644 ref/test/log_sphincsplus_clientv2.txt diff --git a/ref/test/log_sphincsplus_clientv2.txt b/ref/test/log_sphincsplus_clientv2.txt new file mode 100644 index 00000000..f819f330 --- /dev/null +++ b/ref/test/log_sphincsplus_clientv2.txt @@ -0,0 +1,618 @@ + +CONCURRENT_SESSIONS=10 BATCHES=10 ./test_sphincsplus_stress + +sha2-128s simple +log: + +pid=3498 status=OK elapsed_ms=136189 cpu_user_ms=11439.653 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=3497 status=OK elapsed_ms=136193 cpu_user_ms=11423.610 cpu_sys_ms=15.036 rss_kb=608 challenge=32 sig=7856 +pid=3504 status=OK elapsed_ms=136206 cpu_user_ms=11428.664 cpu_sys_ms=11.172 rss_kb=608 challenge=32 sig=7856 +pid=3500 status=OK elapsed_ms=136211 cpu_user_ms=11411.334 cpu_sys_ms=26.250 rss_kb=608 challenge=32 sig=7856 +pid=3502 status=OK elapsed_ms=136190 cpu_user_ms=11437.204 cpu_sys_ms=3.708 rss_kb=608 challenge=32 sig=7856 +pid=3499 status=OK elapsed_ms=136225 cpu_user_ms=11435.253 cpu_sys_ms=7.463 rss_kb=608 challenge=32 sig=7856 +pid=3501 status=OK elapsed_ms=136220 cpu_user_ms=11435.954 cpu_sys_ms=3.747 rss_kb=608 challenge=32 sig=7856 +pid=3503 status=OK elapsed_ms=136235 cpu_user_ms=11444.764 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=3506 status=OK elapsed_ms=136215 cpu_user_ms=11428.396 cpu_sys_ms=11.255 rss_kb=608 challenge=32 sig=7856 +pid=3505 status=OK elapsed_ms=136236 cpu_user_ms=11436.014 cpu_sys_ms=7.497 rss_kb=608 challenge=32 sig=7856 +pid=3692 status=OK elapsed_ms=135925 cpu_user_ms=11416.670 cpu_sys_ms=14.961 rss_kb=608 challenge=32 sig=7856 +pid=3696 status=OK elapsed_ms=135970 cpu_user_ms=11422.230 cpu_sys_ms=7.554 rss_kb=608 challenge=32 sig=7856 +pid=3690 status=OK elapsed_ms=135972 cpu_user_ms=11424.450 cpu_sys_ms=7.467 rss_kb=608 challenge=32 sig=7856 +pid=3694 status=OK elapsed_ms=135992 cpu_user_ms=11421.781 cpu_sys_ms=11.172 rss_kb=608 challenge=32 sig=7856 +pid=3697 status=OK elapsed_ms=135999 cpu_user_ms=11422.038 cpu_sys_ms=11.136 rss_kb=608 challenge=32 sig=7856 +pid=3691 status=OK elapsed_ms=135991 cpu_user_ms=11415.391 cpu_sys_ms=18.513 rss_kb=608 challenge=32 sig=7856 +pid=3699 status=OK elapsed_ms=135996 cpu_user_ms=11431.595 cpu_sys_ms=3.713 rss_kb=608 challenge=32 sig=7856 +pid=3698 status=OK elapsed_ms=135995 cpu_user_ms=11418.892 cpu_sys_ms=14.995 rss_kb=608 challenge=32 sig=7856 +pid=3693 status=OK elapsed_ms=136011 cpu_user_ms=11417.911 cpu_sys_ms=18.795 rss_kb=608 challenge=32 sig=7856 +pid=3695 status=OK elapsed_ms=136024 cpu_user_ms=11416.124 cpu_sys_ms=22.482 rss_kb=608 challenge=32 sig=7856 +pid=3887 status=OK elapsed_ms=136148 cpu_user_ms=11439.450 cpu_sys_ms=7.543 rss_kb=608 challenge=32 sig=7856 +pid=3893 status=OK elapsed_ms=136173 cpu_user_ms=11438.302 cpu_sys_ms=14.993 rss_kb=608 challenge=32 sig=7856 +pid=3885 status=OK elapsed_ms=136178 cpu_user_ms=11451.950 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=3886 status=OK elapsed_ms=136189 cpu_user_ms=11452.399 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=3892 status=OK elapsed_ms=136165 cpu_user_ms=11440.812 cpu_sys_ms=11.270 rss_kb=608 challenge=32 sig=7856 +pid=3884 status=OK elapsed_ms=136195 cpu_user_ms=11449.350 cpu_sys_ms=3.746 rss_kb=608 challenge=32 sig=7856 +pid=3891 status=OK elapsed_ms=136169 cpu_user_ms=11446.668 cpu_sys_ms=7.484 rss_kb=608 challenge=32 sig=7856 +pid=3889 status=OK elapsed_ms=136207 cpu_user_ms=11456.666 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=3890 status=OK elapsed_ms=136208 cpu_user_ms=11451.585 cpu_sys_ms=3.750 rss_kb=608 challenge=32 sig=7856 +pid=3888 status=OK elapsed_ms=136202 cpu_user_ms=11450.313 cpu_sys_ms=7.418 rss_kb=608 challenge=32 sig=7856 +pid=4080 status=OK elapsed_ms=135646 cpu_user_ms=11391.324 cpu_sys_ms=11.316 rss_kb=608 challenge=32 sig=7856 +pid=4082 status=OK elapsed_ms=135649 cpu_user_ms=11393.983 cpu_sys_ms=11.296 rss_kb=608 challenge=32 sig=7856 +pid=4079 status=OK elapsed_ms=135668 cpu_user_ms=11397.868 cpu_sys_ms=7.491 rss_kb=608 challenge=32 sig=7856 +pid=4081 status=OK elapsed_ms=135677 cpu_user_ms=11397.181 cpu_sys_ms=7.498 rss_kb=608 challenge=32 sig=7856 +pid=4085 status=OK elapsed_ms=135682 cpu_user_ms=11396.296 cpu_sys_ms=11.127 rss_kb=608 challenge=32 sig=7856 +pid=4078 status=OK elapsed_ms=135688 cpu_user_ms=11404.950 cpu_sys_ms=3.770 rss_kb=608 challenge=32 sig=7856 +pid=4084 status=OK elapsed_ms=135694 cpu_user_ms=11406.662 cpu_sys_ms=3.740 rss_kb=608 challenge=32 sig=7856 +pid=4077 status=OK elapsed_ms=135698 cpu_user_ms=11394.469 cpu_sys_ms=15.001 rss_kb=608 challenge=32 sig=7856 +pid=4083 status=OK elapsed_ms=135698 cpu_user_ms=11397.182 cpu_sys_ms=11.329 rss_kb=608 challenge=32 sig=7856 +pid=4076 status=OK elapsed_ms=135706 cpu_user_ms=11396.109 cpu_sys_ms=14.896 rss_kb=608 challenge=32 sig=7856 +pid=482 status=OK elapsed_ms=135532 cpu_user_ms=11388.788 cpu_sys_ms=11.299 rss_kb=608 challenge=32 sig=7856 +pid=476 status=OK elapsed_ms=135530 cpu_user_ms=11395.932 cpu_sys_ms=3.763 rss_kb=608 challenge=32 sig=7856 +pid=478 status=OK elapsed_ms=135547 cpu_user_ms=11402.110 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=479 status=OK elapsed_ms=135557 cpu_user_ms=11396.262 cpu_sys_ms=7.537 rss_kb=608 challenge=32 sig=7856 +pid=477 status=OK elapsed_ms=135555 cpu_user_ms=11398.502 cpu_sys_ms=3.750 rss_kb=608 challenge=32 sig=7856 +pid=480 status=OK elapsed_ms=135566 cpu_user_ms=11395.473 cpu_sys_ms=7.546 rss_kb=608 challenge=32 sig=7856 +pid=483 status=OK elapsed_ms=135574 cpu_user_ms=11400.807 cpu_sys_ms=3.779 rss_kb=608 challenge=32 sig=7856 +pid=481 status=OK elapsed_ms=135575 cpu_user_ms=11394.154 cpu_sys_ms=11.174 rss_kb=608 challenge=32 sig=7856 +pid=485 status=OK elapsed_ms=135551 cpu_user_ms=11397.384 cpu_sys_ms=7.513 rss_kb=608 challenge=32 sig=7856 +pid=484 status=OK elapsed_ms=135567 cpu_user_ms=11389.403 cpu_sys_ms=14.946 rss_kb=608 challenge=32 sig=7856 +pid=679 status=OK elapsed_ms=135769 cpu_user_ms=11395.619 cpu_sys_ms=18.756 rss_kb=608 challenge=32 sig=7856 +pid=675 status=OK elapsed_ms=135772 cpu_user_ms=11408.270 cpu_sys_ms=7.538 rss_kb=608 challenge=32 sig=7856 +pid=677 status=OK elapsed_ms=135777 cpu_user_ms=11416.364 cpu_sys_ms=0.000 rss_kb=608 challenge=32 sig=7856 +pid=681 status=OK elapsed_ms=135780 cpu_user_ms=11405.750 cpu_sys_ms=11.255 rss_kb=608 challenge=32 sig=7856 +pid=678 status=OK elapsed_ms=135784 cpu_user_ms=11397.610 cpu_sys_ms=18.690 rss_kb=608 challenge=32 sig=7856 +pid=676 status=OK elapsed_ms=135789 cpu_user_ms=11412.538 cpu_sys_ms=3.739 rss_kb=608 challenge=32 sig=7856 +pid=680 status=OK elapsed_ms=135792 cpu_user_ms=11402.865 cpu_sys_ms=15.029 rss_kb=608 challenge=32 sig=7856 +pid=672 status=OK elapsed_ms=135798 cpu_user_ms=11414.261 cpu_sys_ms=3.770 rss_kb=608 challenge=32 sig=7856 +pid=673 status=OK elapsed_ms=135803 cpu_user_ms=11404.565 cpu_sys_ms=14.960 rss_kb=608 challenge=32 sig=7856 +pid=674 status=OK elapsed_ms=135807 cpu_user_ms=11406.444 cpu_sys_ms=14.976 rss_kb=608 challenge=32 sig=7856 +pid=867 status=OK elapsed_ms=136365 cpu_user_ms=11434.959 cpu_sys_ms=11.291 rss_kb=608 challenge=32 sig=7856 +pid=869 status=OK elapsed_ms=136365 cpu_user_ms=11437.605 cpu_sys_ms=11.243 rss_kb=608 challenge=32 sig=7856 +pid=874 status=OK elapsed_ms=136379 cpu_user_ms=11444.566 cpu_sys_ms=3.759 rss_kb=608 challenge=32 sig=7856 +pid=866 status=OK elapsed_ms=136377 cpu_user_ms=11418.123 cpu_sys_ms=30.008 rss_kb=608 challenge=32 sig=7856 +pid=870 status=OK elapsed_ms=136391 cpu_user_ms=11445.883 cpu_sys_ms=7.464 rss_kb=608 challenge=32 sig=7856 +pid=873 status=OK elapsed_ms=136390 cpu_user_ms=11443.612 cpu_sys_ms=7.473 rss_kb=608 challenge=32 sig=7856 +pid=871 status=OK elapsed_ms=136398 cpu_user_ms=11428.109 cpu_sys_ms=22.457 rss_kb=608 challenge=32 sig=7856 +pid=868 status=OK elapsed_ms=136380 cpu_user_ms=11441.525 cpu_sys_ms=7.507 rss_kb=608 challenge=32 sig=7856 +pid=875 status=OK elapsed_ms=136405 cpu_user_ms=11443.432 cpu_sys_ms=7.455 rss_kb=608 challenge=32 sig=7856 +pid=872 status=OK elapsed_ms=136401 cpu_user_ms=11430.889 cpu_sys_ms=22.329 rss_kb=608 challenge=32 sig=7856 +pid=1068 status=OK elapsed_ms=136129 cpu_user_ms=11428.479 cpu_sys_ms=7.505 rss_kb=608 challenge=32 sig=7856 +pid=1067 status=OK elapsed_ms=136134 cpu_user_ms=11432.769 cpu_sys_ms=7.452 rss_kb=608 challenge=32 sig=7856 +pid=1062 status=OK elapsed_ms=136159 cpu_user_ms=11425.880 cpu_sys_ms=14.929 rss_kb=608 challenge=32 sig=7856 +pid=1063 status=OK elapsed_ms=136140 cpu_user_ms=11435.232 cpu_sys_ms=3.725 rss_kb=608 challenge=32 sig=7856 +pid=1066 status=OK elapsed_ms=136149 cpu_user_ms=11422.194 cpu_sys_ms=15.072 rss_kb=608 challenge=32 sig=7856 +pid=1065 status=OK elapsed_ms=136140 cpu_user_ms=11425.462 cpu_sys_ms=11.217 rss_kb=608 challenge=32 sig=7856 +pid=1060 status=OK elapsed_ms=136158 cpu_user_ms=11425.130 cpu_sys_ms=14.901 rss_kb=608 challenge=32 sig=7856 +pid=1061 status=OK elapsed_ms=136162 cpu_user_ms=11433.921 cpu_sys_ms=7.483 rss_kb=608 challenge=32 sig=7856 +pid=1069 status=OK elapsed_ms=136171 cpu_user_ms=11427.481 cpu_sys_ms=14.898 rss_kb=608 challenge=32 sig=7856 +pid=1064 status=OK elapsed_ms=136199 cpu_user_ms=11433.817 cpu_sys_ms=11.239 rss_kb=608 challenge=32 sig=7856 +pid=1266 status=OK elapsed_ms=135762 cpu_user_ms=11426.816 cpu_sys_ms=7.485 rss_kb=608 challenge=32 sig=7856 +pid=1265 status=OK elapsed_ms=135929 cpu_user_ms=11410.406 cpu_sys_ms=15.073 rss_kb=608 challenge=32 sig=7856 +pid=1260 status=OK elapsed_ms=135958 cpu_user_ms=11422.927 cpu_sys_ms=7.469 rss_kb=608 challenge=32 sig=7856 +pid=1261 status=OK elapsed_ms=135959 cpu_user_ms=11415.571 cpu_sys_ms=15.004 rss_kb=608 challenge=32 sig=7856 +pid=1262 status=OK elapsed_ms=135961 cpu_user_ms=11415.729 cpu_sys_ms=14.922 rss_kb=608 challenge=32 sig=7856 +pid=1267 status=OK elapsed_ms=135967 cpu_user_ms=11427.744 cpu_sys_ms=3.762 rss_kb=608 challenge=32 sig=7856 +pid=1264 status=OK elapsed_ms=135967 cpu_user_ms=11427.369 cpu_sys_ms=3.767 rss_kb=608 challenge=32 sig=7856 +pid=1263 status=OK elapsed_ms=135972 cpu_user_ms=11420.667 cpu_sys_ms=11.200 rss_kb=608 challenge=32 sig=7856 +pid=1259 status=OK elapsed_ms=135983 cpu_user_ms=11422.881 cpu_sys_ms=11.156 rss_kb=608 challenge=32 sig=7856 +pid=1268 status=OK elapsed_ms=135980 cpu_user_ms=11408.857 cpu_sys_ms=26.201 rss_kb=608 challenge=32 sig=7856 +pid=1459 status=OK elapsed_ms=135337 cpu_user_ms=11382.209 cpu_sys_ms=3.761 rss_kb=608 challenge=32 sig=7856 +pid=1454 status=OK elapsed_ms=135347 cpu_user_ms=11374.521 cpu_sys_ms=11.338 rss_kb=608 challenge=32 sig=7856 +pid=1452 status=OK elapsed_ms=135354 cpu_user_ms=11385.174 cpu_sys_ms=3.738 rss_kb=608 challenge=32 sig=7856 +pid=1460 status=OK elapsed_ms=135363 cpu_user_ms=11381.337 cpu_sys_ms=7.513 rss_kb=608 challenge=32 sig=7856 +pid=1461 status=OK elapsed_ms=135364 cpu_user_ms=11382.049 cpu_sys_ms=7.439 rss_kb=608 challenge=32 sig=7856 +pid=1458 status=OK elapsed_ms=135360 cpu_user_ms=11381.735 cpu_sys_ms=7.471 rss_kb=608 challenge=32 sig=7856 +pid=1456 status=OK elapsed_ms=135368 cpu_user_ms=11380.766 cpu_sys_ms=7.480 rss_kb=608 challenge=32 sig=7856 +pid=1455 status=OK elapsed_ms=135370 cpu_user_ms=11373.858 cpu_sys_ms=14.922 rss_kb=608 challenge=32 sig=7856 +pid=1457 status=OK elapsed_ms=135375 cpu_user_ms=11377.364 cpu_sys_ms=15.001 rss_kb=608 challenge=32 sig=7856 +pid=1453 status=OK elapsed_ms=135389 cpu_user_ms=11386.574 cpu_sys_ms=7.470 rss_kb=608 challenge=32 sig=7856 + +sha2-192s simple +log: +pid=2770 status=OK elapsed_ms=292922 cpu_user_ms=24655.677 cpu_sys_ms=15.004 rss_kb=620 challenge=32 sig=16224 +pid=2769 status=OK elapsed_ms=292931 cpu_user_ms=24636.819 cpu_sys_ms=26.217 rss_kb=620 challenge=32 sig=16224 +pid=2775 status=OK elapsed_ms=292951 cpu_user_ms=24658.942 cpu_sys_ms=7.469 rss_kb=620 challenge=32 sig=16224 +pid=2774 status=OK elapsed_ms=292965 cpu_user_ms=24647.079 cpu_sys_ms=22.449 rss_kb=620 challenge=32 sig=16224 +pid=2772 status=OK elapsed_ms=292977 cpu_user_ms=24650.982 cpu_sys_ms=18.605 rss_kb=620 challenge=32 sig=16224 +pid=2771 status=OK elapsed_ms=292954 cpu_user_ms=24649.723 cpu_sys_ms=18.708 rss_kb=620 challenge=32 sig=16224 +pid=2773 status=OK elapsed_ms=292980 cpu_user_ms=24652.003 cpu_sys_ms=18.726 rss_kb=620 challenge=32 sig=16224 +pid=2777 status=OK elapsed_ms=292985 cpu_user_ms=24653.675 cpu_sys_ms=18.620 rss_kb=620 challenge=32 sig=16224 +pid=2776 status=OK elapsed_ms=292987 cpu_user_ms=24648.252 cpu_sys_ms=22.387 rss_kb=620 challenge=32 sig=16224 +pid=2768 status=OK elapsed_ms=292989 cpu_user_ms=24644.101 cpu_sys_ms=29.849 rss_kb=620 challenge=32 sig=16224 +pid=3544 status=OK elapsed_ms=43810 cpu_user_ms=26622.468 cpu_sys_ms=18.635 rss_kb=2368 challenge=32 sig=16224 +pid=1879 status=OK elapsed_ms=314371 cpu_user_ms=26355.509 cpu_sys_ms=30.006 rss_kb=620 challenge=32 sig=16224 +pid=1878 status=OK elapsed_ms=314397 cpu_user_ms=26359.537 cpu_sys_ms=26.050 rss_kb=620 challenge=32 sig=16224 +pid=1880 status=OK elapsed_ms=314414 cpu_user_ms=26362.978 cpu_sys_ms=26.120 rss_kb=620 challenge=32 sig=16224 +pid=1881 status=OK elapsed_ms=314442 cpu_user_ms=26357.837 cpu_sys_ms=33.620 rss_kb=620 challenge=32 sig=16224 +pid=1885 status=OK elapsed_ms=314443 cpu_user_ms=26368.984 cpu_sys_ms=22.243 rss_kb=620 challenge=32 sig=16224 +pid=1876 status=OK elapsed_ms=314422 cpu_user_ms=26369.189 cpu_sys_ms=22.318 rss_kb=620 challenge=32 sig=16224 +pid=1877 status=OK elapsed_ms=314454 cpu_user_ms=26368.773 cpu_sys_ms=26.171 rss_kb=620 challenge=32 sig=16224 +pid=1882 status=OK elapsed_ms=314465 cpu_user_ms=26361.046 cpu_sys_ms=33.661 rss_kb=620 challenge=32 sig=16224 +pid=1883 status=OK elapsed_ms=314469 cpu_user_ms=26371.831 cpu_sys_ms=26.011 rss_kb=620 challenge=32 sig=16224 +pid=1884 status=OK elapsed_ms=314471 cpu_user_ms=26382.447 cpu_sys_ms=14.920 rss_kb=620 challenge=32 sig=16224 +pid=2563 status=OK elapsed_ms=311907 cpu_user_ms=26225.240 cpu_sys_ms=22.338 rss_kb=620 challenge=32 sig=16224 +pid=2567 status=OK elapsed_ms=312027 cpu_user_ms=26214.050 cpu_sys_ms=40.994 rss_kb=620 challenge=32 sig=16224 +pid=2566 status=OK elapsed_ms=312088 cpu_user_ms=26246.558 cpu_sys_ms=14.935 rss_kb=620 challenge=32 sig=16224 +pid=2562 status=OK elapsed_ms=312098 cpu_user_ms=26227.535 cpu_sys_ms=33.599 rss_kb=620 challenge=32 sig=16224 +pid=2564 status=OK elapsed_ms=312101 cpu_user_ms=26230.460 cpu_sys_ms=29.849 rss_kb=620 challenge=32 sig=16224 +pid=2560 status=OK elapsed_ms=312112 cpu_user_ms=26232.539 cpu_sys_ms=29.839 rss_kb=620 challenge=32 sig=16224 +pid=2561 status=OK elapsed_ms=312116 cpu_user_ms=26236.274 cpu_sys_ms=26.193 rss_kb=620 challenge=32 sig=16224 +pid=2558 status=OK elapsed_ms=312125 cpu_user_ms=26209.879 cpu_sys_ms=52.005 rss_kb=620 challenge=32 sig=16224 +pid=2565 status=OK elapsed_ms=312114 cpu_user_ms=26237.775 cpu_sys_ms=29.771 rss_kb=620 challenge=32 sig=16224 +pid=2559 status=OK elapsed_ms=312166 cpu_user_ms=26240.865 cpu_sys_ms=29.831 rss_kb=620 challenge=32 sig=16224 +pid=3270 status=OK elapsed_ms=313394 cpu_user_ms=26291.255 cpu_sys_ms=29.827 rss_kb=620 challenge=32 sig=16224 +pid=3267 status=OK elapsed_ms=313369 cpu_user_ms=26272.107 cpu_sys_ms=41.255 rss_kb=620 challenge=32 sig=16224 +pid=3275 status=OK elapsed_ms=313428 cpu_user_ms=26252.911 cpu_sys_ms=67.313 rss_kb=620 challenge=32 sig=16224 +pid=3268 status=OK elapsed_ms=313426 cpu_user_ms=26287.245 cpu_sys_ms=29.757 rss_kb=620 challenge=32 sig=16224 +pid=3269 status=OK elapsed_ms=313431 cpu_user_ms=26283.008 cpu_sys_ms=33.672 rss_kb=620 challenge=32 sig=16224 +pid=3272 status=OK elapsed_ms=313450 cpu_user_ms=26275.154 cpu_sys_ms=44.902 rss_kb=620 challenge=32 sig=16224 +pid=3273 status=OK elapsed_ms=313457 cpu_user_ms=26281.479 cpu_sys_ms=40.981 rss_kb=620 challenge=32 sig=16224 +pid=3276 status=OK elapsed_ms=313434 cpu_user_ms=26285.665 cpu_sys_ms=29.853 rss_kb=620 challenge=32 sig=16224 +pid=3271 status=OK elapsed_ms=313447 cpu_user_ms=26294.790 cpu_sys_ms=26.039 rss_kb=620 challenge=32 sig=16224 +pid=3274 status=OK elapsed_ms=313488 cpu_user_ms=26274.705 cpu_sys_ms=52.139 rss_kb=620 challenge=32 sig=16224 +pid=3947 status=OK elapsed_ms=313609 cpu_user_ms=26310.622 cpu_sys_ms=22.480 rss_kb=620 challenge=32 sig=16224 +pid=3951 status=OK elapsed_ms=313590 cpu_user_ms=26304.975 cpu_sys_ms=26.301 rss_kb=620 challenge=32 sig=16224 +pid=3945 status=OK elapsed_ms=313604 cpu_user_ms=26304.985 cpu_sys_ms=33.552 rss_kb=620 challenge=32 sig=16224 +pid=3950 status=OK elapsed_ms=313607 cpu_user_ms=26324.766 cpu_sys_ms=11.200 rss_kb=620 challenge=32 sig=16224 +pid=3949 status=OK elapsed_ms=313669 cpu_user_ms=26308.677 cpu_sys_ms=29.695 rss_kb=620 challenge=32 sig=16224 +pid=3948 status=OK elapsed_ms=313660 cpu_user_ms=26331.199 cpu_sys_ms=7.509 rss_kb=620 challenge=32 sig=16224 +pid=3944 status=OK elapsed_ms=313645 cpu_user_ms=26311.567 cpu_sys_ms=26.085 rss_kb=620 challenge=32 sig=16224 +pid=3942 status=OK elapsed_ms=313664 cpu_user_ms=26315.548 cpu_sys_ms=26.073 rss_kb=620 challenge=32 sig=16224 +pid=3943 status=OK elapsed_ms=313672 cpu_user_ms=26309.245 cpu_sys_ms=33.715 rss_kb=620 challenge=32 sig=16224 +pid=3946 status=OK elapsed_ms=313676 cpu_user_ms=26305.242 cpu_sys_ms=40.849 rss_kb=620 challenge=32 sig=16224 +pid=824 status=OK elapsed_ms=313080 cpu_user_ms=26249.416 cpu_sys_ms=37.044 rss_kb=620 challenge=32 sig=16224 +pid=823 status=OK elapsed_ms=313111 cpu_user_ms=26264.467 cpu_sys_ms=26.027 rss_kb=620 challenge=32 sig=16224 +pid=819 status=OK elapsed_ms=313145 cpu_user_ms=26262.177 cpu_sys_ms=29.808 rss_kb=620 challenge=32 sig=16224 +pid=821 status=OK elapsed_ms=313149 cpu_user_ms=26273.457 cpu_sys_ms=18.631 rss_kb=620 challenge=32 sig=16224 +pid=822 status=OK elapsed_ms=313158 cpu_user_ms=26263.841 cpu_sys_ms=30.006 rss_kb=620 challenge=32 sig=16224 +pid=820 status=OK elapsed_ms=313178 cpu_user_ms=26265.597 cpu_sys_ms=29.704 rss_kb=620 challenge=32 sig=16224 +pid=817 status=OK elapsed_ms=313160 cpu_user_ms=26268.313 cpu_sys_ms=26.171 rss_kb=620 challenge=32 sig=16224 +pid=825 status=OK elapsed_ms=313171 cpu_user_ms=26253.191 cpu_sys_ms=41.196 rss_kb=620 challenge=32 sig=16224 +pid=816 status=OK elapsed_ms=313179 cpu_user_ms=26252.191 cpu_sys_ms=48.305 rss_kb=620 challenge=32 sig=16224 +pid=818 status=OK elapsed_ms=313206 cpu_user_ms=26289.509 cpu_sys_ms=15.049 rss_kb=620 challenge=32 sig=16224 +pid=1491 status=OK elapsed_ms=312849 cpu_user_ms=26225.840 cpu_sys_ms=33.690 rss_kb=620 challenge=32 sig=16224 +pid=1492 status=OK elapsed_ms=312963 cpu_user_ms=26223.952 cpu_sys_ms=44.722 rss_kb=620 challenge=32 sig=16224 +pid=1490 status=OK elapsed_ms=312964 cpu_user_ms=26237.667 cpu_sys_ms=29.839 rss_kb=620 challenge=32 sig=16224 +pid=1497 status=OK elapsed_ms=312969 cpu_user_ms=26223.394 cpu_sys_ms=44.660 rss_kb=620 challenge=32 sig=16224 +pid=1489 status=OK elapsed_ms=312972 cpu_user_ms=26241.985 cpu_sys_ms=29.703 rss_kb=620 challenge=32 sig=16224 +pid=1488 status=OK elapsed_ms=312990 cpu_user_ms=26241.265 cpu_sys_ms=29.838 rss_kb=620 challenge=32 sig=16224 +pid=1493 status=OK elapsed_ms=313011 cpu_user_ms=26230.158 cpu_sys_ms=45.085 rss_kb=620 challenge=32 sig=16224 +pid=1495 status=OK elapsed_ms=313002 cpu_user_ms=26251.587 cpu_sys_ms=22.302 rss_kb=620 challenge=32 sig=16224 +pid=1494 status=OK elapsed_ms=313039 cpu_user_ms=26233.139 cpu_sys_ms=44.548 rss_kb=620 challenge=32 sig=16224 +pid=1496 status=OK elapsed_ms=313054 cpu_user_ms=26229.657 cpu_sys_ms=48.399 rss_kb=620 challenge=32 sig=16224 +pid=2165 status=OK elapsed_ms=313136 cpu_user_ms=26255.599 cpu_sys_ms=41.113 rss_kb=620 challenge=32 sig=16224 +pid=2163 status=OK elapsed_ms=313122 cpu_user_ms=26266.762 cpu_sys_ms=29.869 rss_kb=620 challenge=32 sig=16224 +pid=2160 status=OK elapsed_ms=313172 cpu_user_ms=26261.413 cpu_sys_ms=37.553 rss_kb=620 challenge=32 sig=16224 +pid=2157 status=OK elapsed_ms=313172 cpu_user_ms=26263.249 cpu_sys_ms=37.385 rss_kb=620 challenge=32 sig=16224 +pid=2164 status=OK elapsed_ms=313180 cpu_user_ms=26244.116 cpu_sys_ms=55.854 rss_kb=620 challenge=32 sig=16224 +pid=2159 status=OK elapsed_ms=313193 cpu_user_ms=26280.943 cpu_sys_ms=22.336 rss_kb=620 challenge=32 sig=16224 +pid=2158 status=OK elapsed_ms=313226 cpu_user_ms=26271.307 cpu_sys_ms=33.710 rss_kb=620 challenge=32 sig=16224 +pid=2162 status=OK elapsed_ms=313238 cpu_user_ms=26285.665 cpu_sys_ms=22.271 rss_kb=620 challenge=32 sig=16224 +pid=2161 status=OK elapsed_ms=313254 cpu_user_ms=26287.431 cpu_sys_ms=22.289 rss_kb=620 challenge=32 sig=16224 +pid=2156 status=OK elapsed_ms=313269 cpu_user_ms=26267.682 cpu_sys_ms=44.616 rss_kb=620 challenge=32 sig=16224 +pid=2836 status=OK elapsed_ms=312749 cpu_user_ms=26185.749 cpu_sys_ms=59.277 rss_kb=620 challenge=32 sig=16224 +pid=2837 status=OK elapsed_ms=312781 cpu_user_ms=26207.408 cpu_sys_ms=37.371 rss_kb=620 challenge=32 sig=16224 +pid=2838 status=OK elapsed_ms=312764 cpu_user_ms=26208.216 cpu_sys_ms=37.409 rss_kb=620 challenge=32 sig=16224 +pid=2835 status=OK elapsed_ms=312846 cpu_user_ms=26219.147 cpu_sys_ms=33.580 rss_kb=620 challenge=32 sig=16224 +pid=2831 status=OK elapsed_ms=312829 cpu_user_ms=26212.232 cpu_sys_ms=37.237 rss_kb=620 challenge=32 sig=16224 +pid=2834 status=OK elapsed_ms=312865 cpu_user_ms=26231.204 cpu_sys_ms=22.337 rss_kb=620 challenge=32 sig=16224 +pid=2840 status=OK elapsed_ms=312867 cpu_user_ms=26234.754 cpu_sys_ms=22.346 rss_kb=620 challenge=32 sig=16224 +pid=2832 status=OK elapsed_ms=312862 cpu_user_ms=26227.927 cpu_sys_ms=26.092 rss_kb=620 challenge=32 sig=16224 +pid=2833 status=OK elapsed_ms=312879 cpu_user_ms=26218.710 cpu_sys_ms=40.854 rss_kb=620 challenge=32 sig=16224 +pid=2839 status=OK elapsed_ms=312877 cpu_user_ms=26237.278 cpu_sys_ms=22.386 rss_kb=620 challenge=32 sig=16224 +pid=3507 status=OK elapsed_ms=315045 cpu_user_ms=26378.608 cpu_sys_ms=26.091 rss_kb=620 challenge=32 sig=16224 +pid=3503 status=OK elapsed_ms=315115 cpu_user_ms=26401.104 cpu_sys_ms=14.903 rss_kb=620 challenge=32 sig=16224 +pid=3506 status=OK elapsed_ms=315122 cpu_user_ms=26381.063 cpu_sys_ms=37.271 rss_kb=620 challenge=32 sig=16224 +pid=3501 status=OK elapsed_ms=315146 cpu_user_ms=26375.723 cpu_sys_ms=41.098 rss_kb=620 challenge=32 sig=16224 +pid=3508 status=OK elapsed_ms=315164 cpu_user_ms=26399.177 cpu_sys_ms=22.379 rss_kb=620 challenge=32 sig=16224 +pid=3505 status=OK elapsed_ms=315152 cpu_user_ms=26375.545 cpu_sys_ms=41.169 rss_kb=620 challenge=32 sig=16224 +pid=3502 status=OK elapsed_ms=315186 cpu_user_ms=26389.350 cpu_sys_ms=33.583 rss_kb=620 challenge=32 sig=16224 +pid=3500 status=OK elapsed_ms=315180 cpu_user_ms=26367.568 cpu_sys_ms=52.338 rss_kb=620 challenge=32 sig=16224 +pid=3504 status=OK elapsed_ms=315188 cpu_user_ms=26385.968 cpu_sys_ms=33.423 rss_kb=620 challenge=32 sig=16224 +pid=3499 status=OK elapsed_ms=315184 cpu_user_ms=26411.009 cpu_sys_ms=11.187 rss_kb=620 challenge=32 sig=16224 +pid=382 status=OK elapsed_ms=313253 cpu_user_ms=26255.518 cpu_sys_ms=33.497 rss_kb=620 challenge=32 sig=16224 +pid=380 status=OK elapsed_ms=313263 cpu_user_ms=26246.687 cpu_sys_ms=41.145 rss_kb=620 challenge=32 sig=16224 +pid=384 status=OK elapsed_ms=313417 cpu_user_ms=26245.380 cpu_sys_ms=55.723 rss_kb=620 challenge=32 sig=16224 +pid=381 status=OK elapsed_ms=313438 cpu_user_ms=26286.514 cpu_sys_ms=14.987 rss_kb=620 challenge=32 sig=16224 +pid=378 status=OK elapsed_ms=313426 cpu_user_ms=26262.358 cpu_sys_ms=37.109 rss_kb=620 challenge=32 sig=16224 +pid=383 status=OK elapsed_ms=313449 cpu_user_ms=26279.010 cpu_sys_ms=25.949 rss_kb=620 challenge=32 sig=16224 +pid=387 status=OK elapsed_ms=313435 cpu_user_ms=26260.840 cpu_sys_ms=41.025 rss_kb=620 challenge=32 sig=16224 +pid=379 status=OK elapsed_ms=313460 cpu_user_ms=26266.765 cpu_sys_ms=37.338 rss_kb=620 challenge=32 sig=16224 +pid=385 status=OK elapsed_ms=313466 cpu_user_ms=26269.660 cpu_sys_ms=33.759 rss_kb=620 challenge=32 sig=16224 +pid=377 status=OK elapsed_ms=313460 cpu_user_ms=26277.326 cpu_sys_ms=26.161 rss_kb=620 challenge=32 sig=16224 +sha2-256s simple +log: +pid=1258 status=OK elapsed_ms=295854 cpu_user_ms=24837.537 cpu_sys_ms=26.131 rss_kb=568 challenge=32 sig=29792 +pid=1257 status=OK elapsed_ms=295863 cpu_user_ms=24820.793 cpu_sys_ms=44.735 rss_kb=568 challenge=32 sig=29792 +pid=1263 status=OK elapsed_ms=295849 cpu_user_ms=24824.440 cpu_sys_ms=37.479 rss_kb=568 challenge=32 sig=29792 +pid=1255 status=OK elapsed_ms=295867 cpu_user_ms=24857.979 cpu_sys_ms=7.484 rss_kb=568 challenge=32 sig=29792 +pid=1259 status=OK elapsed_ms=295867 cpu_user_ms=24828.861 cpu_sys_ms=37.063 rss_kb=568 challenge=32 sig=29792 +pid=1260 status=OK elapsed_ms=295861 cpu_user_ms=24826.822 cpu_sys_ms=37.372 rss_kb=568 challenge=32 sig=29792 +pid=1254 status=OK elapsed_ms=295894 cpu_user_ms=24830.413 cpu_sys_ms=37.232 rss_kb=568 challenge=32 sig=29792 +pid=1261 status=OK elapsed_ms=295916 cpu_user_ms=24830.596 cpu_sys_ms=44.634 rss_kb=568 challenge=32 sig=29792 +pid=1256 status=OK elapsed_ms=295928 cpu_user_ms=24857.336 cpu_sys_ms=22.303 rss_kb=568 challenge=32 sig=29792 +pid=1262 status=OK elapsed_ms=295921 cpu_user_ms=24854.068 cpu_sys_ms=22.254 rss_kb=568 challenge=32 sig=29792 +pid=1670 status=OK elapsed_ms=295114 cpu_user_ms=24777.069 cpu_sys_ms=18.652 rss_kb=568 challenge=32 sig=29792 +pid=1673 status=OK elapsed_ms=295114 cpu_user_ms=24762.074 cpu_sys_ms=33.651 rss_kb=568 challenge=32 sig=29792 +pid=1666 status=OK elapsed_ms=295118 cpu_user_ms=24760.004 cpu_sys_ms=37.252 rss_kb=568 challenge=32 sig=29792 +pid=1669 status=OK elapsed_ms=295184 cpu_user_ms=24753.042 cpu_sys_ms=52.245 rss_kb=568 challenge=32 sig=29792 +pid=1665 status=OK elapsed_ms=295187 cpu_user_ms=24785.910 cpu_sys_ms=18.685 rss_kb=568 challenge=32 sig=29792 +pid=1668 status=OK elapsed_ms=295192 cpu_user_ms=24782.133 cpu_sys_ms=22.329 rss_kb=568 challenge=32 sig=29792 +pid=1672 status=OK elapsed_ms=295196 cpu_user_ms=24781.781 cpu_sys_ms=22.320 rss_kb=568 challenge=32 sig=29792 +pid=1671 status=OK elapsed_ms=295230 cpu_user_ms=24788.939 cpu_sys_ms=18.680 rss_kb=568 challenge=32 sig=29792 +pid=1664 status=OK elapsed_ms=295235 cpu_user_ms=24777.855 cpu_sys_ms=33.720 rss_kb=568 challenge=32 sig=29792 +pid=1667 status=OK elapsed_ms=295266 cpu_user_ms=24796.081 cpu_sys_ms=18.626 rss_kb=568 challenge=32 sig=29792 +pid=2080 status=OK elapsed_ms=296369 cpu_user_ms=24840.438 cpu_sys_ms=41.064 rss_kb=568 challenge=32 sig=29792 +pid=2081 status=OK elapsed_ms=296463 cpu_user_ms=24875.533 cpu_sys_ms=14.946 rss_kb=568 challenge=32 sig=29792 +pid=2078 status=OK elapsed_ms=296448 cpu_user_ms=24870.926 cpu_sys_ms=18.685 rss_kb=568 challenge=32 sig=29792 +pid=2075 status=OK elapsed_ms=296509 cpu_user_ms=24851.468 cpu_sys_ms=41.226 rss_kb=568 challenge=32 sig=29792 +pid=2073 status=OK elapsed_ms=296538 cpu_user_ms=24860.155 cpu_sys_ms=33.579 rss_kb=568 challenge=32 sig=29792 +pid=2079 status=OK elapsed_ms=296543 cpu_user_ms=24859.027 cpu_sys_ms=37.337 rss_kb=568 challenge=32 sig=29792 +pid=2076 status=OK elapsed_ms=296555 cpu_user_ms=24841.552 cpu_sys_ms=55.997 rss_kb=568 challenge=32 sig=29792 +pid=2077 status=OK elapsed_ms=296583 cpu_user_ms=24873.805 cpu_sys_ms=26.049 rss_kb=568 challenge=32 sig=29792 +pid=2074 status=OK elapsed_ms=296615 cpu_user_ms=24897.455 cpu_sys_ms=7.517 rss_kb=568 challenge=32 sig=29792 +pid=2072 status=OK elapsed_ms=296624 cpu_user_ms=24884.028 cpu_sys_ms=22.328 rss_kb=568 challenge=32 sig=29792 +pid=2491 status=OK elapsed_ms=296494 cpu_user_ms=24848.304 cpu_sys_ms=48.475 rss_kb=568 challenge=32 sig=29792 +pid=2487 status=OK elapsed_ms=296528 cpu_user_ms=24861.696 cpu_sys_ms=37.374 rss_kb=568 challenge=32 sig=29792 +pid=2483 status=OK elapsed_ms=296554 cpu_user_ms=24862.184 cpu_sys_ms=37.330 rss_kb=568 challenge=32 sig=29792 +pid=2488 status=OK elapsed_ms=296616 cpu_user_ms=24869.333 cpu_sys_ms=41.174 rss_kb=568 challenge=32 sig=29792 +pid=2486 status=OK elapsed_ms=296662 cpu_user_ms=24872.450 cpu_sys_ms=37.396 rss_kb=568 challenge=32 sig=29792 +pid=2485 status=OK elapsed_ms=296678 cpu_user_ms=24872.943 cpu_sys_ms=40.926 rss_kb=568 challenge=32 sig=29792 +pid=2482 status=OK elapsed_ms=296679 cpu_user_ms=24879.872 cpu_sys_ms=33.472 rss_kb=568 challenge=32 sig=29792 +pid=2484 status=OK elapsed_ms=296695 cpu_user_ms=24870.298 cpu_sys_ms=44.657 rss_kb=568 challenge=32 sig=29792 +pid=2490 status=OK elapsed_ms=296723 cpu_user_ms=24877.925 cpu_sys_ms=40.897 rss_kb=568 challenge=32 sig=29792 +pid=2489 status=OK elapsed_ms=296745 cpu_user_ms=24885.151 cpu_sys_ms=40.960 rss_kb=568 challenge=32 sig=29792 +pid=2895 status=OK elapsed_ms=295134 cpu_user_ms=24749.258 cpu_sys_ms=52.245 rss_kb=568 challenge=32 sig=29792 +pid=2899 status=OK elapsed_ms=295139 cpu_user_ms=24780.336 cpu_sys_ms=22.450 rss_kb=568 challenge=32 sig=29792 +pid=2898 status=OK elapsed_ms=295152 cpu_user_ms=24778.055 cpu_sys_ms=26.184 rss_kb=568 challenge=32 sig=29792 +pid=2900 status=OK elapsed_ms=295212 cpu_user_ms=24770.266 cpu_sys_ms=37.237 rss_kb=568 challenge=32 sig=29792 +pid=2894 status=OK elapsed_ms=295228 cpu_user_ms=24770.462 cpu_sys_ms=40.850 rss_kb=568 challenge=32 sig=29792 +pid=2893 status=OK elapsed_ms=295244 cpu_user_ms=24772.133 cpu_sys_ms=41.130 rss_kb=568 challenge=32 sig=29792 +pid=2902 status=OK elapsed_ms=295252 cpu_user_ms=24784.988 cpu_sys_ms=29.734 rss_kb=568 challenge=32 sig=29792 +pid=2901 status=OK elapsed_ms=295260 cpu_user_ms=24762.220 cpu_sys_ms=51.780 rss_kb=568 challenge=32 sig=29792 +pid=2897 status=OK elapsed_ms=295278 cpu_user_ms=24799.589 cpu_sys_ms=18.671 rss_kb=568 challenge=32 sig=29792 +pid=2896 status=OK elapsed_ms=295295 cpu_user_ms=24779.145 cpu_sys_ms=41.026 rss_kb=568 challenge=32 sig=29792 +pid=3308 status=OK elapsed_ms=295587 cpu_user_ms=24798.869 cpu_sys_ms=18.749 rss_kb=568 challenge=32 sig=29792 +pid=3309 status=OK elapsed_ms=295639 cpu_user_ms=24788.014 cpu_sys_ms=33.778 rss_kb=568 challenge=32 sig=29792 +pid=3302 status=OK elapsed_ms=295639 cpu_user_ms=24773.492 cpu_sys_ms=48.359 rss_kb=568 challenge=32 sig=29792 +pid=3304 status=OK elapsed_ms=295660 cpu_user_ms=24788.819 cpu_sys_ms=37.470 rss_kb=568 challenge=32 sig=29792 +pid=3306 status=OK elapsed_ms=295611 cpu_user_ms=24793.484 cpu_sys_ms=29.986 rss_kb=568 challenge=32 sig=29792 +pid=3310 status=OK elapsed_ms=295673 cpu_user_ms=24795.079 cpu_sys_ms=29.779 rss_kb=568 challenge=32 sig=29792 +pid=3307 status=OK elapsed_ms=295689 cpu_user_ms=24777.669 cpu_sys_ms=48.397 rss_kb=568 challenge=32 sig=29792 +pid=3303 status=OK elapsed_ms=295695 cpu_user_ms=24803.289 cpu_sys_ms=24.285 rss_kb=568 challenge=32 sig=29792 +pid=3305 status=OK elapsed_ms=295712 cpu_user_ms=24810.706 cpu_sys_ms=22.434 rss_kb=568 challenge=32 sig=29792 +pid=3311 status=OK elapsed_ms=295725 cpu_user_ms=24804.563 cpu_sys_ms=29.880 rss_kb=568 challenge=32 sig=29792 +pid=3712 status=OK elapsed_ms=296183 cpu_user_ms=24819.436 cpu_sys_ms=52.477 rss_kb=568 challenge=32 sig=29792 +pid=3718 status=OK elapsed_ms=296198 cpu_user_ms=24862.467 cpu_sys_ms=11.208 rss_kb=568 challenge=32 sig=29792 +pid=3711 status=OK elapsed_ms=296198 cpu_user_ms=24828.777 cpu_sys_ms=44.512 rss_kb=568 challenge=32 sig=29792 +pid=3714 status=OK elapsed_ms=296233 cpu_user_ms=24839.845 cpu_sys_ms=37.490 rss_kb=568 challenge=32 sig=29792 +pid=3717 status=OK elapsed_ms=296259 cpu_user_ms=24836.510 cpu_sys_ms=44.509 rss_kb=568 challenge=32 sig=29792 +pid=3713 status=OK elapsed_ms=296263 cpu_user_ms=24878.034 cpu_sys_ms=3.736 rss_kb=568 challenge=32 sig=29792 +pid=3715 status=OK elapsed_ms=296267 cpu_user_ms=24848.060 cpu_sys_ms=33.751 rss_kb=568 challenge=32 sig=29792 +pid=3710 status=OK elapsed_ms=296267 cpu_user_ms=24856.263 cpu_sys_ms=26.205 rss_kb=568 challenge=32 sig=29792 +pid=3719 status=OK elapsed_ms=296274 cpu_user_ms=24868.928 cpu_sys_ms=14.920 rss_kb=568 challenge=32 sig=29792 +pid=3716 status=OK elapsed_ms=296280 cpu_user_ms=24852.204 cpu_sys_ms=33.563 rss_kb=568 challenge=32 sig=29792 +pid=331 status=OK elapsed_ms=296105 cpu_user_ms=24816.172 cpu_sys_ms=37.172 rss_kb=568 challenge=32 sig=29792 +pid=332 status=OK elapsed_ms=296124 cpu_user_ms=24810.421 cpu_sys_ms=44.959 rss_kb=568 challenge=32 sig=29792 +pid=327 status=OK elapsed_ms=296178 cpu_user_ms=24841.516 cpu_sys_ms=18.734 rss_kb=568 challenge=32 sig=29792 +pid=328 status=OK elapsed_ms=296288 cpu_user_ms=24839.079 cpu_sys_ms=29.729 rss_kb=568 challenge=32 sig=29792 +pid=325 status=OK elapsed_ms=296317 cpu_user_ms=24833.799 cpu_sys_ms=37.369 rss_kb=568 challenge=32 sig=29792 +pid=324 status=OK elapsed_ms=296322 cpu_user_ms=24820.681 cpu_sys_ms=48.347 rss_kb=568 challenge=32 sig=29792 +pid=333 status=OK elapsed_ms=296325 cpu_user_ms=24824.733 cpu_sys_ms=44.715 rss_kb=568 challenge=32 sig=29792 +pid=326 status=OK elapsed_ms=296335 cpu_user_ms=24831.030 cpu_sys_ms=40.942 rss_kb=568 challenge=32 sig=29792 +pid=329 status=OK elapsed_ms=296359 cpu_user_ms=24834.221 cpu_sys_ms=41.060 rss_kb=568 challenge=32 sig=29792 +pid=334 status=OK elapsed_ms=296381 cpu_user_ms=24850.250 cpu_sys_ms=29.944 rss_kb=568 challenge=32 sig=29792 +pid=748 status=OK elapsed_ms=296739 cpu_user_ms=24892.377 cpu_sys_ms=22.393 rss_kb=568 challenge=32 sig=29792 +pid=740 status=OK elapsed_ms=296740 cpu_user_ms=24911.948 cpu_sys_ms=3.735 rss_kb=568 challenge=32 sig=29792 +pid=746 status=OK elapsed_ms=296784 cpu_user_ms=24892.701 cpu_sys_ms=29.988 rss_kb=568 challenge=32 sig=29792 +pid=747 status=OK elapsed_ms=296797 cpu_user_ms=24888.280 cpu_sys_ms=33.824 rss_kb=568 challenge=32 sig=29792 +pid=741 status=OK elapsed_ms=296801 cpu_user_ms=24887.953 cpu_sys_ms=33.637 rss_kb=568 challenge=32 sig=29792 +pid=744 status=OK elapsed_ms=296824 cpu_user_ms=24894.682 cpu_sys_ms=29.876 rss_kb=568 challenge=32 sig=29792 +pid=743 status=OK elapsed_ms=296814 cpu_user_ms=24869.390 cpu_sys_ms=56.020 rss_kb=568 challenge=32 sig=29792 +pid=742 status=OK elapsed_ms=296839 cpu_user_ms=24887.822 cpu_sys_ms=41.219 rss_kb=568 challenge=32 sig=29792 +pid=749 status=OK elapsed_ms=296831 cpu_user_ms=24898.714 cpu_sys_ms=29.928 rss_kb=568 challenge=32 sig=29792 +pid=745 status=OK elapsed_ms=296832 cpu_user_ms=24902.101 cpu_sys_ms=26.130 rss_kb=568 challenge=32 sig=29792 +pid=1155 status=OK elapsed_ms=296412 cpu_user_ms=24853.441 cpu_sys_ms=22.501 rss_kb=568 challenge=32 sig=29792 +pid=1151 status=OK elapsed_ms=296517 cpu_user_ms=24849.334 cpu_sys_ms=37.295 rss_kb=568 challenge=32 sig=29792 +pid=1154 status=OK elapsed_ms=296519 cpu_user_ms=24845.843 cpu_sys_ms=41.075 rss_kb=568 challenge=32 sig=29792 +pid=1160 status=OK elapsed_ms=296604 cpu_user_ms=24834.810 cpu_sys_ms=60.056 rss_kb=568 challenge=32 sig=29792 +pid=1156 status=OK elapsed_ms=296645 cpu_user_ms=24879.688 cpu_sys_ms=18.675 rss_kb=568 challenge=32 sig=29792 +pid=1158 status=OK elapsed_ms=296639 cpu_user_ms=24877.432 cpu_sys_ms=22.419 rss_kb=568 challenge=32 sig=29792 +pid=1157 status=OK elapsed_ms=296651 cpu_user_ms=24873.322 cpu_sys_ms=26.096 rss_kb=568 challenge=32 sig=29792 +pid=1153 status=OK elapsed_ms=296640 cpu_user_ms=24876.789 cpu_sys_ms=22.506 rss_kb=568 challenge=32 sig=29792 +pid=1152 status=OK elapsed_ms=296647 cpu_user_ms=24872.034 cpu_sys_ms=29.894 rss_kb=568 challenge=32 sig=29792 +pid=1159 status=OK elapsed_ms=296654 cpu_user_ms=24872.658 cpu_sys_ms=29.989 rss_kb=568 challenge=32 sig=29792 +shake-128s simple +log: +pid=3759 status=OK elapsed_ms=296682 cpu_user_ms=24965.625 cpu_sys_ms=18.742 rss_kb=512 challenge=32 sig=7856 +pid=3763 status=OK elapsed_ms=296683 cpu_user_ms=24962.095 cpu_sys_ms=22.353 rss_kb=512 challenge=32 sig=7856 +pid=3760 status=OK elapsed_ms=296702 cpu_user_ms=24960.870 cpu_sys_ms=26.290 rss_kb=512 challenge=32 sig=7856 +pid=3758 status=OK elapsed_ms=296712 cpu_user_ms=24971.079 cpu_sys_ms=18.570 rss_kb=512 challenge=32 sig=7856 +pid=3761 status=OK elapsed_ms=296728 cpu_user_ms=24984.158 cpu_sys_ms=7.469 rss_kb=512 challenge=32 sig=7856 +pid=3766 status=OK elapsed_ms=296725 cpu_user_ms=24976.559 cpu_sys_ms=7.486 rss_kb=512 challenge=32 sig=7856 +pid=3762 status=OK elapsed_ms=296743 cpu_user_ms=24979.708 cpu_sys_ms=14.873 rss_kb=512 challenge=32 sig=7856 +pid=3764 status=OK elapsed_ms=296764 cpu_user_ms=24963.533 cpu_sys_ms=25.888 rss_kb=512 challenge=32 sig=7856 +pid=3757 status=OK elapsed_ms=296751 cpu_user_ms=24957.179 cpu_sys_ms=33.514 rss_kb=512 challenge=32 sig=7856 +pid=3765 status=OK elapsed_ms=296773 cpu_user_ms=24963.656 cpu_sys_ms=29.837 rss_kb=512 challenge=32 sig=7856 +pid=371 status=OK elapsed_ms=295702 cpu_user_ms=24868.697 cpu_sys_ms=18.614 rss_kb=512 challenge=32 sig=7856 +pid=378 status=OK elapsed_ms=295721 cpu_user_ms=24865.735 cpu_sys_ms=26.125 rss_kb=512 challenge=32 sig=7856 +pid=373 status=OK elapsed_ms=295722 cpu_user_ms=24870.303 cpu_sys_ms=22.358 rss_kb=512 challenge=32 sig=7856 +pid=372 status=OK elapsed_ms=295702 cpu_user_ms=24869.578 cpu_sys_ms=22.343 rss_kb=512 challenge=32 sig=7856 +pid=374 status=OK elapsed_ms=295766 cpu_user_ms=24881.103 cpu_sys_ms=14.935 rss_kb=512 challenge=32 sig=7856 +pid=376 status=OK elapsed_ms=295728 cpu_user_ms=24876.699 cpu_sys_ms=18.584 rss_kb=512 challenge=32 sig=7856 +pid=377 status=OK elapsed_ms=295783 cpu_user_ms=24878.196 cpu_sys_ms=18.579 rss_kb=512 challenge=32 sig=7856 +pid=380 status=OK elapsed_ms=295799 cpu_user_ms=24886.349 cpu_sys_ms=14.911 rss_kb=512 challenge=32 sig=7856 +pid=379 status=OK elapsed_ms=295793 cpu_user_ms=24892.201 cpu_sys_ms=7.419 rss_kb=512 challenge=32 sig=7856 +pid=375 status=OK elapsed_ms=295815 cpu_user_ms=24869.671 cpu_sys_ms=33.560 rss_kb=512 challenge=32 sig=7856 +pid=787 status=OK elapsed_ms=296526 cpu_user_ms=24931.323 cpu_sys_ms=18.670 rss_kb=512 challenge=32 sig=7856 +pid=788 status=OK elapsed_ms=296529 cpu_user_ms=24942.923 cpu_sys_ms=7.512 rss_kb=512 challenge=32 sig=7856 +pid=792 status=OK elapsed_ms=296537 cpu_user_ms=24925.699 cpu_sys_ms=29.754 rss_kb=512 challenge=32 sig=7856 +pid=791 status=OK elapsed_ms=296543 cpu_user_ms=24929.593 cpu_sys_ms=22.321 rss_kb=512 challenge=32 sig=7856 +pid=786 status=OK elapsed_ms=296583 cpu_user_ms=24936.345 cpu_sys_ms=18.664 rss_kb=512 challenge=32 sig=7856 +pid=790 status=OK elapsed_ms=296585 cpu_user_ms=24937.074 cpu_sys_ms=18.593 rss_kb=512 challenge=32 sig=7856 +pid=789 status=OK elapsed_ms=296569 cpu_user_ms=24940.441 cpu_sys_ms=14.898 rss_kb=512 challenge=32 sig=7856 +pid=793 status=OK elapsed_ms=296598 cpu_user_ms=24940.787 cpu_sys_ms=18.506 rss_kb=512 challenge=32 sig=7856 +pid=784 status=OK elapsed_ms=296603 cpu_user_ms=24941.962 cpu_sys_ms=18.535 rss_kb=512 challenge=32 sig=7856 +pid=785 status=OK elapsed_ms=296614 cpu_user_ms=24944.962 cpu_sys_ms=14.872 rss_kb=512 challenge=32 sig=7856 +pid=1199 status=OK elapsed_ms=296049 cpu_user_ms=24874.756 cpu_sys_ms=26.070 rss_kb=512 challenge=32 sig=7856 +pid=1198 status=OK elapsed_ms=296060 cpu_user_ms=24881.418 cpu_sys_ms=18.721 rss_kb=512 challenge=32 sig=7856 +pid=1201 status=OK elapsed_ms=296076 cpu_user_ms=24885.949 cpu_sys_ms=18.608 rss_kb=512 challenge=32 sig=7856 +pid=1197 status=OK elapsed_ms=296109 cpu_user_ms=24887.918 cpu_sys_ms=18.730 rss_kb=512 challenge=32 sig=7856 +pid=1202 status=OK elapsed_ms=296114 cpu_user_ms=24886.979 cpu_sys_ms=22.306 rss_kb=512 challenge=32 sig=7856 +pid=1203 status=OK elapsed_ms=296122 cpu_user_ms=24889.756 cpu_sys_ms=18.595 rss_kb=512 challenge=32 sig=7856 +pid=1195 status=OK elapsed_ms=296104 cpu_user_ms=24893.402 cpu_sys_ms=14.878 rss_kb=512 challenge=32 sig=7856 +pid=1200 status=OK elapsed_ms=296137 cpu_user_ms=24891.329 cpu_sys_ms=18.550 rss_kb=512 challenge=32 sig=7856 +pid=1204 status=OK elapsed_ms=296150 cpu_user_ms=24900.683 cpu_sys_ms=14.976 rss_kb=512 challenge=32 sig=7856 +pid=1196 status=OK elapsed_ms=296151 cpu_user_ms=24885.346 cpu_sys_ms=29.845 rss_kb=512 challenge=32 sig=7856 +pid=1608 status=OK elapsed_ms=296083 cpu_user_ms=24871.794 cpu_sys_ms=26.173 rss_kb=512 challenge=32 sig=7856 +pid=1615 status=OK elapsed_ms=296079 cpu_user_ms=24875.154 cpu_sys_ms=22.407 rss_kb=512 challenge=32 sig=7856 +pid=1614 status=OK elapsed_ms=296100 cpu_user_ms=24872.147 cpu_sys_ms=29.718 rss_kb=512 challenge=32 sig=7856 +pid=1609 status=OK elapsed_ms=296100 cpu_user_ms=24883.421 cpu_sys_ms=18.771 rss_kb=512 challenge=32 sig=7856 +pid=1612 status=OK elapsed_ms=296108 cpu_user_ms=24875.193 cpu_sys_ms=25.994 rss_kb=512 challenge=32 sig=7856 +pid=1607 status=OK elapsed_ms=296087 cpu_user_ms=24889.255 cpu_sys_ms=11.232 rss_kb=512 challenge=32 sig=7856 +pid=1610 status=OK elapsed_ms=296137 cpu_user_ms=24899.490 cpu_sys_ms=7.448 rss_kb=512 challenge=32 sig=7856 +pid=1611 status=OK elapsed_ms=296141 cpu_user_ms=24888.586 cpu_sys_ms=18.692 rss_kb=512 challenge=32 sig=7856 +pid=1613 status=OK elapsed_ms=296132 cpu_user_ms=24879.080 cpu_sys_ms=26.035 rss_kb=512 challenge=32 sig=7856 +pid=1606 status=OK elapsed_ms=296130 cpu_user_ms=24880.293 cpu_sys_ms=26.064 rss_kb=512 challenge=32 sig=7856 +pid=2019 status=OK elapsed_ms=296630 cpu_user_ms=24917.444 cpu_sys_ms=26.056 rss_kb=512 challenge=32 sig=7856 +pid=2024 status=OK elapsed_ms=296642 cpu_user_ms=24921.221 cpu_sys_ms=22.441 rss_kb=512 challenge=32 sig=7856 +pid=2022 status=OK elapsed_ms=296647 cpu_user_ms=24919.521 cpu_sys_ms=26.075 rss_kb=512 challenge=32 sig=7856 +pid=2023 status=OK elapsed_ms=296647 cpu_user_ms=24923.855 cpu_sys_ms=22.263 rss_kb=512 challenge=32 sig=7856 +pid=2018 status=OK elapsed_ms=296674 cpu_user_ms=24934.458 cpu_sys_ms=14.896 rss_kb=512 challenge=32 sig=7856 +pid=2017 status=OK elapsed_ms=296668 cpu_user_ms=24921.700 cpu_sys_ms=22.478 rss_kb=512 challenge=32 sig=7856 +pid=2021 status=OK elapsed_ms=296699 cpu_user_ms=24944.993 cpu_sys_ms=7.421 rss_kb=512 challenge=32 sig=7856 +pid=2020 status=OK elapsed_ms=296702 cpu_user_ms=24926.487 cpu_sys_ms=26.302 rss_kb=512 challenge=32 sig=7856 +pid=2025 status=OK elapsed_ms=296717 cpu_user_ms=24921.981 cpu_sys_ms=33.325 rss_kb=512 challenge=32 sig=7856 +pid=2016 status=OK elapsed_ms=296736 cpu_user_ms=24934.561 cpu_sys_ms=25.991 rss_kb=512 challenge=32 sig=7856 +pid=2432 status=OK elapsed_ms=297258 cpu_user_ms=24944.705 cpu_sys_ms=26.133 rss_kb=512 challenge=32 sig=7856 +pid=2428 status=OK elapsed_ms=297348 cpu_user_ms=24966.728 cpu_sys_ms=11.173 rss_kb=512 challenge=32 sig=7856 +pid=2431 status=OK elapsed_ms=297363 cpu_user_ms=24950.046 cpu_sys_ms=29.760 rss_kb=512 challenge=32 sig=7856 +pid=2429 status=OK elapsed_ms=297366 cpu_user_ms=24957.593 cpu_sys_ms=22.359 rss_kb=512 challenge=32 sig=7856 +pid=2434 status=OK elapsed_ms=297357 cpu_user_ms=24964.010 cpu_sys_ms=11.189 rss_kb=512 challenge=32 sig=7856 +pid=2425 status=OK elapsed_ms=297364 cpu_user_ms=24948.549 cpu_sys_ms=26.050 rss_kb=512 challenge=32 sig=7856 +pid=2433 status=OK elapsed_ms=297382 cpu_user_ms=24958.653 cpu_sys_ms=22.326 rss_kb=512 challenge=32 sig=7856 +pid=2430 status=OK elapsed_ms=297370 cpu_user_ms=24954.372 cpu_sys_ms=25.991 rss_kb=512 challenge=32 sig=7856 +pid=2426 status=OK elapsed_ms=297385 cpu_user_ms=24955.647 cpu_sys_ms=26.100 rss_kb=512 challenge=32 sig=7856 +pid=2427 status=OK elapsed_ms=297451 cpu_user_ms=24964.536 cpu_sys_ms=22.262 rss_kb=512 challenge=32 sig=7856 +pid=2838 status=OK elapsed_ms=297543 cpu_user_ms=24946.575 cpu_sys_ms=29.885 rss_kb=512 challenge=32 sig=7856 +pid=2844 status=OK elapsed_ms=297570 cpu_user_ms=24960.280 cpu_sys_ms=18.676 rss_kb=512 challenge=32 sig=7856 +pid=2840 status=OK elapsed_ms=297583 cpu_user_ms=24948.116 cpu_sys_ms=33.412 rss_kb=512 challenge=32 sig=7856 +pid=2846 status=OK elapsed_ms=297571 cpu_user_ms=24957.320 cpu_sys_ms=22.266 rss_kb=512 challenge=32 sig=7856 +pid=2845 status=OK elapsed_ms=297587 cpu_user_ms=24958.797 cpu_sys_ms=22.334 rss_kb=512 challenge=32 sig=7856 +pid=2841 status=OK elapsed_ms=297599 cpu_user_ms=24964.829 cpu_sys_ms=18.622 rss_kb=512 challenge=32 sig=7856 +pid=2847 status=OK elapsed_ms=297599 cpu_user_ms=24955.716 cpu_sys_ms=26.044 rss_kb=512 challenge=32 sig=7856 +pid=2839 status=OK elapsed_ms=297629 cpu_user_ms=24961.436 cpu_sys_ms=29.759 rss_kb=512 challenge=32 sig=7856 +pid=2842 status=OK elapsed_ms=297633 cpu_user_ms=24968.101 cpu_sys_ms=18.525 rss_kb=512 challenge=32 sig=7856 +pid=2843 status=OK elapsed_ms=297642 cpu_user_ms=24982.777 cpu_sys_ms=11.077 rss_kb=512 challenge=32 sig=7856 +pid=3257 status=OK elapsed_ms=297539 cpu_user_ms=24967.443 cpu_sys_ms=14.934 rss_kb=512 challenge=32 sig=7856 +pid=3256 status=OK elapsed_ms=297541 cpu_user_ms=24955.220 cpu_sys_ms=29.890 rss_kb=512 challenge=32 sig=7856 +pid=3254 status=OK elapsed_ms=297568 cpu_user_ms=24963.376 cpu_sys_ms=26.108 rss_kb=512 challenge=32 sig=7856 +pid=3258 status=OK elapsed_ms=297587 cpu_user_ms=24963.888 cpu_sys_ms=26.163 rss_kb=512 challenge=32 sig=7856 +pid=3253 status=OK elapsed_ms=297613 cpu_user_ms=24970.375 cpu_sys_ms=22.321 rss_kb=512 challenge=32 sig=7856 +pid=3255 status=OK elapsed_ms=297612 cpu_user_ms=24973.888 cpu_sys_ms=18.654 rss_kb=512 challenge=32 sig=7856 +pid=3250 status=OK elapsed_ms=297600 cpu_user_ms=24988.134 cpu_sys_ms=3.706 rss_kb=512 challenge=32 sig=7856 +pid=3252 status=OK elapsed_ms=297605 cpu_user_ms=24963.870 cpu_sys_ms=29.666 rss_kb=512 challenge=32 sig=7856 +pid=3251 status=OK elapsed_ms=297621 cpu_user_ms=24981.171 cpu_sys_ms=14.903 rss_kb=512 challenge=32 sig=7856 +pid=3249 status=OK elapsed_ms=297624 cpu_user_ms=24995.948 cpu_sys_ms=0.000 rss_kb=512 challenge=32 sig=7856 +pid=3666 status=OK elapsed_ms=298104 cpu_user_ms=25014.394 cpu_sys_ms=18.575 rss_kb=512 challenge=32 sig=7856 +pid=3669 status=OK elapsed_ms=298112 cpu_user_ms=24997.774 cpu_sys_ms=33.826 rss_kb=512 challenge=32 sig=7856 +pid=3667 status=OK elapsed_ms=298139 cpu_user_ms=25033.552 cpu_sys_ms=3.739 rss_kb=512 challenge=32 sig=7856 +pid=3668 status=OK elapsed_ms=298156 cpu_user_ms=24984.959 cpu_sys_ms=52.184 rss_kb=512 challenge=32 sig=7856 +pid=3662 status=OK elapsed_ms=298147 cpu_user_ms=24991.596 cpu_sys_ms=44.564 rss_kb=512 challenge=32 sig=7856 +pid=3665 status=OK elapsed_ms=298171 cpu_user_ms=25022.526 cpu_sys_ms=14.938 rss_kb=512 challenge=32 sig=7856 +pid=3660 status=OK elapsed_ms=298177 cpu_user_ms=25025.256 cpu_sys_ms=14.965 rss_kb=512 challenge=32 sig=7856 +pid=3663 status=OK elapsed_ms=298192 cpu_user_ms=24992.117 cpu_sys_ms=48.204 rss_kb=512 challenge=32 sig=7856 +pid=3664 status=OK elapsed_ms=298196 cpu_user_ms=25019.788 cpu_sys_ms=22.306 rss_kb=512 challenge=32 sig=7856 +pid=3661 status=OK elapsed_ms=298201 cpu_user_ms=25018.279 cpu_sys_ms=29.692 rss_kb=512 challenge=32 sig=7856 +shake-192s simple +log: +pid=3166 status=OK elapsed_ms=516954 cpu_user_ms=43325.789 cpu_sys_ms=33.716 rss_kb=584 challenge=32 sig=16224 +pid=3172 status=OK elapsed_ms=517023 cpu_user_ms=43334.626 cpu_sys_ms=26.159 rss_kb=584 challenge=32 sig=16224 +pid=3171 status=OK elapsed_ms=517079 cpu_user_ms=43338.592 cpu_sys_ms=29.829 rss_kb=584 challenge=32 sig=16224 +pid=3167 status=OK elapsed_ms=517138 cpu_user_ms=43355.833 cpu_sys_ms=22.407 rss_kb=584 challenge=32 sig=16224 +pid=3168 status=OK elapsed_ms=517152 cpu_user_ms=43350.508 cpu_sys_ms=26.084 rss_kb=584 challenge=32 sig=16224 +pid=3164 status=OK elapsed_ms=517122 cpu_user_ms=43317.909 cpu_sys_ms=51.975 rss_kb=584 challenge=32 sig=16224 +pid=3165 status=OK elapsed_ms=517193 cpu_user_ms=43337.343 cpu_sys_ms=44.670 rss_kb=584 challenge=32 sig=16224 +pid=3173 status=OK elapsed_ms=517181 cpu_user_ms=43348.980 cpu_sys_ms=33.518 rss_kb=584 challenge=32 sig=16224 +pid=3169 status=OK elapsed_ms=517224 cpu_user_ms=43352.413 cpu_sys_ms=37.376 rss_kb=584 challenge=32 sig=16224 +pid=3170 status=OK elapsed_ms=517204 cpu_user_ms=43319.427 cpu_sys_ms=63.158 rss_kb=584 challenge=32 sig=16224 +pid=3877 status=OK elapsed_ms=516125 cpu_user_ms=43280.493 cpu_sys_ms=40.850 rss_kb=584 challenge=32 sig=16224 +pid=3880 status=OK elapsed_ms=517104 cpu_user_ms=43264.794 cpu_sys_ms=48.591 rss_kb=584 challenge=32 sig=16224 +pid=3873 status=OK elapsed_ms=517151 cpu_user_ms=43284.407 cpu_sys_ms=33.463 rss_kb=584 challenge=32 sig=16224 +pid=3874 status=OK elapsed_ms=517162 cpu_user_ms=43259.446 cpu_sys_ms=60.040 rss_kb=584 challenge=32 sig=16224 +pid=3875 status=OK elapsed_ms=517188 cpu_user_ms=43293.560 cpu_sys_ms=29.895 rss_kb=584 challenge=32 sig=16224 +pid=3878 status=OK elapsed_ms=517215 cpu_user_ms=43294.831 cpu_sys_ms=33.563 rss_kb=584 challenge=32 sig=16224 +pid=3879 status=OK elapsed_ms=517267 cpu_user_ms=43307.397 cpu_sys_ms=22.479 rss_kb=584 challenge=32 sig=16224 +pid=3872 status=OK elapsed_ms=517273 cpu_user_ms=43283.354 cpu_sys_ms=48.460 rss_kb=584 challenge=32 sig=16224 +pid=3871 status=OK elapsed_ms=517275 cpu_user_ms=43288.978 cpu_sys_ms=44.467 rss_kb=584 challenge=32 sig=16224 +pid=3876 status=OK elapsed_ms=517286 cpu_user_ms=43278.536 cpu_sys_ms=59.410 rss_kb=584 challenge=32 sig=16224 +pid=797 status=OK elapsed_ms=525480 cpu_user_ms=43353.405 cpu_sys_ms=55.853 rss_kb=584 challenge=32 sig=16224 +pid=795 status=OK elapsed_ms=525487 cpu_user_ms=43367.899 cpu_sys_ms=44.777 rss_kb=584 challenge=32 sig=16224 +pid=794 status=OK elapsed_ms=525529 cpu_user_ms=43358.027 cpu_sys_ms=55.890 rss_kb=584 challenge=32 sig=16224 +pid=793 status=OK elapsed_ms=525535 cpu_user_ms=43355.361 cpu_sys_ms=59.471 rss_kb=584 challenge=32 sig=16224 +pid=791 status=OK elapsed_ms=525561 cpu_user_ms=43371.923 cpu_sys_ms=44.745 rss_kb=584 challenge=32 sig=16224 +pid=789 status=OK elapsed_ms=525562 cpu_user_ms=43376.361 cpu_sys_ms=40.796 rss_kb=584 challenge=32 sig=16224 +pid=790 status=OK elapsed_ms=525566 cpu_user_ms=43387.594 cpu_sys_ms=29.843 rss_kb=584 challenge=32 sig=16224 +pid=792 status=OK elapsed_ms=525572 cpu_user_ms=43386.121 cpu_sys_ms=33.421 rss_kb=584 challenge=32 sig=16224 +pid=798 status=OK elapsed_ms=525577 cpu_user_ms=43368.103 cpu_sys_ms=51.992 rss_kb=584 challenge=32 sig=16224 +pid=796 status=OK elapsed_ms=525580 cpu_user_ms=43403.338 cpu_sys_ms=14.879 rss_kb=584 challenge=32 sig=16224 +pid=1521 status=OK elapsed_ms=517664 cpu_user_ms=43335.410 cpu_sys_ms=52.260 rss_kb=584 challenge=32 sig=16224 +pid=1524 status=OK elapsed_ms=517827 cpu_user_ms=43373.773 cpu_sys_ms=22.372 rss_kb=584 challenge=32 sig=16224 +pid=1522 status=OK elapsed_ms=517880 cpu_user_ms=43355.241 cpu_sys_ms=44.768 rss_kb=584 challenge=32 sig=16224 +pid=1525 status=OK elapsed_ms=517901 cpu_user_ms=43357.171 cpu_sys_ms=44.797 rss_kb=584 challenge=32 sig=16224 +pid=1523 status=OK elapsed_ms=517944 cpu_user_ms=43377.369 cpu_sys_ms=29.872 rss_kb=584 challenge=32 sig=16224 +pid=1527 status=OK elapsed_ms=517969 cpu_user_ms=43374.735 cpu_sys_ms=33.542 rss_kb=584 challenge=32 sig=16224 +pid=1519 status=OK elapsed_ms=517970 cpu_user_ms=43359.901 cpu_sys_ms=48.558 rss_kb=584 challenge=32 sig=16224 +pid=1520 status=OK elapsed_ms=517974 cpu_user_ms=43335.641 cpu_sys_ms=71.032 rss_kb=584 challenge=32 sig=16224 +pid=1526 status=OK elapsed_ms=518002 cpu_user_ms=43375.128 cpu_sys_ms=40.986 rss_kb=584 challenge=32 sig=16224 +pid=1528 status=OK elapsed_ms=517978 cpu_user_ms=43386.939 cpu_sys_ms=22.548 rss_kb=584 challenge=32 sig=16224 +pid=2225 status=OK elapsed_ms=518866 cpu_user_ms=43395.320 cpu_sys_ms=63.536 rss_kb=584 challenge=32 sig=16224 +pid=2224 status=OK elapsed_ms=518868 cpu_user_ms=43413.940 cpu_sys_ms=44.948 rss_kb=584 challenge=32 sig=16224 +pid=2226 status=OK elapsed_ms=518886 cpu_user_ms=43437.749 cpu_sys_ms=26.216 rss_kb=584 challenge=32 sig=16224 +pid=2228 status=OK elapsed_ms=518921 cpu_user_ms=43395.592 cpu_sys_ms=71.078 rss_kb=584 challenge=32 sig=16224 +pid=2227 status=OK elapsed_ms=518955 cpu_user_ms=43387.765 cpu_sys_ms=82.324 rss_kb=584 challenge=32 sig=16224 +pid=2223 status=OK elapsed_ms=518965 cpu_user_ms=43413.939 cpu_sys_ms=56.020 rss_kb=584 challenge=32 sig=16224 +pid=2230 status=OK elapsed_ms=518968 cpu_user_ms=43426.756 cpu_sys_ms=44.677 rss_kb=584 challenge=32 sig=16224 +pid=2231 status=OK elapsed_ms=518972 cpu_user_ms=43424.883 cpu_sys_ms=48.441 rss_kb=584 challenge=32 sig=16224 +pid=2229 status=OK elapsed_ms=518979 cpu_user_ms=43436.503 cpu_sys_ms=40.870 rss_kb=584 challenge=32 sig=16224 +pid=2232 status=OK elapsed_ms=519000 cpu_user_ms=43444.318 cpu_sys_ms=40.983 rss_kb=584 challenge=32 sig=16224 +pid=2943 status=OK elapsed_ms=517442 cpu_user_ms=43266.372 cpu_sys_ms=52.385 rss_kb=584 challenge=32 sig=16224 +pid=2941 status=OK elapsed_ms=517461 cpu_user_ms=43282.195 cpu_sys_ms=41.156 rss_kb=584 challenge=32 sig=16224 +pid=2940 status=OK elapsed_ms=517470 cpu_user_ms=43278.127 cpu_sys_ms=44.790 rss_kb=584 challenge=32 sig=16224 +pid=2938 status=OK elapsed_ms=517521 cpu_user_ms=43289.642 cpu_sys_ms=37.398 rss_kb=584 challenge=32 sig=16224 +pid=2935 status=OK elapsed_ms=517520 cpu_user_ms=43265.172 cpu_sys_ms=59.706 rss_kb=584 challenge=32 sig=16224 +pid=2939 status=OK elapsed_ms=517546 cpu_user_ms=43287.034 cpu_sys_ms=40.892 rss_kb=584 challenge=32 sig=16224 +pid=2942 status=OK elapsed_ms=517554 cpu_user_ms=43318.299 cpu_sys_ms=14.949 rss_kb=584 challenge=32 sig=16224 +pid=2944 status=OK elapsed_ms=517563 cpu_user_ms=43276.664 cpu_sys_ms=55.975 rss_kb=584 challenge=32 sig=16224 +pid=2937 status=OK elapsed_ms=517565 cpu_user_ms=43298.178 cpu_sys_ms=33.603 rss_kb=584 challenge=32 sig=16224 +pid=2936 status=OK elapsed_ms=517574 cpu_user_ms=43272.032 cpu_sys_ms=63.285 rss_kb=584 challenge=32 sig=16224 +pid=3646 status=OK elapsed_ms=517420 cpu_user_ms=43351.649 cpu_sys_ms=56.031 rss_kb=584 challenge=32 sig=16224 +pid=3645 status=OK elapsed_ms=517425 cpu_user_ms=43398.057 cpu_sys_ms=14.973 rss_kb=584 challenge=32 sig=16224 +pid=3647 status=OK elapsed_ms=517438 cpu_user_ms=43386.264 cpu_sys_ms=29.779 rss_kb=584 challenge=32 sig=16224 +pid=3643 status=OK elapsed_ms=517444 cpu_user_ms=43398.396 cpu_sys_ms=18.624 rss_kb=584 challenge=32 sig=16224 +pid=3649 status=OK elapsed_ms=517455 cpu_user_ms=43393.133 cpu_sys_ms=26.082 rss_kb=584 challenge=32 sig=16224 +pid=3651 status=OK elapsed_ms=517456 cpu_user_ms=43390.700 cpu_sys_ms=26.112 rss_kb=584 challenge=32 sig=16224 +pid=3648 status=OK elapsed_ms=517468 cpu_user_ms=43373.469 cpu_sys_ms=44.766 rss_kb=584 challenge=32 sig=16224 +pid=3650 status=OK elapsed_ms=517506 cpu_user_ms=43373.332 cpu_sys_ms=48.406 rss_kb=584 challenge=32 sig=16224 +pid=3644 status=OK elapsed_ms=517532 cpu_user_ms=43400.834 cpu_sys_ms=29.808 rss_kb=584 challenge=32 sig=16224 +pid=3642 status=OK elapsed_ms=517537 cpu_user_ms=43400.813 cpu_sys_ms=33.462 rss_kb=584 challenge=32 sig=16224 +pid=1171 status=OK elapsed_ms=515720 cpu_user_ms=43349.072 cpu_sys_ms=29.865 rss_kb=584 challenge=32 sig=16224 +pid=1173 status=OK elapsed_ms=515769 cpu_user_ms=43376.343 cpu_sys_ms=7.436 rss_kb=584 challenge=32 sig=16224 +pid=1169 status=OK elapsed_ms=515795 cpu_user_ms=43353.267 cpu_sys_ms=29.792 rss_kb=584 challenge=32 sig=16224 +pid=1174 status=OK elapsed_ms=515804 cpu_user_ms=43363.725 cpu_sys_ms=22.352 rss_kb=584 challenge=32 sig=16224 +pid=1168 status=OK elapsed_ms=515757 cpu_user_ms=43364.944 cpu_sys_ms=14.981 rss_kb=584 challenge=32 sig=16224 +pid=1175 status=OK elapsed_ms=515780 cpu_user_ms=43365.249 cpu_sys_ms=18.686 rss_kb=584 challenge=32 sig=16224 +pid=1167 status=OK elapsed_ms=515814 cpu_user_ms=43349.635 cpu_sys_ms=37.315 rss_kb=584 challenge=32 sig=16224 +pid=1172 status=OK elapsed_ms=515820 cpu_user_ms=43355.661 cpu_sys_ms=29.828 rss_kb=584 challenge=32 sig=16224 +pid=1176 status=OK elapsed_ms=515775 cpu_user_ms=43350.542 cpu_sys_ms=37.266 rss_kb=584 challenge=32 sig=16224 +pid=1170 status=OK elapsed_ms=515866 cpu_user_ms=43363.758 cpu_sys_ms=37.206 rss_kb=584 challenge=32 sig=16224 +pid=1877 status=OK elapsed_ms=515193 cpu_user_ms=43302.023 cpu_sys_ms=29.920 rss_kb=584 challenge=32 sig=16224 +pid=1875 status=OK elapsed_ms=515225 cpu_user_ms=43314.348 cpu_sys_ms=22.296 rss_kb=584 challenge=32 sig=16224 +pid=1881 status=OK elapsed_ms=515242 cpu_user_ms=43301.711 cpu_sys_ms=37.257 rss_kb=584 challenge=32 sig=16224 +pid=1883 status=OK elapsed_ms=515251 cpu_user_ms=43318.369 cpu_sys_ms=22.376 rss_kb=584 challenge=32 sig=16224 +pid=1878 status=OK elapsed_ms=515248 cpu_user_ms=43316.012 cpu_sys_ms=22.368 rss_kb=584 challenge=32 sig=16224 +pid=1874 status=OK elapsed_ms=515251 cpu_user_ms=43307.405 cpu_sys_ms=33.364 rss_kb=584 challenge=32 sig=16224 +pid=1879 status=OK elapsed_ms=515272 cpu_user_ms=43312.188 cpu_sys_ms=29.868 rss_kb=584 challenge=32 sig=16224 +pid=1876 status=OK elapsed_ms=515304 cpu_user_ms=43309.572 cpu_sys_ms=41.037 rss_kb=584 challenge=32 sig=16224 +pid=1882 status=OK elapsed_ms=515314 cpu_user_ms=43320.515 cpu_sys_ms=33.524 rss_kb=584 challenge=32 sig=16224 +pid=1880 status=OK elapsed_ms=515330 cpu_user_ms=43335.007 cpu_sys_ms=22.348 rss_kb=584 challenge=32 sig=16224 +shake-256s simple +log: +pid=445 status=OK elapsed_ms=449691 cpu_user_ms=37729.704 cpu_sys_ms=40.909 rss_kb=660 challenge=32 sig=29792 +pid=450 status=OK elapsed_ms=449764 cpu_user_ms=37751.824 cpu_sys_ms=22.297 rss_kb=660 challenge=32 sig=29792 +pid=444 status=OK elapsed_ms=449771 cpu_user_ms=37754.252 cpu_sys_ms=22.328 rss_kb=660 challenge=32 sig=29792 +pid=452 status=OK elapsed_ms=449785 cpu_user_ms=37740.836 cpu_sys_ms=37.248 rss_kb=660 challenge=32 sig=29792 +pid=449 status=OK elapsed_ms=449797 cpu_user_ms=37758.558 cpu_sys_ms=18.644 rss_kb=660 challenge=32 sig=29792 +pid=447 status=OK elapsed_ms=449809 cpu_user_ms=37750.582 cpu_sys_ms=37.035 rss_kb=660 challenge=32 sig=29792 +pid=448 status=OK elapsed_ms=449812 cpu_user_ms=37761.333 cpu_sys_ms=25.957 rss_kb=660 challenge=32 sig=29792 +pid=446 status=OK elapsed_ms=449840 cpu_user_ms=37763.358 cpu_sys_ms=26.045 rss_kb=660 challenge=32 sig=29792 +pid=451 status=OK elapsed_ms=449843 cpu_user_ms=37759.972 cpu_sys_ms=29.723 rss_kb=660 challenge=32 sig=29792 +pid=453 status=OK elapsed_ms=449853 cpu_user_ms=37756.620 cpu_sys_ms=33.451 rss_kb=660 challenge=32 sig=29792 +pid=1071 status=OK elapsed_ms=450959 cpu_user_ms=37748.644 cpu_sys_ms=48.150 rss_kb=660 challenge=32 sig=29792 +pid=1069 status=OK elapsed_ms=450993 cpu_user_ms=37747.716 cpu_sys_ms=48.251 rss_kb=660 challenge=32 sig=29792 +pid=1070 status=OK elapsed_ms=451044 cpu_user_ms=37763.883 cpu_sys_ms=37.217 rss_kb=660 challenge=32 sig=29792 +pid=1067 status=OK elapsed_ms=451052 cpu_user_ms=37773.239 cpu_sys_ms=33.407 rss_kb=660 challenge=32 sig=29792 +pid=1062 status=OK elapsed_ms=451058 cpu_user_ms=37754.597 cpu_sys_ms=48.256 rss_kb=660 challenge=32 sig=29792 +pid=1066 status=OK elapsed_ms=451053 cpu_user_ms=37750.028 cpu_sys_ms=59.589 rss_kb=660 challenge=32 sig=29792 +pid=1063 status=OK elapsed_ms=451079 cpu_user_ms=37782.601 cpu_sys_ms=26.074 rss_kb=660 challenge=32 sig=29792 +pid=1064 status=OK elapsed_ms=451068 cpu_user_ms=37770.203 cpu_sys_ms=37.106 rss_kb=660 challenge=32 sig=29792 +pid=1068 status=OK elapsed_ms=451096 cpu_user_ms=37782.633 cpu_sys_ms=29.723 rss_kb=660 challenge=32 sig=29792 +pid=1065 status=OK elapsed_ms=451110 cpu_user_ms=37783.242 cpu_sys_ms=33.403 rss_kb=660 challenge=32 sig=29792 +pid=1689 status=OK elapsed_ms=449538 cpu_user_ms=37706.255 cpu_sys_ms=14.807 rss_kb=660 challenge=32 sig=29792 +pid=1692 status=OK elapsed_ms=449542 cpu_user_ms=37690.312 cpu_sys_ms=33.552 rss_kb=660 challenge=32 sig=29792 +pid=1688 status=OK elapsed_ms=449557 cpu_user_ms=37693.980 cpu_sys_ms=26.155 rss_kb=660 challenge=32 sig=29792 +pid=1687 status=OK elapsed_ms=449564 cpu_user_ms=37689.818 cpu_sys_ms=33.565 rss_kb=660 challenge=32 sig=29792 +pid=1691 status=OK elapsed_ms=449598 cpu_user_ms=37699.059 cpu_sys_ms=29.849 rss_kb=660 challenge=32 sig=29792 +pid=1693 status=OK elapsed_ms=449602 cpu_user_ms=37702.459 cpu_sys_ms=29.816 rss_kb=660 challenge=32 sig=29792 +pid=1685 status=OK elapsed_ms=449603 cpu_user_ms=37679.530 cpu_sys_ms=44.564 rss_kb=660 challenge=32 sig=29792 +pid=1684 status=OK elapsed_ms=449614 cpu_user_ms=37692.971 cpu_sys_ms=33.520 rss_kb=660 challenge=32 sig=29792 +pid=1690 status=OK elapsed_ms=449657 cpu_user_ms=37708.260 cpu_sys_ms=29.455 rss_kb=660 challenge=32 sig=29792 +pid=1686 status=OK elapsed_ms=449683 cpu_user_ms=37729.937 cpu_sys_ms=11.148 rss_kb=660 challenge=32 sig=29792 +pid=2303 status=OK elapsed_ms=451168 cpu_user_ms=37817.220 cpu_sys_ms=41.236 rss_kb=660 challenge=32 sig=29792 +pid=2301 status=OK elapsed_ms=451200 cpu_user_ms=37837.508 cpu_sys_ms=22.378 rss_kb=660 challenge=32 sig=29792 +pid=2307 status=OK elapsed_ms=451216 cpu_user_ms=37828.668 cpu_sys_ms=33.432 rss_kb=660 challenge=32 sig=29792 +pid=2304 status=OK elapsed_ms=451253 cpu_user_ms=37838.167 cpu_sys_ms=29.915 rss_kb=660 challenge=32 sig=29792 +pid=2308 status=OK elapsed_ms=451269 cpu_user_ms=37836.747 cpu_sys_ms=33.491 rss_kb=660 challenge=32 sig=29792 +pid=2302 status=OK elapsed_ms=451240 cpu_user_ms=37840.013 cpu_sys_ms=26.018 rss_kb=660 challenge=32 sig=29792 +pid=2305 status=OK elapsed_ms=451300 cpu_user_ms=37836.637 cpu_sys_ms=37.037 rss_kb=660 challenge=32 sig=29792 +pid=2299 status=OK elapsed_ms=451308 cpu_user_ms=37850.167 cpu_sys_ms=22.324 rss_kb=660 challenge=32 sig=29792 +pid=2300 status=OK elapsed_ms=451316 cpu_user_ms=37802.719 cpu_sys_ms=70.701 rss_kb=660 challenge=32 sig=29792 +pid=2306 status=OK elapsed_ms=451306 cpu_user_ms=37858.075 cpu_sys_ms=18.586 rss_kb=660 challenge=32 sig=29792 +pid=2922 status=OK elapsed_ms=450609 cpu_user_ms=37820.208 cpu_sys_ms=18.667 rss_kb=660 challenge=32 sig=29792 +pid=2926 status=OK elapsed_ms=450662 cpu_user_ms=37802.362 cpu_sys_ms=41.281 rss_kb=660 challenge=32 sig=29792 +pid=2920 status=OK elapsed_ms=450680 cpu_user_ms=37822.783 cpu_sys_ms=25.981 rss_kb=660 challenge=32 sig=29792 +pid=2919 status=OK elapsed_ms=450701 cpu_user_ms=37810.796 cpu_sys_ms=37.200 rss_kb=660 challenge=32 sig=29792 +pid=2925 status=OK elapsed_ms=450739 cpu_user_ms=37828.647 cpu_sys_ms=26.162 rss_kb=660 challenge=32 sig=29792 +pid=2923 status=OK elapsed_ms=450767 cpu_user_ms=37828.007 cpu_sys_ms=29.909 rss_kb=660 challenge=32 sig=29792 +pid=2928 status=OK elapsed_ms=450769 cpu_user_ms=37821.402 cpu_sys_ms=33.486 rss_kb=660 challenge=32 sig=29792 +pid=2921 status=OK elapsed_ms=450778 cpu_user_ms=37819.023 cpu_sys_ms=37.106 rss_kb=660 challenge=32 sig=29792 +pid=2924 status=OK elapsed_ms=450788 cpu_user_ms=37813.084 cpu_sys_ms=44.639 rss_kb=660 challenge=32 sig=29792 +pid=2927 status=OK elapsed_ms=450787 cpu_user_ms=37830.099 cpu_sys_ms=29.801 rss_kb=660 challenge=32 sig=29792 +pid=3542 status=OK elapsed_ms=449467 cpu_user_ms=37732.422 cpu_sys_ms=29.848 rss_kb=660 challenge=32 sig=29792 +pid=3535 status=OK elapsed_ms=449483 cpu_user_ms=37712.316 cpu_sys_ms=48.715 rss_kb=660 challenge=32 sig=29792 +pid=3536 status=OK elapsed_ms=449499 cpu_user_ms=37747.181 cpu_sys_ms=18.607 rss_kb=660 challenge=32 sig=29792 +pid=3534 status=OK elapsed_ms=449549 cpu_user_ms=37725.644 cpu_sys_ms=44.661 rss_kb=660 challenge=32 sig=29792 +pid=3541 status=OK elapsed_ms=449564 cpu_user_ms=37736.240 cpu_sys_ms=33.463 rss_kb=660 challenge=32 sig=29792 +pid=3538 status=OK elapsed_ms=449569 cpu_user_ms=37732.015 cpu_sys_ms=37.216 rss_kb=660 challenge=32 sig=29792 +pid=3539 status=OK elapsed_ms=449574 cpu_user_ms=37749.148 cpu_sys_ms=22.464 rss_kb=660 challenge=32 sig=29792 +pid=3543 status=OK elapsed_ms=449612 cpu_user_ms=37752.278 cpu_sys_ms=22.405 rss_kb=660 challenge=32 sig=29792 +pid=3537 status=OK elapsed_ms=449640 cpu_user_ms=37720.202 cpu_sys_ms=59.875 rss_kb=660 challenge=32 sig=29792 +pid=3540 status=OK elapsed_ms=449645 cpu_user_ms=37753.266 cpu_sys_ms=26.072 rss_kb=660 challenge=32 sig=29792 +pid=357 status=OK elapsed_ms=450690 cpu_user_ms=37765.231 cpu_sys_ms=22.417 rss_kb=660 challenge=32 sig=29792 +pid=362 status=OK elapsed_ms=450752 cpu_user_ms=37760.173 cpu_sys_ms=33.662 rss_kb=660 challenge=32 sig=29792 +pid=356 status=OK elapsed_ms=450768 cpu_user_ms=37773.700 cpu_sys_ms=22.306 rss_kb=660 challenge=32 sig=29792 +pid=355 status=OK elapsed_ms=450755 cpu_user_ms=37768.644 cpu_sys_ms=26.055 rss_kb=660 challenge=32 sig=29792 +pid=360 status=OK elapsed_ms=450780 cpu_user_ms=37755.354 cpu_sys_ms=41.027 rss_kb=660 challenge=32 sig=29792 +pid=363 status=OK elapsed_ms=450796 cpu_user_ms=37764.957 cpu_sys_ms=37.117 rss_kb=660 challenge=32 sig=29792 +pid=358 status=OK elapsed_ms=450820 cpu_user_ms=37757.934 cpu_sys_ms=44.767 rss_kb=660 challenge=32 sig=29792 +pid=359 status=OK elapsed_ms=450835 cpu_user_ms=37768.674 cpu_sys_ms=40.854 rss_kb=660 challenge=32 sig=29792 +pid=354 status=OK elapsed_ms=450843 cpu_user_ms=37765.186 cpu_sys_ms=44.643 rss_kb=660 challenge=32 sig=29792 +pid=361 status=OK elapsed_ms=450847 cpu_user_ms=37772.431 cpu_sys_ms=37.225 rss_kb=660 challenge=32 sig=29792 +pid=978 status=OK elapsed_ms=449752 cpu_user_ms=37721.644 cpu_sys_ms=26.270 rss_kb=660 challenge=32 sig=29792 +pid=983 status=OK elapsed_ms=449756 cpu_user_ms=37729.745 cpu_sys_ms=18.705 rss_kb=660 challenge=32 sig=29792 +pid=974 status=OK elapsed_ms=449787 cpu_user_ms=37721.288 cpu_sys_ms=29.903 rss_kb=660 challenge=32 sig=29792 +pid=979 status=OK elapsed_ms=449852 cpu_user_ms=37732.047 cpu_sys_ms=26.119 rss_kb=660 challenge=32 sig=29792 +pid=981 status=OK elapsed_ms=449864 cpu_user_ms=37710.224 cpu_sys_ms=51.901 rss_kb=660 challenge=32 sig=29792 +pid=980 status=OK elapsed_ms=449873 cpu_user_ms=37730.933 cpu_sys_ms=33.492 rss_kb=660 challenge=32 sig=29792 +pid=976 status=OK elapsed_ms=449887 cpu_user_ms=37723.806 cpu_sys_ms=37.269 rss_kb=660 challenge=32 sig=29792 +pid=975 status=OK elapsed_ms=449899 cpu_user_ms=37731.299 cpu_sys_ms=29.785 rss_kb=660 challenge=32 sig=29792 +pid=982 status=OK elapsed_ms=449904 cpu_user_ms=37741.310 cpu_sys_ms=22.266 rss_kb=660 challenge=32 sig=29792 +pid=977 status=OK elapsed_ms=449927 cpu_user_ms=37734.125 cpu_sys_ms=33.298 rss_kb=660 challenge=32 sig=29792 +pid=1598 status=OK elapsed_ms=449701 cpu_user_ms=37706.646 cpu_sys_ms=29.869 rss_kb=660 challenge=32 sig=29792 +pid=1604 status=OK elapsed_ms=449785 cpu_user_ms=37703.750 cpu_sys_ms=41.061 rss_kb=660 challenge=32 sig=29792 +pid=1596 status=OK elapsed_ms=449779 cpu_user_ms=37690.541 cpu_sys_ms=51.999 rss_kb=660 challenge=32 sig=29792 +pid=1603 status=OK elapsed_ms=449785 cpu_user_ms=37703.131 cpu_sys_ms=40.997 rss_kb=660 challenge=32 sig=29792 +pid=1595 status=OK elapsed_ms=449796 cpu_user_ms=37715.475 cpu_sys_ms=29.732 rss_kb=660 challenge=32 sig=29792 +pid=1602 status=OK elapsed_ms=449824 cpu_user_ms=37699.588 cpu_sys_ms=52.219 rss_kb=660 challenge=32 sig=29792 +pid=1601 status=OK elapsed_ms=449839 cpu_user_ms=37726.714 cpu_sys_ms=22.365 rss_kb=660 challenge=32 sig=29792 +pid=1597 status=OK elapsed_ms=449842 cpu_user_ms=37712.902 cpu_sys_ms=37.232 rss_kb=660 challenge=32 sig=29792 +pid=1599 status=OK elapsed_ms=449852 cpu_user_ms=37704.136 cpu_sys_ms=48.329 rss_kb=660 challenge=32 sig=29792 +pid=1600 status=OK elapsed_ms=449869 cpu_user_ms=37725.628 cpu_sys_ms=33.487 rss_kb=660 challenge=32 sig=29792 +pid=2212 status=OK elapsed_ms=451890 cpu_user_ms=37837.407 cpu_sys_ms=29.760 rss_kb=660 challenge=32 sig=29792 +pid=2218 status=OK elapsed_ms=451893 cpu_user_ms=37819.954 cpu_sys_ms=48.422 rss_kb=660 challenge=32 sig=29792 +pid=2217 status=OK elapsed_ms=451903 cpu_user_ms=37814.904 cpu_sys_ms=52.261 rss_kb=660 challenge=32 sig=29792 +pid=2219 status=OK elapsed_ms=451899 cpu_user_ms=37858.749 cpu_sys_ms=7.475 rss_kb=660 challenge=32 sig=29792 +pid=2213 status=OK elapsed_ms=451935 cpu_user_ms=37829.287 cpu_sys_ms=41.069 rss_kb=660 challenge=32 sig=29792 +pid=2215 status=OK elapsed_ms=451998 cpu_user_ms=37819.907 cpu_sys_ms=55.815 rss_kb=660 challenge=32 sig=29792 +pid=2211 status=OK elapsed_ms=452015 cpu_user_ms=37846.103 cpu_sys_ms=29.740 rss_kb=660 challenge=32 sig=29792 +pid=2216 status=OK elapsed_ms=452020 cpu_user_ms=37839.127 cpu_sys_ms=37.341 rss_kb=660 challenge=32 sig=29792 +pid=2210 status=OK elapsed_ms=452024 cpu_user_ms=37846.164 cpu_sys_ms=29.890 rss_kb=660 challenge=32 sig=29792 +pid=2214 status=OK elapsed_ms=452028 cpu_user_ms=37829.759 cpu_sys_ms=48.294 rss_kb=660 challenge=32 sig=29792 \ No newline at end of file