From 6d066cf8293675ac5a376541e06335819f768c47 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Mon, 6 Apr 2026 18:13:13 +0300 Subject: [PATCH 1/9] added native Ed25519 signature functions that use the precalculated digest --- src/microsui_core/sign.c | 127 ++++++++++++++++++++++++++++++++++++--- src/microsui_core/sign.h | 6 ++ 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index 8869b7b..0fe3daf 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -9,6 +9,27 @@ #include "byte_conversions.h" +/** + * @brief Sign a pre-computed digest and build a Sui-formatted Ed25519 signature. + * + * Signs the given 32-byte digest using the provided Ed25519 secret key and + * assembles the result into the Sui signature format: + * [0x00 scheme | 64-byte Ed25519 signature | 32-byte public key] + * + * @param[out] sui_sig_out Output buffer for the Sui signature (must be 97 bytes). + * @param[in] secret_key 64-byte Ed25519 secret key, as produced by crypto_ed25519_key_pair (dont confuse with the 32-byte seed). + * @param[in] public_key 32-byte Ed25519 public key. + * @param[in] digest 32-byte digest to sign. + */ +void microsui_sign_ed25519_from_digest(uint8_t sui_sig_out[97], const uint8_t secret_key[64], const uint8_t public_key[32], const uint8_t digest[32]) { + uint8_t ed25519_signature[64]; + crypto_ed25519_sign_sha512(ed25519_signature, secret_key, digest, 32); + + sui_sig_out[0] = 0x00; // Ed25519 Scheme + memcpy(sui_sig_out + 1, ed25519_signature, 64); + memcpy(sui_sig_out + 65, public_key, 32); +} + /** * @brief Sign a Sui Transaction message using Ed25519 and produce a Sui-formatted signature. * @@ -49,14 +70,8 @@ int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const crypto_blake2b_final(&ctx, digest); - // 4. Sign the digest using Ed25519 with the secret key and public key - uint8_t ed25519_signature[64]; - crypto_ed25519_sign_sha512(ed25519_signature, secret_key, digest, 32); - - // 5. Build Sui signature - sui_sig_out[0] = 0x00; // Ed25519 Scheme - memcpy(sui_sig_out + 1, ed25519_signature, 64); - memcpy(sui_sig_out + 65, public_key, 32); + // 4. Sign the digest and build the Sui signature + microsui_sign_ed25519_from_digest(sui_sig_out, secret_key, public_key, digest); crypto_wipe(secret_key, sizeof secret_key); crypto_wipe(seed_cp, sizeof seed_cp); @@ -152,7 +167,46 @@ int microsui_verify_signature_ed25519(uint8_t sui_sig[97], const uint8_t* messag if(crypto_ed25519_check_sha512(signature, public_key, digest, 32) != 0) { return -2; // Signature verification failed } - + + return 0; // Signature is valid +} + +/** + * @brief Verify a Sui-formatted Ed25519 signature against a pre-computed digest. + * + * Expects a Sui signature encoded as: + * [0x00 scheme | 64-byte Ed25519 signature | 32-byte public key] + * + * Extracts the Ed25519 signature and public key from the Sui signature payload, + * then verifies them against the caller-supplied 32-byte digest. + * + * @param[in] sui_sig Pointer to the Sui signature buffer (must be 97 bytes). + * @param[in] digest 32-byte pre-computed digest to verify against. + * + * @return 0 if the signature is valid, + * -1 if the scheme byte is not Ed25519 (0x00), + * -2 if the signature verification fails. + * + * @note This function does not compute the digest internally; it expects + * the caller to provide a ready-to-verify 32-byte digest. + * @note This function does not recover a public key; it verifies using the public key + * embedded inside the Sui signature payload. + */ +int microsui_verify_signature_ed25519_from_digest(uint8_t sui_sig[97], const uint8_t digest[32]) { + if(sui_sig[0] != 0x00) { + return -1; // This is not an Ed25519 signature + } + + uint8_t signature[64]; + memcpy(signature, sui_sig + 1, 64); + + uint8_t public_key[32]; + memcpy(public_key, sui_sig + 65, 32); + + if(crypto_ed25519_check_sha512(signature, public_key, digest, 32) != 0) { + return -2; // Signature verification failed + } + return 0; // Signature is valid } @@ -218,6 +272,61 @@ int microsui_verify_signature_ed25519_with_public_key(uint8_t sui_sig[97], const return 0; // Signature is valid and public key matches } + +/** + * @brief Verify a Sui-formatted Ed25519 signature against a pre-computed digest + * and validate it against a known public key. + * + * Expects a Sui signature encoded as: + * [0x00 scheme | 64-byte Ed25519 signature | 32-byte public key] + * + * Extracts the Ed25519 signature and public key from the Sui signature payload, + * verifies them against the caller-supplied 32-byte digest, and then confirms + * that the embedded public key matches the caller-supplied key using a + * constant-time comparison. + * + * @param[in] sui_sig Pointer to the Sui signature buffer (must be 97 bytes). + * @param[in] digest 32-byte pre-computed digest to verify against. + * @param[in] public_key Pointer to the expected 32-byte Ed25519 public key. + * + * @return 0 if the signature is valid and the embedded public key matches @p public_key, + * -1 if the scheme byte is not Ed25519 (0x00), + * -2 if the signature verification fails, + * -3 if the public key embedded in the signature does not match @p public_key. + * + * @note This function does not compute the digest internally; it expects + * the caller to provide a ready-to-verify 32-byte digest. + * @note The public key comparison is performed in constant time to mitigate timing attacks. + * @note Signature verification (-2) is checked before public key comparison (-3); a -3 result + * therefore implies the signature itself was cryptographically valid. + */ +int microsui_verify_signature_ed25519_with_public_key_from_digest(uint8_t sui_sig[97], const uint8_t digest[32], uint8_t public_key[32]) { + if(sui_sig[0] != 0x00) { + return -1; // This is not an Ed25519 signature + } + + uint8_t signature[64]; + memcpy(signature, sui_sig + 1, 64); + + uint8_t signature_public_key[32]; + memcpy(signature_public_key, sui_sig + 65, 32); + + if(crypto_ed25519_check_sha512(signature, signature_public_key, digest, 32) != 0) { + return -2; // Signature verification failed + } + + // Check if the public key in the signature matches the provided public key (with timing attacks protection) + uint8_t diff = 0; + for (size_t i = 0; i < 32; i++) { + diff |= signature_public_key[i] ^ public_key[i]; + } + if (diff != 0) { + return -3; // Public key mismatch + } + + return 0; // Signature is valid and public key matches +} + /** * @brief Generic signature verification entry point for multiple signature schemes. * diff --git a/src/microsui_core/sign.h b/src/microsui_core/sign.h index 26fbbdc..595528c 100644 --- a/src/microsui_core/sign.h +++ b/src/microsui_core/sign.h @@ -8,10 +8,16 @@ int microsui_sign(uint8_t sui_sig_out[97], uint8_t scheme, const uint8_t* messag int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const size_t message_len, const uint8_t seed[32]); +void microsui_sign_ed25519_from_digest(uint8_t sui_sig_out[97], const uint8_t secret_key[64], const uint8_t public_key[32], const uint8_t digest[32]); + int microsui_verify_signature_ed25519(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len); +int microsui_verify_signature_ed25519_from_digest(uint8_t sui_sig[97], const uint8_t digest[32]); + int microsui_verify_signature_ed25519_with_public_key(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, uint8_t public_key[32]); +int microsui_verify_signature_ed25519_with_public_key_from_digest(uint8_t sui_sig[97], const uint8_t digest[32], uint8_t public_key[32]); + int microsui_verify_signature(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len); int microsui_verify_signature_with_public_key(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, uint8_t public_key[32]); From 9d32488fae2d98d4f2772d74c59cc4b22cc740bf Mon Sep 17 00:00:00 2001 From: Gustbel Date: Mon, 6 Apr 2026 18:17:04 +0300 Subject: [PATCH 2/9] added new functions in bechmark example --- .../{benchmarks => benchmark}/Makefile | 4 +- examples/core_examples/benchmark/benchmark.c | 155 ++++++++++++++++++ .../core_examples/benchmarks/benchmarks.c | 95 ----------- src/microsui_core/sign.c | 1 - 4 files changed, 157 insertions(+), 98 deletions(-) rename examples/core_examples/{benchmarks => benchmark}/Makefile (96%) create mode 100644 examples/core_examples/benchmark/benchmark.c delete mode 100644 examples/core_examples/benchmarks/benchmarks.c diff --git a/examples/core_examples/benchmarks/Makefile b/examples/core_examples/benchmark/Makefile similarity index 96% rename from examples/core_examples/benchmarks/Makefile rename to examples/core_examples/benchmark/Makefile index 72a186d..8e01c04 100644 --- a/examples/core_examples/benchmarks/Makefile +++ b/examples/core_examples/benchmark/Makefile @@ -17,7 +17,7 @@ WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This fil CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) -SOURCES := benchmarks.c \ +SOURCES := benchmark.c \ $(wildcard $(SRC)/*.c) \ $(wildcard $(MICROSUI_CORE)/*.c) \ $(wildcard $(UTILS)/*.c) \ @@ -28,7 +28,7 @@ SOURCES := benchmarks.c \ $(WIFI_DESKTOP_FILE) \ $(WIFI_UNSUPPORTED_FILE) -OUTPUT := benchmarks.out +OUTPUT := benchmark.out all: clean_before_build $(OUTPUT) diff --git a/examples/core_examples/benchmark/benchmark.c b/examples/core_examples/benchmark/benchmark.c new file mode 100644 index 0000000..9c5ca59 --- /dev/null +++ b/examples/core_examples/benchmark/benchmark.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "MicroSui.h" + +// Sui Message in hex format (this message must be signed) +const char* message_hex = "00000200080065cd1d0000000000202e3d52393c9035afd1ef38abd7fce2dad71f0e276b522fb274f4e14d1df974720202000101000001010300000000010100d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379d0180dc491e55e7caabfcdd1b0f538928d8d54107b9c1def3ed0baa3aa5106ba8674f0dd01400000000204b7e9da00f30cd1edf4d40710213c15a862e1fc175f2edb2b2c870c8559d65cdd79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379de80300000000000040ab3c000000000000"; + +// You must place your seed private key (in bytes format) here. +const uint8_t private_key_seed[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +uint8_t random_digest[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F +}; + +uint64_t millis(void); + +int main() { + printf("\n\t\t\t --- MicroSui Operations Benchmarks ---\n"); + printf("\n\tOriginal Message: %s", message_hex); + + // 0. Converting the message from hex to bytes + size_t message_len = strlen(message_hex) / 2; // 2 hex chars = 1 byte + uint8_t message[message_len]; + hex_to_bytes(message_hex, message, message_len); + + // 0. Generate public and secret key + uint8_t public_key[32]; + uint8_t secret_key[64]; + microsui_derive_public_key_ed25519(public_key, private_key_seed); + memcpy(secret_key, private_key_seed, 32); + memcpy(secret_key + 32, public_key, 32); + + // 1. Generating the Sui Signature from the message and seed private key + printf("\n\n\n 1 - Generating Signature from Sui Message...\n"); + uint8_t sui_sig[97]; + + uint64_t start_time = millis(); + microsui_sign_ed25519(sui_sig, message, message_len, private_key_seed); + uint64_t end_time = millis(); + printf("\t Signature created successfully\n\n"); + + // Calculate the time taken for verification + uint64_t time_taken_signature = end_time - start_time; + + // 2. Generating the Sui Signature from the precalculated digest and secret key + printf(" 2 - Generating Signature from precalculated Digest...\n"); + uint8_t sui_sig_from_digest[97]; + + start_time = millis(); + microsui_sign_ed25519_from_digest(sui_sig_from_digest, secret_key, public_key, random_digest); + end_time = millis(); + + uint64_t time_taken_signature_from_digest = end_time - start_time; + printf("\t Signature from digest created successfully\n\n"); + + // 3. Verifying the Sui Signature from the message and signature + printf(" 3 - Verifying Signature from Sui Message...\n"); + + start_time = millis(); + int verification_result = microsui_verify_signature(sui_sig, message, message_len); + end_time = millis(); + + // Calculate the time taken for verification + uint64_t time_taken_verification = end_time - start_time; + if(verification_result == 0) { + printf("\t Signature verified successfully\n\n"); + } else { + printf("\t Signature verification failed --\n"); + printf("\t Error code: %d --\n\n", verification_result); + } + + // 4. Verifying the Sui Signature from the precalculated digest and signature + printf(" 4 - Verifying Signature from precalculated Digest...\n"); + start_time = millis(); + int verification_result_from_digest = microsui_verify_signature_ed25519_from_digest(sui_sig_from_digest, random_digest); + end_time = millis(); + + // Calculate the time taken for verification + uint64_t time_taken_verification_from_digest = end_time - start_time; + if(verification_result_from_digest == 0) { + printf("\t Signature from digest verified successfully\n\n"); + } else { + printf("\t Signature verification failed --\n"); + printf("\t Error code: %d --\n\n", verification_result_from_digest); + } + + printf("\t Benchmarks Results:\n"); + printf("\t\t Time taken for signing from Sui Message: "); + if (time_taken_signature > 100000) { + printf("%llu ms\n", (unsigned long long)(time_taken_signature / 1000)); + } else { + printf("%.2f ms (%llu us) \n", (double)time_taken_signature / 1000.0, (unsigned long long)time_taken_signature); + } + + printf("\t\t Time taken for signing from precalculated digest: "); + if (time_taken_signature_from_digest > 100000) { + printf("%llu ms\n", (unsigned long long)(time_taken_signature_from_digest / 1000)); + } else { + printf("%.2f ms (%llu us) \n", (double)time_taken_signature_from_digest / 1000.0, (unsigned long long)time_taken_signature_from_digest); + } + + printf("\t\t Time taken for verification from Sui Message: "); + if (time_taken_verification > 100000) { + printf("%llu ms\n", (unsigned long long)(time_taken_verification / 1000)); + } else { + printf("%.2f ms (%llu us) \n", (double)time_taken_verification / 1000.0, (unsigned long long)time_taken_verification); + } + + printf("\t\t Time taken for verification from precalculated digest: "); + if (time_taken_verification_from_digest > 100000) { + printf("%llu ms\n", (unsigned long long)(time_taken_verification_from_digest / 1000)); + } else { + printf("%.2f ms (%llu us) \n", (double)time_taken_verification_from_digest / 1000.0, (unsigned long long)time_taken_verification_from_digest); + } + + printf("\n \tEnd of benchmarks.\n"); + + return 0; +} + +uint64_t millis(void) +{ +#if defined(_WIN32) || defined(_WIN64) + // Windows: QueryPerformanceCounter (high-resolution timer) + static LARGE_INTEGER freq = {0}; + LARGE_INTEGER now; + + if (freq.QuadPart == 0) + QueryPerformanceFrequency(&freq); + + QueryPerformanceCounter(&now); + return (uint64_t)((now.QuadPart * 1000000) / freq.QuadPart); + +#else + // Linux y macOS: clock_gettime(CLOCK_MONOTONIC) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)(ts.tv_sec) + (ts.tv_nsec / 1000ULL); +#endif +} \ No newline at end of file diff --git a/examples/core_examples/benchmarks/benchmarks.c b/examples/core_examples/benchmarks/benchmarks.c deleted file mode 100644 index 2d8b95b..0000000 --- a/examples/core_examples/benchmarks/benchmarks.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include - -#include "MicroSui.h" - -// Sui Message in hex format (this message must be signed) -const char* message_hex = "00000200080065cd1d0000000000202e3d52393c9035afd1ef38abd7fce2dad71f0e276b522fb274f4e14d1df974720202000101000001010300000000010100d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379d0180dc491e55e7caabfcdd1b0f538928d8d54107b9c1def3ed0baa3aa5106ba8674f0dd01400000000204b7e9da00f30cd1edf4d40710213c15a862e1fc175f2edb2b2c870c8559d65cdd79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379de80300000000000040ab3c000000000000"; - -// You must place your seed private key (in bytes format) here. -const uint8_t private_key_seed[32] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -uint64_t millis(void); - -int main() { - printf("\n\t\t\t --- MicroSui Operations Benchmarks ---\n"); - printf("\n\tOriginal Message: %s", message_hex); - - // Converting the message from hex to bytes - size_t message_len = strlen(message_hex) / 2; // 2 hex chars = 1 byte - uint8_t message[message_len]; - hex_to_bytes(message_hex, message, message_len); - - // Generating the Sui Signature from the message and private key - uint8_t sui_sig[97]; - printf("\n\n\n Generating Signature...\n"); - - uint64_t start_time = millis(); - microsui_sign_ed25519(sui_sig, message, message_len, private_key_seed); - uint64_t end_time = millis(); - printf("\t Signature created successfully\n"); - - // Calculate the time taken for verification - uint64_t time_taken_signature = end_time - start_time; - - // Verifying the Sui Signature - start_time = millis(); - int verification_result = microsui_verify_signature(sui_sig, message, message_len); - end_time = millis(); - - // Calculate the time taken for verification - uint64_t time_taken_verification = end_time - start_time; - if(verification_result == 0) { - printf("\t Signature verified successfully\n\n"); - } else { - printf("\t Signature verification failed\n"); - printf("\t Error code: %d\n\n", verification_result); - } - - - printf("\t Benchmarks Results:\n"); - printf("\t\t Time taken for signing: "); - if (time_taken_signature > 100000) { - printf("%llu ms\n", (unsigned long long)(time_taken_signature / 1000)); - } else { - printf("%.2f ms (%llu us) \n", (double)time_taken_signature / 1000.0, (unsigned long long)time_taken_signature); - } - - printf("\t\t Time taken for verification: "); - if (time_taken_verification > 100000) { - printf("%llu ms\n", (unsigned long long)(time_taken_verification / 1000)); - } else { - printf("%.2f ms (%llu us) \n", (double)time_taken_verification / 1000.0, (unsigned long long)time_taken_verification); - } - printf("\n End of benchmarks.\n"); - - return 0; -} - -uint64_t millis(void) -{ -#if defined(_WIN32) || defined(_WIN64) - // Windows: QueryPerformanceCounter (high-resolution timer) - static LARGE_INTEGER freq = {0}; - LARGE_INTEGER now; - - if (freq.QuadPart == 0) - QueryPerformanceFrequency(&freq); - - QueryPerformanceCounter(&now); - return (uint64_t)((now.QuadPart * 1000000) / freq.QuadPart); - -#else - // Linux y macOS: clock_gettime(CLOCK_MONOTONIC) - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint64_t)(ts.tv_sec) + (ts.tv_nsec / 1000ULL); -#endif -} \ No newline at end of file diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index 0fe3daf..1aa19c2 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -272,7 +272,6 @@ int microsui_verify_signature_ed25519_with_public_key(uint8_t sui_sig[97], const return 0; // Signature is valid and public key matches } - /** * @brief Verify a Sui-formatted Ed25519 signature against a pre-computed digest * and validate it against a known public key. From 2a322b4b8be0157270359915079c7386089112f8 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Tue, 7 Apr 2026 14:18:09 +0300 Subject: [PATCH 3/9] new signing function without key derivation --- examples/core_examples/benchmark/benchmark.c | 2 +- src/microsui_core/sign.c | 46 +++++++++++++++++++- src/microsui_core/sign.h | 4 +- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/examples/core_examples/benchmark/benchmark.c b/examples/core_examples/benchmark/benchmark.c index 9c5ca59..9bd653c 100644 --- a/examples/core_examples/benchmark/benchmark.c +++ b/examples/core_examples/benchmark/benchmark.c @@ -62,7 +62,7 @@ int main() { uint8_t sui_sig_from_digest[97]; start_time = millis(); - microsui_sign_ed25519_from_digest(sui_sig_from_digest, secret_key, public_key, random_digest); + microsui_sign_ed25519_from_digest(sui_sig_from_digest, random_digest, secret_key, public_key); end_time = millis(); uint64_t time_taken_signature_from_digest = end_time - start_time; diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index 1aa19c2..91aac39 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -17,11 +17,11 @@ * [0x00 scheme | 64-byte Ed25519 signature | 32-byte public key] * * @param[out] sui_sig_out Output buffer for the Sui signature (must be 97 bytes). + * @param[in] digest 32-byte digest to sign. * @param[in] secret_key 64-byte Ed25519 secret key, as produced by crypto_ed25519_key_pair (dont confuse with the 32-byte seed). * @param[in] public_key 32-byte Ed25519 public key. - * @param[in] digest 32-byte digest to sign. */ -void microsui_sign_ed25519_from_digest(uint8_t sui_sig_out[97], const uint8_t secret_key[64], const uint8_t public_key[32], const uint8_t digest[32]) { +void microsui_sign_ed25519_from_digest(uint8_t sui_sig_out[97], const uint8_t digest[32], const uint8_t secret_key[64], const uint8_t public_key[32]) { uint8_t ed25519_signature[64]; crypto_ed25519_sign_sha512(ed25519_signature, secret_key, digest, 32); @@ -81,6 +81,48 @@ int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const return 0; } +/** + * @brief Sign a Sui Transaction message using pre-derived Ed25519 keys. + * This function is a variant of microsui_sign_ed25519(), the purpose of which is skipping the key pair + * derivation step which is an expensive part of the signing process. This makes it suitable for low-power devices + * where CPU time is critical and the caller can manage key pairs separately for better performance. + * + * Builds the "message with intent" (prefix + tx bytes), digests it with BLAKE2b, + * signs the digest with Ed25519, and encodes the result in the Sui signature + * format (scheme byte + 64-byte Ed25519 signature + 32-byte public key). + * + * Unlike microsui_sign_ed25519(), this function skips key pair derivation, + * which is the an expensive step (~50% of the total signing time). + * The caller is responsible for providing a valid key pair. + * + * @param[out] sui_sig_out Output buffer for the Sui signature (must be 97 bytes). + * @param[in] message Pointer to raw transaction bytes (already serialized). + * @param[in] message_len Length of the transaction bytes. + * @param[in] secret_key 64-byte Ed25519 secret key, as produced by crypto_ed25519_key_pair (dont confuse with the 32-byte seed). + * @param[in] public_key 32-byte Ed25519 public key. + * + * @warning No validation is performed to check that the public key corresponds + * to the secret key. Passing mismatched keys will produce an invalid signature. + * It's up to the caller to ensure that the provided key pair is correct and corresponds to the intended signing identity. + */ +void microsui_sign_ed25519_with_keys(uint8_t sui_sig_out[97], const uint8_t* message, const size_t message_len, const uint8_t secret_key[64], const uint8_t public_key[32]) { + uint8_t digest[32]; + + crypto_blake2b_ctx ctx; + crypto_blake2b_init(&ctx, 32); + + const uint8_t intent[3] = {0x00, 0x00, 0x00}; + crypto_blake2b_update(&ctx, intent, sizeof intent); + crypto_blake2b_update(&ctx, message, message_len); + + crypto_blake2b_final(&ctx, digest); + + microsui_sign_ed25519_from_digest(sui_sig_out, secret_key, public_key, digest); + + crypto_wipe(&ctx, sizeof ctx); + crypto_wipe(digest, sizeof digest); +} + /** * @brief Generic signing entry point for multiple signature schemes. * diff --git a/src/microsui_core/sign.h b/src/microsui_core/sign.h index 595528c..d238283 100644 --- a/src/microsui_core/sign.h +++ b/src/microsui_core/sign.h @@ -8,7 +8,9 @@ int microsui_sign(uint8_t sui_sig_out[97], uint8_t scheme, const uint8_t* messag int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const size_t message_len, const uint8_t seed[32]); -void microsui_sign_ed25519_from_digest(uint8_t sui_sig_out[97], const uint8_t secret_key[64], const uint8_t public_key[32], const uint8_t digest[32]); +void microsui_sign_ed25519_with_keys(uint8_t sui_sig_out[97], const uint8_t* message, const size_t message_len, const uint8_t secret_key[64], const uint8_t public_key[32]); + +void microsui_sign_ed25519_from_digest(uint8_t sui_sig_out[97], const uint8_t digest[32], const uint8_t secret_key[64], const uint8_t public_key[32]); int microsui_verify_signature_ed25519(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len); From 23745d3ac4e70fc915ceb1c4482485e5663d4413 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Tue, 7 Apr 2026 14:25:29 +0300 Subject: [PATCH 4/9] added derive keypair ed25519 new function --- src/microsui_core/key_management.c | 37 ++++++++++++++++++++++++++++-- src/microsui_core/key_management.h | 2 ++ src/microsui_core/sign.c | 3 ++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/microsui_core/key_management.c b/src/microsui_core/key_management.c index 836497b..2608c3d 100644 --- a/src/microsui_core/key_management.c +++ b/src/microsui_core/key_management.c @@ -62,6 +62,39 @@ int microsui_derive_public_key_ed25519(uint8_t public_key_out[32], const uint8_t // Clear sensitive data from memory crypto_wipe(seed_cp, sizeof seed_cp); crypto_wipe(_, sizeof _); - + return 0; -} \ No newline at end of file +} + +/** + * @brief Derive an Ed25519 key pair (64-byte secret key and 32-byte public key) from a 32-byte seed. + * + * Generates the full 64-byte Ed25519 secret key and its corresponding + * 32-byte public key from the provided seed. + * + * @param[out] secret_key_out Output buffer for the 64-byte Ed25519 secret key. + * @param[out] public_key_out Output buffer for the 32-byte Ed25519 public key. + * @param[in] seed 32-byte Ed25519 seed. + * + * @return 0 on success; -1 if input pointers are NULL. + * + * @note The seed is copied to a local buffer before use, + * as the underlying library may modify it during key generation. + * @note The caller is responsible for wiping secret_key_out when no longer needed. + */ +int microsui_derive_keypair_ed25519(uint8_t secret_key_out[64], uint8_t public_key_out[32], const uint8_t seed[32]) { + if (seed == NULL || secret_key_out == NULL || public_key_out == NULL) return -1; + + // Copy seed to a local variable + uint8_t seed_cp[32]; + memcpy(seed_cp, seed, 32); + + // Generate secret and public key from seed using Ed25519 + crypto_ed25519_key_pair(secret_key_out, public_key_out, seed_cp); + + // Clear sensitive data from memory + crypto_wipe(seed_cp, sizeof seed_cp); + + return 0; +} + diff --git a/src/microsui_core/key_management.h b/src/microsui_core/key_management.h index 67146f0..0234bfc 100644 --- a/src/microsui_core/key_management.h +++ b/src/microsui_core/key_management.h @@ -8,4 +8,6 @@ int microsui_derive_sui_address_ed25519(uint8_t sui_address_out[32], const uint8 int microsui_derive_public_key_ed25519(uint8_t public_key_out[32], const uint8_t seed[32]); +int microsui_derive_keypair_ed25519(uint8_t secret_key_out[64], uint8_t public_key_out[32], const uint8_t seed[32]); + #endif \ No newline at end of file diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index 91aac39..0ea38fb 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -93,7 +93,8 @@ int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const * * Unlike microsui_sign_ed25519(), this function skips key pair derivation, * which is the an expensive step (~50% of the total signing time). - * The caller is responsible for providing a valid key pair. + * The caller is responsible for providing a valid key pair, which can be calculated once + * from microsui_derive_keypair_ed25519() function and reused across multiple signing operations. * * @param[out] sui_sig_out Output buffer for the Sui signature (must be 97 bytes). * @param[in] message Pointer to raw transaction bytes (already serialized). From 44fffee93dbce60bc8f64e0fadc6d961295048a1 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Tue, 7 Apr 2026 15:20:26 +0300 Subject: [PATCH 5/9] added more cases in bechmark --- examples/core_examples/benchmark/benchmark.c | 152 ++++++++++++++++--- 1 file changed, 135 insertions(+), 17 deletions(-) diff --git a/examples/core_examples/benchmark/benchmark.c b/examples/core_examples/benchmark/benchmark.c index 9bd653c..99a230a 100644 --- a/examples/core_examples/benchmark/benchmark.c +++ b/examples/core_examples/benchmark/benchmark.c @@ -31,7 +31,11 @@ uint64_t millis(void); int main() { printf("\n\t\t\t --- MicroSui Operations Benchmarks ---\n"); - printf("\n\tOriginal Message: %s", message_hex); + + printf("\n\t This benchmark will measure the execution time of key operations in the MicroSui library, including signature generation and verification, as well as key management functions.\n"); + printf("\t The time taken for each operation will be displayed in milliseconds (ms) or microseconds (us) depending on the duration, providing insights into the performance of the library's core functionalities, and may vary significantly based on the underlying hardware and optimizations.\n\n"); + + printf("\n\tOriginal Message: '%s'", message_hex); // 0. Converting the message from hex to bytes size_t message_len = strlen(message_hex) / 2; // 2 hex chars = 1 byte @@ -39,12 +43,11 @@ int main() { hex_to_bytes(message_hex, message, message_len); // 0. Generate public and secret key - uint8_t public_key[32]; uint8_t secret_key[64]; - microsui_derive_public_key_ed25519(public_key, private_key_seed); - memcpy(secret_key, private_key_seed, 32); - memcpy(secret_key + 32, public_key, 32); + uint8_t public_key[32]; + microsui_derive_keypair_ed25519(secret_key, public_key, private_key_seed); + /////// SIGNATURES /////// // 1. Generating the Sui Signature from the message and seed private key printf("\n\n\n 1 - Generating Signature from Sui Message...\n"); uint8_t sui_sig[97]; @@ -70,7 +73,6 @@ int main() { // 3. Verifying the Sui Signature from the message and signature printf(" 3 - Verifying Signature from Sui Message...\n"); - start_time = millis(); int verification_result = microsui_verify_signature(sui_sig, message, message_len); end_time = millis(); @@ -99,33 +101,149 @@ int main() { printf("\t Error code: %d --\n\n", verification_result_from_digest); } - printf("\t Benchmarks Results:\n"); + /////// KEY MANAGEMENT /////// + printf(" 5 - Deriving a Public Key from a 32-byte Ed25519 seed private key...\n"); + uint8_t derived_public_key_out[32]; + start_time = millis(); + int public_key_derivation_result = microsui_derive_public_key_ed25519(derived_public_key_out, private_key_seed); + end_time = millis(); + uint64_t time_taken_public_key_derivation = end_time - start_time; + if(public_key_derivation_result == 0) { + printf("\t Public key derived successfully.\n\n"); + } else { + printf("\t Public key derivation failed --\n\n"); + printf("\t Error code: %d --\n\n", public_key_derivation_result); + } + + printf(" 6 - Deriving a Keypair (Secret Key + Public Key) from a 32-byte Ed25519 seed private key...\n"); + u_int8_t derived_secret_key_out[64]; + uint8_t derived_public_key_out2[32]; + start_time = millis(); + int keypair_derivation_result = microsui_derive_keypair_ed25519(derived_secret_key_out, derived_public_key_out2, private_key_seed); + end_time = millis(); + uint64_t time_taken_keypair_derivation = end_time - start_time; + if(keypair_derivation_result == 0) { + printf("\t Keypair derived successfully.\n\n"); + } else { + printf("\t Keypair derivation failed --\n\n"); + printf("\t Error code: %d --\n\n", keypair_derivation_result); + } + + printf(" 7 - Deriving a Sui address from a 32-byte Ed25519 public key...\n"); + uint8_t encoded_address[32]; + start_time = millis(); + int address_derivation_result = microsui_derive_sui_address_ed25519(encoded_address, public_key); + end_time = millis(); + uint64_t time_taken_address_derivation = end_time - start_time; + + if(address_derivation_result == 0) { + printf("\t Sui address derived successfully. Address: 0x"); + for (int i = 0; i < 32; i++) printf("%02x", encoded_address[i]); + printf("\n\n"); + } else { + printf("\t Sui address derivation failed --\n\n"); + printf("\t Error code: %d --\n\n", address_derivation_result); + } + + + /////// KEY MANAGEMENT - BECH32 OPERATIONS /////// + printf(" 8 - Encoding the 32-byte seed into a Sui Bech32 private key string....\n"); + char private_key_bech32_output[71]; + start_time = millis(); + int encoding_result = microsui_encode_bech32_private_key(private_key_bech32_output, random_digest); + end_time = millis(); + + // Calculate the time taken for encoding + uint64_t time_taken_encoding = end_time - start_time; + if(encoding_result == 0) { + printf("\t Encoding successful. Encoded Bech32 Key: %s\n\n", private_key_bech32_output); + } else { + printf("\t Encoding failed --\n"); + printf("\t Error code: %d --\n\n", encoding_result); + } + + printf(" 9 - Decoding the Sui Bech32 private key string into a 32 raw seed bytes...\n"); + uint8_t private_key_output[32]; + start_time = millis(); + int decoding_result = microsui_decode_bech32_private_key(private_key_output, private_key_bech32_output); + end_time = millis(); + + // Calculate the time taken for decoding + uint64_t time_taken_decoding = end_time - start_time; + if(decoding_result == 0) { + printf("\t Decoding successful.\n\n"); + } else { + printf("\t Decoding failed --\n"); + printf("\t Error code: %d --\n\n", decoding_result); + } + + + + printf("\t MicroSui Benchmarks Results:\n"); + printf("\t Signatures:\n"); printf("\t\t Time taken for signing from Sui Message: "); if (time_taken_signature > 100000) { - printf("%llu ms\n", (unsigned long long)(time_taken_signature / 1000)); + printf("\t\t %llu ms\n", (unsigned long long)(time_taken_signature / 1000)); } else { - printf("%.2f ms (%llu us) \n", (double)time_taken_signature / 1000.0, (unsigned long long)time_taken_signature); + printf("\t\t %.2f ms (%llu us) \n", (double)time_taken_signature / 1000.0, (unsigned long long)time_taken_signature); } printf("\t\t Time taken for signing from precalculated digest: "); if (time_taken_signature_from_digest > 100000) { - printf("%llu ms\n", (unsigned long long)(time_taken_signature_from_digest / 1000)); + printf("\t %llu ms\n", (unsigned long long)(time_taken_signature_from_digest / 1000)); } else { - printf("%.2f ms (%llu us) \n", (double)time_taken_signature_from_digest / 1000.0, (unsigned long long)time_taken_signature_from_digest); + printf("\t %.2f ms (%llu us) \n", (double)time_taken_signature_from_digest / 1000.0, (unsigned long long)time_taken_signature_from_digest); } - printf("\t\t Time taken for verification from Sui Message: "); + printf("\n\t Signature Check / Verification:\n"); + printf("\t\t Time taken for sign check from Sui Message: "); if (time_taken_verification > 100000) { - printf("%llu ms\n", (unsigned long long)(time_taken_verification / 1000)); + printf("\t\t %llu ms\n", (unsigned long long)(time_taken_verification / 1000)); } else { - printf("%.2f ms (%llu us) \n", (double)time_taken_verification / 1000.0, (unsigned long long)time_taken_verification); + printf("\t\t %.2f ms (%llu us) \n", (double)time_taken_verification / 1000.0, (unsigned long long)time_taken_verification); } - printf("\t\t Time taken for verification from precalculated digest: "); + printf("\t\t Time taken for sign check from precalculated digest: "); if (time_taken_verification_from_digest > 100000) { - printf("%llu ms\n", (unsigned long long)(time_taken_verification_from_digest / 1000)); + printf("\t %llu ms\n", (unsigned long long)(time_taken_verification_from_digest / 1000)); + } else { + printf("\t %.2f ms (%llu us) \n", (double)time_taken_verification_from_digest / 1000.0, (unsigned long long)time_taken_verification_from_digest); + } + + printf("\n\t Key Management Operations:\n"); + printf("\t\t Time taken for deriving public key from seed: "); + if (time_taken_public_key_derivation > 100000) { + printf("\t\t %llu ms\n", (unsigned long long)(time_taken_public_key_derivation / 1000)); + } else { + printf("\t\t %.2f ms (%llu us) \n", (double)time_taken_public_key_derivation / 1000.0, (unsigned long long)time_taken_public_key_derivation); + } + + printf("\t\t Time taken for deriving keypair from seed: "); + if (time_taken_keypair_derivation > 100000) { + printf("\t\t %llu ms\n", (unsigned long long)(time_taken_keypair_derivation / 1000)); + } else { + printf("\t\t %.2f ms (%llu us) \n", (double)time_taken_keypair_derivation / 1000.0, (unsigned long long)time_taken_keypair_derivation); + } + + printf("\t\t Time taken for deriving Sui address from public key: "); + if (time_taken_address_derivation > 100000) { + printf("\t %llu ms\n", (unsigned long long)(time_taken_address_derivation / 1000)); + } else { + printf("\t %.2f ms (%llu us) \n", (double)time_taken_address_derivation / 1000.0, (unsigned long long)time_taken_address_derivation); + } + + printf("\n\t BECH32 Operations:\n"); + printf("\t\t Time taken for seed/private key bech32 encoding: "); + if (time_taken_encoding > 100000) { + printf("\t %llu ms\n", (unsigned long long)(time_taken_encoding / 1000)); + } else { + printf("\t %.2f ms (%llu us) \n", (double)time_taken_encoding / 1000.0, (unsigned long long)time_taken_encoding); + } + printf("\t\t Time taken for seed/private key bech32 decoding: "); + if (time_taken_decoding > 100000) { + printf("\t %llu ms\n", (unsigned long long)(time_taken_decoding / 1000)); } else { - printf("%.2f ms (%llu us) \n", (double)time_taken_verification_from_digest / 1000.0, (unsigned long long)time_taken_verification_from_digest); + printf("\t %.2f ms (%llu us) \n", (double)time_taken_decoding / 1000.0, (unsigned long long)time_taken_decoding); } printf("\n \tEnd of benchmarks.\n"); From 7a7abb1ff476edef533690369a9a8b93fea6c5b8 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Tue, 7 Apr 2026 15:37:31 +0300 Subject: [PATCH 6/9] improving bechmark example for GH workflow --- examples/core_examples/benchmark/benchmark.c | 32 ++++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/examples/core_examples/benchmark/benchmark.c b/examples/core_examples/benchmark/benchmark.c index 99a230a..79cdcbf 100644 --- a/examples/core_examples/benchmark/benchmark.c +++ b/examples/core_examples/benchmark/benchmark.c @@ -53,9 +53,15 @@ int main() { uint8_t sui_sig[97]; uint64_t start_time = millis(); - microsui_sign_ed25519(sui_sig, message, message_len, private_key_seed); + int sign_result = microsui_sign_ed25519(sui_sig, message, message_len, private_key_seed); uint64_t end_time = millis(); - printf("\t Signature created successfully\n\n"); + if(sign_result == 0) { + printf("\t Signature created successfully\n\n"); + } else { + printf("\t Signature creation failed --\n"); + printf("\t Error code: %d -- Aborting\n\n", sign_result); + return -1; + } // Calculate the time taken for verification uint64_t time_taken_signature = end_time - start_time; @@ -83,7 +89,8 @@ int main() { printf("\t Signature verified successfully\n\n"); } else { printf("\t Signature verification failed --\n"); - printf("\t Error code: %d --\n\n", verification_result); + printf("\t Error code: %d -- Aborting\n\n", verification_result); + return -1; } // 4. Verifying the Sui Signature from the precalculated digest and signature @@ -98,7 +105,8 @@ int main() { printf("\t Signature from digest verified successfully\n\n"); } else { printf("\t Signature verification failed --\n"); - printf("\t Error code: %d --\n\n", verification_result_from_digest); + printf("\t Error code: %d -- Aborting\n\n", verification_result_from_digest); + return -1; } /////// KEY MANAGEMENT /////// @@ -112,7 +120,8 @@ int main() { printf("\t Public key derived successfully.\n\n"); } else { printf("\t Public key derivation failed --\n\n"); - printf("\t Error code: %d --\n\n", public_key_derivation_result); + printf("\t Error code: %d -- Aborting\n\n", public_key_derivation_result); + return -1; } printf(" 6 - Deriving a Keypair (Secret Key + Public Key) from a 32-byte Ed25519 seed private key...\n"); @@ -126,7 +135,8 @@ int main() { printf("\t Keypair derived successfully.\n\n"); } else { printf("\t Keypair derivation failed --\n\n"); - printf("\t Error code: %d --\n\n", keypair_derivation_result); + printf("\t Error code: %d -- Aborting\n\n", keypair_derivation_result); + return -1; } printf(" 7 - Deriving a Sui address from a 32-byte Ed25519 public key...\n"); @@ -142,7 +152,8 @@ int main() { printf("\n\n"); } else { printf("\t Sui address derivation failed --\n\n"); - printf("\t Error code: %d --\n\n", address_derivation_result); + printf("\t Error code: %d -- Aborting\n\n", address_derivation_result); + return -1; } @@ -159,7 +170,8 @@ int main() { printf("\t Encoding successful. Encoded Bech32 Key: %s\n\n", private_key_bech32_output); } else { printf("\t Encoding failed --\n"); - printf("\t Error code: %d --\n\n", encoding_result); + printf("\t Error code: %d -- Aborting\n\n", encoding_result); + return -1; } printf(" 9 - Decoding the Sui Bech32 private key string into a 32 raw seed bytes...\n"); @@ -174,11 +186,11 @@ int main() { printf("\t Decoding successful.\n\n"); } else { printf("\t Decoding failed --\n"); - printf("\t Error code: %d --\n\n", decoding_result); + printf("\t Error code: %d -- Aborting\n\n", decoding_result); + return -1; } - printf("\t MicroSui Benchmarks Results:\n"); printf("\t Signatures:\n"); printf("\t\t Time taken for signing from Sui Message: "); From c55b0e06b581e76a66fd35b12797feaf8a4af833 Mon Sep 17 00:00:00 2001 From: Gustavo <44475146+Gustbel@users.noreply.github.com> Date: Tue, 7 Apr 2026 15:33:59 +0200 Subject: [PATCH 7/9] Fix/malfunction in signature generation (#21) * added job in GH workflow and renamed to `ci.yml` * fixed error in signature generation --- .github/workflows/build.yml | 24 ------------------- .github/workflows/ci.yml | 46 +++++++++++++++++++++++++++++++++++++ src/microsui_core/sign.c | 4 ++-- 3 files changed, 48 insertions(+), 26 deletions(-) delete mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 53ab524..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Build and Test - -on: - push: - branches: ["**"] - pull_request: - branches: ["**"] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install build tools - run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev - - - name: Run make - run: make - - - name: Confirm success - run: echo "Makefile executed successfully" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2798f40 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: MicroSui lib GitHub Actions CI + +on: + push: + branches: ["**"] + pull_request: + branches: ["**"] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install build tools + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev + + - name: Run make + run: make + + - name: Confirm success + run: echo "Makefile executed successfully" + + selftest: + runs-on: ubuntu-latest + defaults: + run: + working-directory: examples/core_examples/benchmark + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install build tools + run: sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev + + - name: Run make + run: make + + - name: Run benchmark + run: ./benchmark.out + + - name: Confirm success + run: echo "Selftest completed successfully" diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index 0ea38fb..affb393 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -71,7 +71,7 @@ int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const crypto_blake2b_final(&ctx, digest); // 4. Sign the digest and build the Sui signature - microsui_sign_ed25519_from_digest(sui_sig_out, secret_key, public_key, digest); + microsui_sign_ed25519_from_digest(sui_sig_out, digest, secret_key, public_key); crypto_wipe(secret_key, sizeof secret_key); crypto_wipe(seed_cp, sizeof seed_cp); @@ -118,7 +118,7 @@ void microsui_sign_ed25519_with_keys(uint8_t sui_sig_out[97], const uint8_t* mes crypto_blake2b_final(&ctx, digest); - microsui_sign_ed25519_from_digest(sui_sig_out, secret_key, public_key, digest); + microsui_sign_ed25519_from_digest(sui_sig_out, digest, secret_key, public_key); crypto_wipe(&ctx, sizeof ctx); crypto_wipe(digest, sizeof digest); From 7fd5d91d19b0803d78dc86d6cdfb33236c2a3c22 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Tue, 7 Apr 2026 17:18:15 +0300 Subject: [PATCH 8/9] Remove unused errno.h include from sign.c --- src/microsui_core/sign.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index affb393..098251c 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "lib/monocypher/monocypher.h" #include "byte_conversions.h" From 58a85b6ccf52852cae719f5e65a815861ee9d8f4 Mon Sep 17 00:00:00 2001 From: Gustbel Date: Tue, 7 Apr 2026 17:19:05 +0300 Subject: [PATCH 9/9] Update changelog and version to 0.3.4 --- CHANGELOG.md | 11 +++++++++++ library.json | 2 +- library.properties | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36d11b4..a2fae98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ 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.0.html). +## \[0.3.4] - 2026-04-07 + +This release introduces lower-level signing primitives designed for resource-constrained microcontrollers, allowing developers to work directly with pre-computed **_BLAKE2b digests_** (significantly reducing the data that needs to be transferred between components) or skip redundant steps when intermediate values such as the derived keypair are already available in memory. + +- Added `microsui_sign_ed25519_from_digest()`: accepts a pre-computed _32-byte BLAKE2b digest_ instead of the _full transaction message_, significantly reducing the data that needs to be transferred between components, a critical advantage in embedded communication pipelines where bandwidth and memory are limited. +- Added `microsui_sign_ed25519_from_keypair()`: accepts a precomputed keypair directly, avoiding redundant key derivation. +- Added new keypair derivation function. +- Improved benchmark to cover all new operations. + +--- + ## \[0.3.3] - 2026-04-01 - Added new mod functions to Monocypher library (these functions are more efficient than the compact25519 ones). diff --git a/library.json b/library.json index 136a198..3ee0655 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "microsui-lib", - "version": "0.3.3", + "version": "0.3.4", "description": "MicroSui Library is a lightweight C library for embedded systems to interact with the Sui Network Blockchain", "keywords": "microsui, sui, blockchain, sui-network, walrus, cryptography, c-library", "repository": { diff --git a/library.properties b/library.properties index 76cd5f4..c918d01 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=MicroSui -version=0.3.3 +version=0.3.4 author=Gustavo Belbruno maintainer=Gustavo Belbruno sentence=Pure C library for interacting with the Sui Network blockchain from microcontrollers.