diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..53ab524 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,24 @@ +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/CHANGELOG.md b/CHANGELOG.md index 5d8792e..36d11b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,22 @@ 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.3] - 2026-04-01 + +- Added new mod functions to Monocypher library (these functions are more efficient than the compact25519 ones). +- Implemented new functions in `microsui_sign.c`, replacing the compact25519 ones. +- Deleted the now-obsolete _compact25519 library_. +- Refactor: rename output parameters for consistency in core functions. +- Refactor: `private/secret key` in bytes now is renamed to `seed` for avoid imprecisions. +- Added new Signature verification/check with public key function. +- Added new examples (Signature and Benchmark). +- Updated Makefiles. +- Added GitHub `make` workflow. +- General improvements and minor bugs fixed. + ## \[0.3.2] - 2026-01-27 -This release introduces ***Signature Verification*** support and improves developer experience with clearer examples. +This release introduces **_Signature Verification_** support and improves developer experience with clearer examples. ### Added diff --git a/Makefile b/Makefile index 3a39421..ee04764 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,6 @@ all: fi \ done @echo "" - @echo "✅ All examples built successfully!" @echo "---------------------------------------" @for dir in $(EXAMPLE_DIRS); do \ if [ -f $$dir/Makefile ]; then \ @@ -23,4 +22,7 @@ all: fi \ fi \ done + @echo "" + @echo "✅ All examples built successfully!" @echo "---------------------------------------" + diff --git a/README.md b/README.md index 639cc29..75637b2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -*MicroSui Library* is a lightweight C library designed primarily for embedded systems to interact with the ***Sui Network Blockchain***. +_MicroSui Library_ is a lightweight C library designed primarily for embedded systems to interact with the **_Sui Network Blockchain_**. Full compatibility with _ESP32 microcontrollers_ and _traditional desktop OS_. More device support coming soon. @@ -11,6 +11,10 @@ This library is **_Arduino and PlatformIO Compatible_** [![microsui-lib on Arduino Registry](https://www.ardu-badge.com/badge/MicroSui.svg)](https://www.ardu-badge.com/MicroSui/ide) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/gustavogb/library/microsui-lib.svg)](https://registry.platformio.org/libraries/gustavogb/microsui-lib) +### Documentation API Reference Page: + +[![Docs](https://img.shields.io/badge/docs-docs.microsui.com-blue?logo=bookstack&logoColor=white)](https://docs.microsui.com) + ## The Library: ### Build all the examples: @@ -22,7 +26,7 @@ In Windows, macOS or Linux it will be necessary to install `cURL`: ##### In Linux: ``` -sudo apt install -y libcurl4-openssl-dev pkg-config build-essential +sudo apt-get update && sudo apt-get install -y libcurl4-openssl-dev ``` ##### In macOS: @@ -45,7 +49,11 @@ In root, run make ``` -You will find the `.out` binaries to run in each example folder. +You will find the `.out` binaries to run in each example folder. Run every example with + +```bash +./example.out +``` ## Project Directory Structure: @@ -58,8 +66,6 @@ microsui-lib/ │ ├── microsui_core │ │ ├── lib/ # Third-party dependencies │ │ │ ├── monocypher/ -│ │ │ ├── compact25519/ -│ │ │ │ └── c25519/ │ │ │ └── jsmn/ │ │ ├── impl/ # Platform/board specific implementation │ │ │ ├── http/ @@ -89,9 +95,7 @@ microsui-lib/ ### 📦 Dependencies (`/lib`) - `monocypher`: - Lightweight cryptographic primitives. -- `compact25519`: - Ed25519 key format support. + Lightweight Ed25519 cryptographic primitives. - `jsmn`: Lightweight minimalistic JSON parser for C. diff --git a/examples/ArduinoExamples/OfflineSign/OfflineSign.ino b/examples/ArduinoExamples/OfflineSign/OfflineSign.ino index 38b9d7c..c760047 100644 --- a/examples/ArduinoExamples/OfflineSign/OfflineSign.ino +++ b/examples/ArduinoExamples/OfflineSign/OfflineSign.ino @@ -1,3 +1,4 @@ +#include #include // --- PRIVATE KEY (EXAMPLE / DO NOT USE IN PRODUCTION) --- @@ -15,7 +16,7 @@ void setup() { delay(500); Serial.println(); - Serial.println(F("=== MicroSui ESP32 — Offline Sign Transaction Message - Obtain Sui Signature with PK ===")); + Serial.println(F("=== MicroSui Arduino — Offline Sign Transaction Message - Obtain Sui Signature with PK ===")); // 1) Load keypair from Bech32 secret key Serial.println(F("\n [1/2] Loading keypair from Bech32...")); diff --git a/examples/ArduinoExamples/SignAndExecuteTransaction/SignAndExecuteTransaction.ino b/examples/ArduinoExamples/SignAndExecuteTransaction/SignAndExecuteTransaction.ino index 13a4b0d..ccc15ec 100644 --- a/examples/ArduinoExamples/SignAndExecuteTransaction/SignAndExecuteTransaction.ino +++ b/examples/ArduinoExamples/SignAndExecuteTransaction/SignAndExecuteTransaction.ino @@ -1,3 +1,4 @@ +#include #include // --- WiFi credentials (example) --- @@ -22,7 +23,8 @@ void setup() { delay(500); Serial.println(); - Serial.println(F("=== MicroSui ESP32 — Sign & Execute Transaction ===")); + Serial.println(F("=== MicroSui Arduino — Sign & Execute Transaction ===")); + Serial.println(F("=== Note: This example is guaranteed to work on ESP32 family, but may not work on other boards for the moment ===")); // 1) Connect WiFi Serial.println(F("\n [1/5] Connecting WiFi...")); diff --git a/examples/ArduinoExamples/SignatureBechmark/SignatureBechmark.ino b/examples/ArduinoExamples/SignatureBechmark/SignatureBechmark.ino new file mode 100644 index 0000000..4d9cf51 --- /dev/null +++ b/examples/ArduinoExamples/SignatureBechmark/SignatureBechmark.ino @@ -0,0 +1,65 @@ +#include +#include + +// Sample Sui message and private key for testing +const uint8_t private_key[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}; +const char *message_hex = "00000200080065cd1d0000000000202e3d52393c9035afd1ef38abd7fce2dad71f0e276b522fb274f4e14d1df974720202000101000001010300000000010100d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379d0180dc491e55e7caabfcdd1b0f538928d8d54107b9c1def3ed0baa3aa5106ba8674f0dd01400000000204b7e9da00f30cd1edf4d40710213c15a862e1fc175f2edb2b2c870c8559d65cdd79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379de80300000000000040ab3c000000000000"; + +size_t message_len; +uint8_t message[512]; +uint8_t sui_sig[97]; + +void setup() +{ + Serial.begin(115200); + + message_len = strlen(message_hex) / 2; // 2 hex chars = 1 byte + hex_to_bytes(message_hex, message, message_len); +} + +void loop() +{ + Serial.println(F("=== MicroSui Arduino — Bechmark Signature and Verification ===")); + // Creating Signature + Serial.println(F("\n\n Generating Signature...\n")); + + unsigned long start_time = millis(); + microsui_sign_ed25519(sui_sig, message, message_len, private_key); + unsigned long end_time = millis(); + // Calculate the time taken for signing + unsigned long time_taken_signature = end_time - start_time; + + Serial.println(F("\t Signature created successfully\n")); + + // Validating Signature + Serial.println(F(" Verifying Signature...\n")); + start_time = millis(); + int verification_result = microsui_verify_signature(sui_sig, message, message_len); + end_time = millis(); + // Calculate the time taken for verification + unsigned long time_taken_verification = end_time - start_time; + + if(verification_result == 0) { + Serial.println(F("\t Signature verified successfully\n\n")); + } else { + Serial.println(F("\t Signature verification failed\n")); + Serial.print(F("\t Error code: ")); + Serial.println(verification_result); + } + + Serial.print(F(" Time taken for signing: ")); + Serial.print(time_taken_signature); + Serial.println(F(" ms")); + + Serial.print(F(" Time taken for verification: ")); + Serial.print(time_taken_verification); + Serial.println(F(" ms\n")); + + Serial.println(F(" Done.")); + + delay(1000); +} \ No newline at end of file diff --git a/examples/ArduinoExamples/ValidatingSignatures/ValidatingSignatures.ino b/examples/ArduinoExamples/ValidatingSignatures/ValidatingSignatures.ino index 5f4ef7a..b2dffa5 100644 --- a/examples/ArduinoExamples/ValidatingSignatures/ValidatingSignatures.ino +++ b/examples/ArduinoExamples/ValidatingSignatures/ValidatingSignatures.ino @@ -1,3 +1,4 @@ +#include #include // --- PRIVATE KEY (EXAMPLE / DO NOT USE IN PRODUCTION) --- @@ -15,7 +16,7 @@ void setup() delay(500); Serial.println(); - Serial.println(F("=== MicroSui ESP32 — Validation of a Sui Signature ===")); + Serial.println(F("=== MicroSui Arduino — Validation of a Sui Signature ===")); // 1) Generating Keypair, and Transactions Objects Serial.println(F("\n [1/4] Generating Keypair, and Transactions Objects...")); @@ -47,7 +48,7 @@ void setup() // 4) Validating Message2 with the signature (Must be FAILED) Serial.println(F("\n [4/4] Validating Message2 with the signature (Must be FAILED)...")); int verification_result_2 = microsui_verify_signature(sig.bytes, tx2.tx_bytes.data, tx2.tx_bytes.length); - if (verification_result_2 == 0) + if (verification_result_2 != 0) Serial.println(F("\t - Signature Verification is FAILED for Message 2 -- OK\n\n")); Serial.println(F(" Done.")); diff --git a/examples/core_examples/benchmarks/Makefile b/examples/core_examples/benchmarks/Makefile new file mode 100644 index 0000000..72a186d --- /dev/null +++ b/examples/core_examples/benchmarks/Makefile @@ -0,0 +1,47 @@ +ROOT_DIR := ../../.. +SRC := $(ROOT_DIR)/src +INCLUDE := $(ROOT_DIR)/include +MICROSUI_CORE := $(ROOT_DIR)/src/microsui_core +UTILS := $(MICROSUI_CORE)/utils +LIB := $(MICROSUI_CORE)/lib + +MONOCYPHER := $(LIB)/monocypher +JSMN := $(LIB)/jsmn + +HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system +HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support +HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 -lcrypt32) + +WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c +WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support + +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) + +SOURCES := benchmarks.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ + $(wildcard $(MONOCYPHER)/*.c) \ + $(HTTP_CURL_FILE) \ + $(HTTP_UNSUPPORTED_FILE) \ + $(WIFI_DESKTOP_FILE) \ + $(WIFI_UNSUPPORTED_FILE) + +OUTPUT := benchmarks.out + +all: clean_before_build $(OUTPUT) + +$(OUTPUT): $(SOURCES) + @echo "Compiling example: $@" + gcc $(CFLAGS) $^ -o $@ $(HTTP_LIBS) + +.PHONY: clean clean_before_build + +clean_before_build: + @echo "Cleaning old binary if it exists..." + @rm -f $(OUTPUT) + +clean: + @echo "Removing binary..." + @rm -f $(OUTPUT) \ No newline at end of file diff --git a/examples/core_examples/benchmarks/benchmarks.c b/examples/core_examples/benchmarks/benchmarks.c new file mode 100644 index 0000000..2d8b95b --- /dev/null +++ b/examples/core_examples/benchmarks/benchmarks.c @@ -0,0 +1,95 @@ +#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/examples/core_examples/decoding_rpc_json/Makefile b/examples/core_examples/decoding_rpc_json/Makefile index 492ddcf..f05cc45 100644 --- a/examples/core_examples/decoding_rpc_json/Makefile +++ b/examples/core_examples/decoding_rpc_json/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := decoding_rpc_json.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ @@ -48,4 +44,4 @@ clean_before_build: clean: @echo "Removing binary..." - @rm -f $(OUTPUT) + @rm -f $(OUTPUT) \ No newline at end of file diff --git a/examples/core_examples/decoding_rpc_json/decoding_rpc_json.c b/examples/core_examples/decoding_rpc_json/decoding_rpc_json.c index 648bf16..2e668c7 100644 --- a/examples/core_examples/decoding_rpc_json/decoding_rpc_json.c +++ b/examples/core_examples/decoding_rpc_json/decoding_rpc_json.c @@ -1,7 +1,8 @@ #include #include #include -#include "microsui/rpc_json_decoder.h" + +#include "MicroSui.h" int main() { printf("\t\t Generate Sui Treansaction Block Response Object from RPC JSON Response\n\n"); diff --git a/examples/core_examples/encode_conversions/Makefile b/examples/core_examples/encode_conversions/Makefile index 8ab9161..5d43411 100644 --- a/examples/core_examples/encode_conversions/Makefile +++ b/examples/core_examples/encode_conversions/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := encode_conversions.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/core_examples/encode_conversions/encode_conversions.c b/examples/core_examples/encode_conversions/encode_conversions.c index 2e26741..876d96e 100644 --- a/examples/core_examples/encode_conversions/encode_conversions.c +++ b/examples/core_examples/encode_conversions/encode_conversions.c @@ -1,8 +1,8 @@ #include #include #include -#include "microsui/byte_conversions.h" +#include "MicroSui.h" int main() { printf("\t\t Byte / HEXA and BASE64 CONVERSION examples:\n"); diff --git a/examples/core_examples/encode_decode_privkey/Makefile b/examples/core_examples/encode_decode_privkey/Makefile index 1f83f4f..f1407f3 100644 --- a/examples/core_examples/encode_decode_privkey/Makefile +++ b/examples/core_examples/encode_decode_privkey/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := encode_decode_privkey.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/core_examples/encode_decode_privkey/encode_decode_privkey.c b/examples/core_examples/encode_decode_privkey/encode_decode_privkey.c index 3df7420..e359033 100644 --- a/examples/core_examples/encode_decode_privkey/encode_decode_privkey.c +++ b/examples/core_examples/encode_decode_privkey/encode_decode_privkey.c @@ -1,7 +1,8 @@ #include #include #include -#include "microsui/cryptography.h" + +#include "MicroSui.h" const char *private_key_1_bech32 = "suiprivkey1qqqsyqcyq5rqwzqfpg9scrgwpugpzysnzs23v9ccrydpk8qarc0jqa4ffsr"; @@ -17,7 +18,7 @@ int main() { printf("\t1 - decode_sui_privkey:\n"); uint8_t private_key_output[32]; - if (microsui_decode_sui_privkey(private_key_1_bech32, private_key_output) == 0) { + if (microsui_decode_bech32_private_key(private_key_output, private_key_1_bech32) == 0) { printf("Original Bech32 Key: %s\n", private_key_1_bech32); printf("Decoded Key: "); for (int i = 0; i < 32; i++) { @@ -30,7 +31,7 @@ int main() { printf("\n\n\t2 - encode_sui_privkey:\n"); char private_key_bech32_output[71]; - if (microsui_encode_sui_privkey(private_key_2, private_key_bech32_output) == 0) { + if (microsui_encode_bech32_private_key(private_key_bech32_output, private_key_2) == 0) { printf("Original Hexa Key: "); for (int i = 0; i < 32; i++) { printf("%02x", private_key_2[i]); diff --git a/examples/core_examples/offline_sign/Makefile b/examples/core_examples/offline_sign/Makefile index 59269aa..56329d1 100644 --- a/examples/core_examples/offline_sign/Makefile +++ b/examples/core_examples/offline_sign/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := offline_sign.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/core_examples/offline_sign/offline_sign.c b/examples/core_examples/offline_sign/offline_sign.c index 776915d..f63cf9e 100644 --- a/examples/core_examples/offline_sign/offline_sign.c +++ b/examples/core_examples/offline_sign/offline_sign.c @@ -1,14 +1,14 @@ #include #include #include -#include "microsui/sign.h" -#include "microsui/byte_conversions.h" + +#include "MicroSui.h" // Sui Message in hex format (this message must be signed) const char* message_hex = "00000200080065cd1d0000000000202e3d52393c9035afd1ef38abd7fce2dad71f0e276b522fb274f4e14d1df974720202000101000001010300000000010100d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379d0180dc491e55e7caabfcdd1b0f538928d8d54107b9c1def3ed0baa3aa5106ba8674f0dd01400000000204b7e9da00f30cd1edf4d40710213c15a862e1fc175f2edb2b2c870c8559d65cdd79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379de80300000000000040ab3c000000000000"; -// You must place your PK (in bytes format) here. -const uint8_t private_key[32] = { +// You must place your seed private key / secret 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, @@ -16,7 +16,7 @@ const uint8_t private_key[32] = { }; int main() { - printf("\n\t\t\t --- SUI OFFLINE SIGN DEMO ---\n"); + printf("\n\t\t\t --- Microsui - Sui OFFLINE Signature ---\n"); printf("\n\tOriginal Message: %s", message_hex); // Converting the message from hex to bytes @@ -24,10 +24,10 @@ int main() { uint8_t message[message_len]; hex_to_bytes(message_hex, message, message_len); - // Generating the Sui Signature from the message and private key (private_key is in constant.h) + // Generating the Sui Signature from the message and private key uint8_t sui_sig[97]; printf("\n\n\n Generating Signature...\n"); - microsui_sign_ed25519(sui_sig, message, message_len, private_key); + microsui_sign_ed25519(sui_sig, message, message_len, private_key_seed); printf("\t Signature created successfully\n"); // Verifying the Sui Signature diff --git a/examples/core_examples/offline_sign_with_bech32_privkey/Makefile b/examples/core_examples/offline_sign_with_bech32_privkey/Makefile index 73cfcfe..91ad073 100644 --- a/examples/core_examples/offline_sign_with_bech32_privkey/Makefile +++ b/examples/core_examples/offline_sign_with_bech32_privkey/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := offline_sign_with_bech32_privkey.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/core_examples/offline_sign_with_bech32_privkey/offline_sign_with_bech32_privkey.c b/examples/core_examples/offline_sign_with_bech32_privkey/offline_sign_with_bech32_privkey.c index 3e800ed..1e4c2c5 100644 --- a/examples/core_examples/offline_sign_with_bech32_privkey/offline_sign_with_bech32_privkey.c +++ b/examples/core_examples/offline_sign_with_bech32_privkey/offline_sign_with_bech32_privkey.c @@ -1,9 +1,8 @@ #include #include #include -#include "microsui/sign.h" -#include "microsui/cryptography.h" -#include "microsui/byte_conversions.h" + +#include "MicroSui.h" // Sui Message in hex format (this message must be signed) const char* message_hex = "00000200080065cd1d0000000000202e3d52393c9035afd1ef38abd7fce2dad71f0e276b522fb274f4e14d1df974720202000101000001010300000000010100d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379d0180dc491e55e7caabfcdd1b0f538928d8d54107b9c1def3ed0baa3aa5106ba8674f0dd01400000000204b7e9da00f30cd1edf4d40710213c15a862e1fc175f2edb2b2c870c8559d65cdd79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379de80300000000000040ab3c000000000000"; @@ -11,14 +10,13 @@ const char* message_hex = "00000200080065cd1d0000000000202e3d52393c9035afd1ef38a // You must place your bech32 private key here const char *private_key_bech32 = "suiprivkey1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq509duq"; - int main() { - printf("\n\t\t\t --- SUI OFFLINE SIGN DEMO (with Bech32 Private Key) ---\n"); + printf("\n\t\t\t --- Microsui - Sui OFFLINE Signature (with Bech32 Private Key) ---\n"); printf("\n\tOriginal Message: %s", message_hex); // Decoding the Bech32 private key to bytes uint8_t private_key[32]; - if (microsui_decode_sui_privkey(private_key_bech32, private_key) != 0) { + if (microsui_decode_bech32_private_key(private_key, private_key_bech32) != 0) { printf("Invalid Bech32 private key.\n"); return -1; } diff --git a/examples/core_examples/prepare_and_send_transaction/Makefile b/examples/core_examples/prepare_and_send_transaction/Makefile index 7e023bf..0af221c 100644 --- a/examples/core_examples/prepare_and_send_transaction/Makefile +++ b/examples/core_examples/prepare_and_send_transaction/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := prepare_and_send_transaction.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/core_examples/prepare_and_send_transaction/prepare_and_send_transaction.c b/examples/core_examples/prepare_and_send_transaction/prepare_and_send_transaction.c index 17a5e7f..cf9afbc 100644 --- a/examples/core_examples/prepare_and_send_transaction/prepare_and_send_transaction.c +++ b/examples/core_examples/prepare_and_send_transaction/prepare_and_send_transaction.c @@ -2,9 +2,8 @@ #include #include #include -#include "microsui/byte_conversions.h" -#include "microsui/rpc_json_builder.h" -#include "microsui/http_router.h" + +#include "MicroSui.h" // Sui Message and Signature in hex format const char* sui_message = "0000020008c0320a030000000000202e3d52393c9035afd1ef38abd7fce2dad71f0e276b522fb274f4e14d1df974720202000101000001010300000000010100d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379d0115bc7e3113dfaebc7bdb30676e56e6ff651365235b74a202cbb1e73f57eaeb78600fd0140000000020c00463b22a32bebcb028b264d61bfa963c3f6a82bd7487c52bec8b2bf0c0e373d79a4c7a655aa80cf92069bbac9666705f1d7181ff9c2d59efbc7e6ec4c3379de80300000000000040ab3c000000000000"; diff --git a/examples/core_examples/verify_signatures/Makefile b/examples/core_examples/verify_signatures/Makefile new file mode 100644 index 0000000..5ebd888 --- /dev/null +++ b/examples/core_examples/verify_signatures/Makefile @@ -0,0 +1,47 @@ +ROOT_DIR := ../../.. +SRC := $(ROOT_DIR)/src +INCLUDE := $(ROOT_DIR)/include +MICROSUI_CORE := $(ROOT_DIR)/src/microsui_core +UTILS := $(MICROSUI_CORE)/utils +LIB := $(MICROSUI_CORE)/lib + +MONOCYPHER := $(LIB)/monocypher +JSMN := $(LIB)/jsmn + +HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system +HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support +HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 -lcrypt32) + +WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c +WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support + +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) + +SOURCES := verify_signatures.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ + $(wildcard $(MONOCYPHER)/*.c) \ + $(HTTP_CURL_FILE) \ + $(HTTP_UNSUPPORTED_FILE) \ + $(WIFI_DESKTOP_FILE) \ + $(WIFI_UNSUPPORTED_FILE) + +OUTPUT := verify_signatures.out + +all: clean_before_build $(OUTPUT) + +$(OUTPUT): $(SOURCES) + @echo "Compiling example: $@" + gcc $(CFLAGS) $^ -o $@ $(HTTP_LIBS) + +.PHONY: clean clean_before_build + +clean_before_build: + @echo "Cleaning old binary if it exists..." + @rm -f $(OUTPUT) + +clean: + @echo "Removing binary..." + @rm -f $(OUTPUT) \ No newline at end of file diff --git a/examples/core_examples/verify_signatures/verify_signatures.c b/examples/core_examples/verify_signatures/verify_signatures.c new file mode 100644 index 0000000..8b6755e --- /dev/null +++ b/examples/core_examples/verify_signatures/verify_signatures.c @@ -0,0 +1,56 @@ +#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 / secret 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 +}; + +int main() { + printf("\n\t\t\t --- Sui Signature Verification ---\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"); + microsui_sign_ed25519(sui_sig, message, message_len, private_key_seed); + printf("\t Signature created successfully\n\n"); + + // Verifying the Sui Signature + int verification_result = microsui_verify_signature(sui_sig, message, message_len); + if(verification_result == 0) { + printf("\t 1 - Signature verified successfully\n"); + } else { + printf("\t Signature verification failed\n"); + printf("\t Error code: %d\n\n", verification_result); + } + + // Veryfing the Sui Signature with the expected public key (derived from the seed private key) + uint8_t public_key[32]; + microsui_derive_public_key_ed25519(public_key, private_key_seed); + verification_result = microsui_verify_signature_ed25519_with_public_key(sui_sig, message, message_len, public_key); + if(verification_result == 0) { + printf("\t 2 - Signature verified successfully with public key validation\n"); + } else { + printf("\t Signature verification with public key validation failed\n"); + printf("\t Error code: %d\n\n", verification_result); + } + + printf("\n\t SIGNATURE must be sended to the Gateway to be broadcasted to the Sui Network...\n"); + + return 0; +} \ No newline at end of file diff --git a/examples/sdk_examples/client_demo/Makefile b/examples/sdk_examples/client_demo/Makefile index 17bb2f0..8e6bcb7 100644 --- a/examples/sdk_examples/client_demo/Makefile +++ b/examples/sdk_examples/client_demo/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := client_demo.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/sdk_examples/keypair_demo/Makefile b/examples/sdk_examples/keypair_demo/Makefile index 59e74ef..3c85a26 100644 --- a/examples/sdk_examples/keypair_demo/Makefile +++ b/examples/sdk_examples/keypair_demo/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := keypair_demo.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/sdk_examples/transaction_demo/Makefile b/examples/sdk_examples/transaction_demo/Makefile index 57e6b1a..f0fac57 100644 --- a/examples/sdk_examples/transaction_demo/Makefile +++ b/examples/sdk_examples/transaction_demo/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := transaction_demo.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/sdk_examples/validating_signature/Makefile b/examples/sdk_examples/validating_signature/Makefile index 7952c18..c51d40b 100644 --- a/examples/sdk_examples/validating_signature/Makefile +++ b/examples/sdk_examples/validating_signature/Makefile @@ -6,9 +6,7 @@ UTILS := $(MICROSUI_CORE)/utils LIB := $(MICROSUI_CORE)/lib MONOCYPHER := $(LIB)/monocypher -COMPACT := $(LIB)/compact25519 -C25519 := $(COMPACT)/c25519 -JSMN := $(LIB)/JSMN +JSMN := $(LIB)/jsmn HTTP_CURL_FILE = $(MICROSUI_CORE)/impl/http/http_curl.c # This Makefile needs cURL installed in the system HTTP_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/http/http_unsupported.c # This file is used when make is made on a system without cURL support @@ -17,16 +15,14 @@ HTTP_LIBS = -lcurl $(if $(filter Windows_NT,$(OS)),-lws2_32 -lbcrypt -lwldap32 - WIFI_DESKTOP_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_desktop.c WIFI_UNSUPPORTED_FILE = $(MICROSUI_CORE)/impl/wifi/wifi_unsupported.c # This file is used when make is made on a system without WiFi support -CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(COMPACT) -I$(C25519) -I$(JSMN) +CFLAGS := -Wall -Wextra -I$(INCLUDE) -I$(SRC) -I$(MICROSUI_CORE) -I$(UTILS) -I$(LIB) -I$(MONOCYPHER) -I$(JSMN) SOURCES := validating_signature.c \ - $(SRC)/*.c \ - $(MICROSUI_CORE)/*.c \ - $(UTILS)/*.c \ - $(JSMN)/*.c \ + $(wildcard $(SRC)/*.c) \ + $(wildcard $(MICROSUI_CORE)/*.c) \ + $(wildcard $(UTILS)/*.c) \ + $(wildcard $(JSMN)/*.c) \ $(wildcard $(MONOCYPHER)/*.c) \ - $(wildcard $(COMPACT)/*.c) \ - $(wildcard $(C25519)/*.c) \ $(HTTP_CURL_FILE) \ $(HTTP_UNSUPPORTED_FILE) \ $(WIFI_DESKTOP_FILE) \ diff --git a/examples/sdk_examples/validating_signature/validating_signature.c b/examples/sdk_examples/validating_signature/validating_signature.c index 9bdf649..6531731 100644 --- a/examples/sdk_examples/validating_signature/validating_signature.c +++ b/examples/sdk_examples/validating_signature/validating_signature.c @@ -37,7 +37,7 @@ int main(void) { printf("\t - Signature Verification is CORRECT for Message 1 -- OK\n"); // Validation with message 2 (incorrect) int verification_result_2 = microsui_verify_signature(sig.bytes, tx2.tx_bytes.data, tx2.tx_bytes.length); - if(verification_result_2 == -1) + if(verification_result_2 != 0) printf("\t - Signature Verification is FAILED for Message 2 -- OK\n"); printf("\n\n\t\t --- END OF TRANSACTION DEMO ---\n"); diff --git a/library.json b/library.json index 9cb5bb3..136a198 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "microsui-lib", - "version": "0.3.2", + "version": "0.3.3", "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": { @@ -22,9 +22,7 @@ "srcDir": "src", "includeDir": "include", "flags": [ - "-Isrc/microsui_core/lib/monocypher", - "-Isrc/microsui_core/lib/compact25519", - "-Isrc/microsui_core/lib/compact25519/c25519" + "-Isrc/microsui_core/lib/monocypher" ], "srcFilter": [ "+<*.c>", @@ -32,8 +30,6 @@ "+", "+", "+", - "+", - "+", "+", "-", "-", diff --git a/library.properties b/library.properties index 70138fc..76cd5f4 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=MicroSui -version=0.3.2 +version=0.3.3 author=Gustavo Belbruno maintainer=Gustavo Belbruno sentence=Pure C library for interacting with the Sui Network blockchain from microcontrollers. diff --git a/src/Keypair.c b/src/Keypair.c index 3139c28..325617c 100644 --- a/src/Keypair.c +++ b/src/Keypair.c @@ -8,7 +8,8 @@ * * Features: * - Generate random keypairs from entropy. - * - Initialize a keypair from a Bech32-encoded secret key string. + * - Initialize a keypair from a Sui Bech32-encoded private key string (also called + * "Secret Key" in the Mysten Labs TypeScript SDK). * - Sign transaction messages with Ed25519. * - Retrieve the secret key (Bech32), public key (raw bytes), and * derive the Sui-formatted address. @@ -17,7 +18,10 @@ * - Functions returning strings or buffers use static internal storage. * Results will be overwritten by subsequent calls and are not thread-safe. * - All cryptographic primitives are delegated to the MicroSui core modules. - * + * - Mysten Labs' TypeScript SDK uses the term "Secret Key" for the Sui Bech32 encoded + * private key string. To maintain consistency with the TypeScript SDK, the naming + * convention "Secret Key" is used here regarding the Sui Bech32-encoded private key. + * * Inspired by the Mysten Labs TypeScript SDK, adapted for embedded C. */ @@ -48,7 +52,7 @@ typedef struct { typedef struct MicroSuiEd25519 MicroSuiEd25519; struct MicroSuiEd25519 { - uint8_t secret_key[32]; + uint8_t seed[32]; // OO-style methods SuiSignature (*signTransaction)(MicroSuiEd25519 *self, const char *msg); @@ -60,7 +64,7 @@ struct MicroSuiEd25519 { // ========================== // Constructor prototypes // ========================== -MicroSuiEd25519 SuiKeypair_generate(uint8_t seed_extra); +MicroSuiEd25519 SuiKeypair_generate(uint8_t rng_entropy); MicroSuiEd25519 SuiKeypair_fromSecretKey(const char *sk); // ========================== @@ -82,19 +86,21 @@ static const char* ms_toSuiAddress_impl(MicroSuiEd25519 *self); * Function pointers for signing, retrieving keys, and deriving the * Sui address are also assigned. * - * @param[in] seed_extra Extra seed mixed with current time to initialize PRNG. + * @param[in] rng_entropy High-quality entropy from hardware (ADC noise, + * temperature jitter, etc.) or very high-quality software entropy. + * Should NOT be predictable. * * @return Initialized MicroSuiEd25519 struct. */ -MicroSuiEd25519 SuiKeypair_generate(uint8_t seed_extra) { +MicroSuiEd25519 SuiKeypair_generate(uint8_t rng_entropy) { MicroSuiEd25519 kp; memset(&kp, 0, sizeof(kp)); // Generate a random secret key - unsigned seed = (unsigned)time(NULL) ^ seed_extra; - srand(seed); + unsigned rng = (unsigned)time(NULL) ^ rng_entropy; + srand(rng); for (size_t i = 0; i < 32; i++) { - kp.secret_key[i] = (uint8_t)(rand() % 256); + kp.seed[i] = (uint8_t)(rand() % 256); } // Assign methods @@ -117,6 +123,10 @@ MicroSuiEd25519 SuiKeypair_generate(uint8_t seed_extra) { * @param[in] sk Bech32-encoded secret key string. * * @return Initialized MicroSuiEd25519 struct, or empty if decoding fails. + * + * @note Mysten Labs' TypeScript SDK uses the term "Secret Key" for the Sui Bech32 + * encoded private key string. To maintain consistency with the TypeScript SDK, + * the naming convention `fromSecretKey` is used here. */ MicroSuiEd25519 SuiKeypair_fromSecretKey(const char *sk) { MicroSuiEd25519 kp; @@ -125,7 +135,7 @@ MicroSuiEd25519 SuiKeypair_fromSecretKey(const char *sk) { if (sk == NULL || strlen(sk) == 0 || strlen(sk) != PK_BECH32_LEN) return kp; // Error: Invalid secret key: return empty struct // Decode the secret key from Bech32 - if (microsui_decode_sui_privkey(sk, kp.secret_key) != 0) return kp; // Error: Decoding failed: return empty struct + if (microsui_decode_bech32_private_key(kp.seed, sk) != 0) return kp; // Error: Decoding failed: return empty struct // Assign methods kp.signTransaction = ms_signTransaction_impl; @@ -159,7 +169,7 @@ static SuiSignature ms_signTransaction_impl(MicroSuiEd25519 *self, const char *m hex_to_bytes(msg, message, message_len); // sign - microsui_sign_ed25519(sig.bytes, message, message_len, self->secret_key); + microsui_sign_ed25519(sig.bytes, message, message_len, self->seed); // encode to base64 bytes_to_base64(sig.bytes, 97, sig.signature, sizeof(sig.signature)); @@ -177,10 +187,14 @@ static SuiSignature ms_signTransaction_impl(MicroSuiEd25519 *self, const char *m * @param[in] self Pointer to MicroSuiEd25519 instance. * * @return Pointer to a static null-terminated string containing the secret key. + * + * @note Mysten Labs' TypeScript SDK returns the private key as a Sui Bech32 string + * with the name `Secret Key`. To maintain consistency with the TypeScript SDK, + * the naming convention `getSecretKey` is used here. */ static const char* ms_getSecretKey_impl(MicroSuiEd25519 *self) { static char secret_key[PK_BECH32_LEN + 1]; // Placeholder for secret key - microsui_encode_sui_privkey(self->secret_key, secret_key); + microsui_encode_bech32_private_key(secret_key, self->seed); return secret_key; // placeholder } @@ -197,7 +211,7 @@ static const char* ms_getSecretKey_impl(MicroSuiEd25519 *self) { */ static const uint8_t* ms_getPublicKey_impl(MicroSuiEd25519 *self) { static uint8_t public_key[32]; // Placeholder for Sui address - get_public_key_from_private_key(self->secret_key, public_key); + microsui_derive_public_key_ed25519(public_key, self->seed); return public_key; // placeholder } @@ -219,11 +233,11 @@ static const char* ms_toSuiAddress_impl(MicroSuiEd25519 *self) { // Obtain the public key from the secret key uint8_t public_key[32]; - get_public_key_from_private_key(self->secret_key, public_key); + microsui_derive_public_key_ed25519(public_key, self->seed); // Encode public key to Sui address uint8_t encoded_address[32]; - microsui_pubkey_to_sui_address(public_key, encoded_address); + microsui_derive_sui_address_ed25519(encoded_address, public_key); // Convert the encoded address to a hex string char encoded_address_string[65]; diff --git a/src/Keypair.h b/src/Keypair.h index 8aa8bd1..2867ac2 100644 --- a/src/Keypair.h +++ b/src/Keypair.h @@ -21,7 +21,7 @@ typedef struct { typedef struct MicroSuiEd25519 MicroSuiEd25519; struct MicroSuiEd25519 { - uint8_t secret_key[32]; + uint8_t seed[32]; // OO-style methods SuiSignature (*signTransaction)(MicroSuiEd25519 *self, const char *msg); @@ -33,7 +33,7 @@ struct MicroSuiEd25519 { // ========================== // Constructors // ========================== -MicroSuiEd25519 SuiKeypair_generate(uint8_t seed_extra); +MicroSuiEd25519 SuiKeypair_generate(uint8_t rng_entropy); MicroSuiEd25519 SuiKeypair_fromSecretKey(const char *sk); #endif // MICROSUI_KEYPAIR_H \ No newline at end of file diff --git a/src/microsui_core/cryptography.c b/src/microsui_core/cryptography.c index b5db61b..32306d1 100644 --- a/src/microsui_core/cryptography.c +++ b/src/microsui_core/cryptography.c @@ -3,10 +3,10 @@ #include #include #include +#include "lib/monocypher/monocypher.h" #include "cryptography.h" - static const char ALPHABET[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; static const int8_t ALPHABET_MAP[128] = { @@ -103,14 +103,13 @@ static void bech32_create_checksum(const char *hrp, const uint8_t *data, size_t } /** - * @brief Decode a Sui Bech32 private key string into 32 raw bytes. + * @brief Decode a Sui Bech32 private key string into 32 raw seed bytes. * * Validates the Bech32-encoded private key (HRP = "suiprivkey", no mixed case), - * converts the 5-bit words back to 8-bit bytes, and extracts the 32-byte secret - * (sk) after the 1-byte scheme flag. + * converts the 5-bit words back to 8-bit bytes, and extracts the 32-byte seed after the 1-byte scheme flag. * - * @param[in] privkey_bech Null-terminated Bech32 string ("suiprivkey1..."). - * @param[out] privkey_bytes_output Output buffer for the 32-byte secret key. + * @param[out] seed_out Output buffer for the 32-byte seed private key. + * @param[in] private_key_bech Null-terminated Bech32 private key string ("suiprivkey1..."). * * @return 0 on success; -1 on invalid length/format, mixed case, bad alphabet, * conversion failure, or unexpected payload size. @@ -118,13 +117,13 @@ static void bech32_create_checksum(const char *hrp, const uint8_t *data, size_t * @note Expects total string length == PK_BECH32_LEN. Mixed case is rejected. * @note The returned key is the 32-byte seed; callers must handle it securely. */ -int microsui_decode_sui_privkey(const char *privkey_bech, uint8_t privkey_bytes_output[32]) { - size_t len = strlen(privkey_bech); +int microsui_decode_bech32_private_key(uint8_t seed_out[32], const char *private_key_bech) { + size_t len = strlen(private_key_bech); if (len != PK_BECH32_LEN) return -1; bool hasLower = false, hasUpper = false; for (size_t i = 0; i < len; i++) { - char c = privkey_bech[i]; + char c = private_key_bech[i]; if (c >= 'a' && c <= 'z') hasLower = true; if (c >= 'A' && c <= 'Z') hasUpper = true; } @@ -132,7 +131,7 @@ int microsui_decode_sui_privkey(const char *privkey_bech, uint8_t privkey_bytes_ char str[PK_BECH32_LEN + 1]; for (size_t i = 0; i < len; i++) { - str[i] = TOLOWER(privkey_bech[i]); + str[i] = TOLOWER(private_key_bech[i]); } str[len] = '\0'; @@ -169,34 +168,42 @@ int microsui_decode_sui_privkey(const char *privkey_bech, uint8_t privkey_bytes_ if (!convert_bits(ext_secret, &ext_len, words, words_len, 5, 8, false)) return -1; if (ext_len != 33) return -1; - memcpy(privkey_bytes_output, ext_secret + 1, 32); + memcpy(seed_out, ext_secret + 1, 32); + + // Clear sensitive data from memory + crypto_wipe(ext_secret, sizeof ext_secret); + crypto_wipe(hrp_expanded, sizeof hrp_expanded); + crypto_wipe(words, sizeof words); + crypto_wipe(data5, sizeof data5); + crypto_wipe(str, sizeof str); + return 0; } /** - * @brief Encode a 32-byte Sui private key into a Bech32 string. + * @brief Encode a 32-byte seed into a Sui Bech32 private key string. * - * Builds the Bech32 payload as: [1-byte scheme flag (0x00) | 32-byte secret], + * Builds the Bech32 payload as: [1-byte scheme flag (0x00) | 32-byte seed], * converts to 5-bit words, appends checksum, and writes the Bech32 string with * HRP = "suiprivkey". * - * @param[in] privkey_bytes Pointer to the 32-byte secret key. - * @param[out] privkey_bech_output Output buffer for the null-terminated Bech32 string. - * Must have capacity >= PK_BECH32_LEN + 1. + * @param[out] private_key_bech_out Output buffer for the null-terminated Bech32 string. + * @param[in] seed_bytes Pointer to the 32-byte seed. + * Must have capacity >= PK_BECH32_LEN + 1. * * @return 0 on success; -1 on conversion failure or insufficient output capacity. * * @note The output uses lowercase Bech32 alphabet and includes the null terminator. * @note Callers are responsible for providing a sufficiently large output buffer. */ -int microsui_encode_sui_privkey(const uint8_t *privkey_bytes, char *privkey_bech_output) { +int microsui_encode_bech32_private_key(char *private_key_bech_out, const uint8_t *seed) { const char *hrp = "suiprivkey"; const uint8_t scheme_flag = 0x00; const size_t output_len = PK_BECH32_LEN + 1; uint8_t data[33]; data[0] = scheme_flag; - memcpy(data + 1, privkey_bytes, 32); + memcpy(data + 1, seed, 32); size_t data5_len = 0; uint8_t data5[(33 * 8 + 4) / 5 + 1]; @@ -213,18 +220,24 @@ int microsui_encode_sui_privkey(const uint8_t *privkey_bytes, char *privkey_bech } for (size_t i = 0; i < hrp_len; i++) { - privkey_bech_output[i] = hrp[i]; + private_key_bech_out[i] = hrp[i]; } - privkey_bech_output[hrp_len] = '1'; + private_key_bech_out[hrp_len] = '1'; size_t idx = hrp_len + 1; for (size_t i = 0; i < data5_len; i++) { - privkey_bech_output[idx++] = ALPHABET[data5[i]]; + private_key_bech_out[idx++] = ALPHABET[data5[i]]; } for (int i = 0; i < 6; i++) { - privkey_bech_output[idx++] = ALPHABET[checksum[i]]; + private_key_bech_out[idx++] = ALPHABET[checksum[i]]; } - privkey_bech_output[idx] = '\0'; // null-terminator + private_key_bech_out[idx] = '\0'; // null-terminator + + // Clear sensitive data from memory + crypto_wipe(checksum, sizeof checksum); + crypto_wipe(data5, sizeof data5); + crypto_wipe(data, sizeof data); + return 0; } \ No newline at end of file diff --git a/src/microsui_core/cryptography.h b/src/microsui_core/cryptography.h index d29f2f9..0ca55e5 100644 --- a/src/microsui_core/cryptography.h +++ b/src/microsui_core/cryptography.h @@ -6,8 +6,8 @@ #define PK_BECH32_LEN 70 // Length of Sui private key in Bech32 format -int microsui_decode_sui_privkey(const char *privkey_bech, uint8_t privkey_bytes_output[32]); +int microsui_decode_bech32_private_key(uint8_t seed_out[32], const char *private_key_bech); -int microsui_encode_sui_privkey(const uint8_t *privkey_bytes, char *privkey_bech_output); +int microsui_encode_bech32_private_key(char *private_key_bech_out, const uint8_t *seed); #endif \ No newline at end of file diff --git a/src/microsui_core/key_management.c b/src/microsui_core/key_management.c index d191fc3..836497b 100644 --- a/src/microsui_core/key_management.c +++ b/src/microsui_core/key_management.c @@ -13,20 +13,20 @@ * then computes the BLAKE2b-256 hash of the 33-byte input. * The resulting 32-byte digest is the canonical Sui address. * - * @param[in] pubkey 32-byte Ed25519 public key. - * @param[out] sui_address_out Output buffer for the 32-byte Sui address. + * @param[out] sui_address_out Output buffer for the 32-byte Sui address. + * @param[in] public_key 32-byte Ed25519 public key. * * @return 0 on success; -1 if input pointers are NULL. * * @note This implementation follows the Sui address derivation convention: - * sui_address = blake2b_256([scheme_flag | pubkey]). + * sui_address = blake2b_256([scheme_flag | public_key]). */ -int microsui_pubkey_to_sui_address(const uint8_t pubkey[32], uint8_t sui_address_out[32]) { - if (!pubkey || !sui_address_out) return -1; +int microsui_derive_sui_address_ed25519(uint8_t sui_address_out[32], const uint8_t public_key[32]) { + if (!public_key || !sui_address_out) return -1; uint8_t input[33]; input[0] = 0x00; // flag de esquema: Ed25519 - memcpy(input + 1, pubkey, 32); + memcpy(input + 1, public_key, 32); // Monocypher: hash_size = 32, msg = input (33 bytes) crypto_blake2b(sui_address_out, 32, input, 33); @@ -35,29 +35,33 @@ int microsui_pubkey_to_sui_address(const uint8_t pubkey[32], uint8_t sui_address } /** - * @brief Derive a 32-byte Ed25519 public key from a 32-byte private key seed. + * @brief Derive a 32-byte Ed25519 public key from a 32-byte seed. * * Generates the full 64-byte Ed25519 secret key internally, then extracts * the corresponding public key. * - * @param[in] private_key 32-byte Ed25519 private key seed. - * @param[out] public_key Output buffer for the 32-byte public key. + * @param[out] public_key_out Output buffer for the 32-byte public key. + * @param[in] seed 32-byte Ed25519 seed. * * @return 0 on success; -1 if input pointers are NULL. * - * @note The private key is copied to a local buffer before use, to avoid - * modifying the caller’s memory. + * @note The seed is copied to a local buffer before use, + * as the underlying library may modify it during key generation. */ -int get_public_key_from_private_key(const uint8_t private_key[32], uint8_t public_key[32]) { - if (private_key == NULL || public_key == NULL) return -1; +int microsui_derive_public_key_ed25519(uint8_t public_key_out[32], const uint8_t seed[32]) { + if (seed == NULL || public_key_out == NULL) return -1; - // Copy private key to a local variable - uint8_t private_key_cp[32]; - memcpy(private_key_cp, private_key, 32); + // Copy secret key to a local variable + uint8_t seed_cp[32]; + memcpy(seed_cp, seed, 32); - // Generate public key from private key using Ed25519 - uint8_t secret_key[64]; - crypto_ed25519_key_pair(secret_key, public_key, private_key_cp); + // Generate public key from secret key using Ed25519 + uint8_t _[64]; // Placeholder for the secret key (not used here) + crypto_ed25519_key_pair(_, public_key_out, seed_cp); + + // Clear sensitive data from memory + crypto_wipe(seed_cp, sizeof seed_cp); + crypto_wipe(_, sizeof _); return 0; } \ No newline at end of file diff --git a/src/microsui_core/key_management.h b/src/microsui_core/key_management.h index 54d62e8..67146f0 100644 --- a/src/microsui_core/key_management.h +++ b/src/microsui_core/key_management.h @@ -4,8 +4,8 @@ #include #include -int microsui_pubkey_to_sui_address(const uint8_t pubkey[32], uint8_t sui_address_out[32]); +int microsui_derive_sui_address_ed25519(uint8_t sui_address_out[32], const uint8_t pubkey[32]); -int get_public_key_from_private_key(const uint8_t private_key[32], uint8_t public_key[32]); +int microsui_derive_public_key_ed25519(uint8_t public_key_out[32], const uint8_t seed[32]); #endif \ No newline at end of file diff --git a/src/microsui_core/lib/compact25519/c25519/README.md b/src/microsui_core/lib/compact25519/c25519/README.md deleted file mode 100644 index e7587ed..0000000 --- a/src/microsui_core/lib/compact25519/c25519/README.md +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains [Daniel Beer's (Public Domain) c25519 implementation](https://www.dlbeer.co.nz/oss/c25519.html), -with some minor adjustments to add define guards. - -Version: 2017-10-05 \ No newline at end of file diff --git a/src/microsui_core/lib/compact25519/c25519/c25519.c b/src/microsui_core/lib/compact25519/c25519/c25519.c deleted file mode 100644 index 223ecf2..0000000 --- a/src/microsui_core/lib/compact25519/c25519/c25519.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Curve25519 (Montgomery form) - * Daniel Beer , 18 Apr 2014 - * - * This file is in the public domain. - */ - -#include "c25519.h" - -#ifndef COMPACT_DISABLE_X25519 -const uint8_t c25519_base_x[F25519_SIZE] = {9}; - -/* Double an X-coordinate */ -static void xc_double(uint8_t *x3, uint8_t *z3, - const uint8_t *x1, const uint8_t *z1) -{ - /* Explicit formulas database: dbl-1987-m - * - * source 1987 Montgomery "Speeding the Pollard and elliptic - * curve methods of factorization", page 261, fourth display - * compute X3 = (X1^2-Z1^2)^2 - * compute Z3 = 4 X1 Z1 (X1^2 + a X1 Z1 + Z1^2) - */ - uint8_t x1sq[F25519_SIZE]; - uint8_t z1sq[F25519_SIZE]; - uint8_t x1z1[F25519_SIZE]; - uint8_t a[F25519_SIZE]; - - f25519_mul__distinct(x1sq, x1, x1); - f25519_mul__distinct(z1sq, z1, z1); - f25519_mul__distinct(x1z1, x1, z1); - - f25519_sub(a, x1sq, z1sq); - f25519_mul__distinct(x3, a, a); - - f25519_mul_c(a, x1z1, 486662); - f25519_add(a, x1sq, a); - f25519_add(a, z1sq, a); - f25519_mul__distinct(x1sq, x1z1, a); - f25519_mul_c(z3, x1sq, 4); -} - -/* Differential addition */ -static void xc_diffadd(uint8_t *x5, uint8_t *z5, - const uint8_t *x1, const uint8_t *z1, - const uint8_t *x2, const uint8_t *z2, - const uint8_t *x3, const uint8_t *z3) -{ - /* Explicit formulas database: dbl-1987-m3 - * - * source 1987 Montgomery "Speeding the Pollard and elliptic curve - * methods of factorization", page 261, fifth display, plus - * common-subexpression elimination - * compute A = X2+Z2 - * compute B = X2-Z2 - * compute C = X3+Z3 - * compute D = X3-Z3 - * compute DA = D A - * compute CB = C B - * compute X5 = Z1(DA+CB)^2 - * compute Z5 = X1(DA-CB)^2 - */ - uint8_t da[F25519_SIZE]; - uint8_t cb[F25519_SIZE]; - uint8_t a[F25519_SIZE]; - uint8_t b[F25519_SIZE]; - - f25519_add(a, x2, z2); - f25519_sub(b, x3, z3); /* D */ - f25519_mul__distinct(da, a, b); - - f25519_sub(b, x2, z2); - f25519_add(a, x3, z3); /* C */ - f25519_mul__distinct(cb, a, b); - - f25519_add(a, da, cb); - f25519_mul__distinct(b, a, a); - f25519_mul__distinct(x5, z1, b); - - f25519_sub(a, da, cb); - f25519_mul__distinct(b, a, a); - f25519_mul__distinct(z5, x1, b); -} - -void c25519_smult(uint8_t *result, const uint8_t *q, const uint8_t *e) -{ - /* Current point: P_m */ - uint8_t xm[F25519_SIZE]; - uint8_t zm[F25519_SIZE] = {1}; - - /* Predecessor: P_(m-1) */ - uint8_t xm1[F25519_SIZE] = {1}; - uint8_t zm1[F25519_SIZE] = {0}; - - int i; - - /* Note: bit 254 is assumed to be 1 */ - f25519_copy(xm, q); - - for (i = 253; i >= 0; i--) { - const int bit = (e[i >> 3] >> (i & 7)) & 1; - uint8_t xms[F25519_SIZE]; - uint8_t zms[F25519_SIZE]; - - /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */ - xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1); - xc_double(xm, zm, xm, zm); - - /* Compute P_(2m+1) */ - xc_diffadd(xms, zms, xm1, zm1, xm, zm, q, f25519_one); - - /* Select: - * bit = 1 --> (P_(2m+1), P_(2m)) - * bit = 0 --> (P_(2m), P_(2m-1)) - */ - f25519_select(xm1, xm1, xm, bit); - f25519_select(zm1, zm1, zm, bit); - f25519_select(xm, xm, xms, bit); - f25519_select(zm, zm, zms, bit); - } - - /* Freeze out of projective coordinates */ - f25519_inv__distinct(zm1, zm); - f25519_mul__distinct(result, zm1, xm); - f25519_normalize(result); -} -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/c25519.h b/src/microsui_core/lib/compact25519/c25519/c25519.h deleted file mode 100644 index eeac849..0000000 --- a/src/microsui_core/lib/compact25519/c25519/c25519.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Curve25519 (Montgomery form) - * Daniel Beer , 18 Apr 2014 - * - * This file is in the public domain. - */ - -#ifndef C25519_H_ -#define C25519_H_ - -#ifndef COMPACT_DISABLE_X25519 -#include -#include "f25519.h" - -/* Curve25519 has the equation over F(p = 2^255-19): - * - * y^2 = x^3 + 486662x^2 + x - * - * 486662 = 4A+2, where A = 121665. This is a Montgomery curve. - * - * For more information, see: - * - * Bernstein, D.J. (2006) "Curve25519: New Diffie-Hellman speed - * records". Document ID: 4230efdfa673480fc079449d90f322c0. - */ - -/* This is the site of a Curve25519 exponent (private key) */ -#define C25519_EXPONENT_SIZE 32 - -/* Having generated 32 random bytes, you should call this function to - * finalize the generated key. - */ -static inline void c25519_prepare(uint8_t *key) -{ - key[0] &= 0xf8; - key[31] &= 0x7f; - key[31] |= 0x40; -} - -/* X-coordinate of the base point */ -extern const uint8_t c25519_base_x[F25519_SIZE]; - -/* X-coordinate scalar multiply: given the X-coordinate of q, return the - * X-coordinate of e*q. - * - * result and q are field elements. e is an exponent. - */ -void c25519_smult(uint8_t *result, const uint8_t *q, const uint8_t *e); -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/ed25519.c b/src/microsui_core/lib/compact25519/c25519/ed25519.c deleted file mode 100644 index fb8cfa2..0000000 --- a/src/microsui_core/lib/compact25519/c25519/ed25519.c +++ /dev/null @@ -1,323 +0,0 @@ -/* Edwards curve operations - * Daniel Beer , 9 Jan 2014 - * - * This file is in the public domain. - */ - -#include "ed25519.h" - -#ifndef COMPACT_DISABLE_ED25519 - -/* Base point is (numbers wrapped): - * - * x = 151122213495354007725011514095885315114 - * 54012693041857206046113283949847762202 - * y = 463168356949264781694283940034751631413 - * 07993866256225615783033603165251855960 - * - * y is derived by transforming the original Montgomery base (u=9). x - * is the corresponding positive coordinate for the new curve equation. - * t is x*y. - */ -const struct ed25519_pt ed25519_base = { - .x = { - 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, - 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, - 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, - 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 - }, - .y = { - 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 - }, - .t = { - 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, - 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, - 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, - 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67 - }, - .z = {1, 0} -}; - -const struct ed25519_pt ed25519_neutral = { - .x = {0}, - .y = {1, 0}, - .t = {0}, - .z = {1, 0} -}; - -/* Conversion to and from projective coordinates */ -void ed25519_project(struct ed25519_pt *p, - const uint8_t *x, const uint8_t *y) -{ - f25519_copy(p->x, x); - f25519_copy(p->y, y); - f25519_load(p->z, 1); - f25519_mul__distinct(p->t, x, y); -} - -void ed25519_unproject(uint8_t *x, uint8_t *y, - const struct ed25519_pt *p) -{ - uint8_t z1[F25519_SIZE]; - - f25519_inv__distinct(z1, p->z); - f25519_mul__distinct(x, p->x, z1); - f25519_mul__distinct(y, p->y, z1); - - f25519_normalize(x); - f25519_normalize(y); -} - -/* Compress/uncompress points. We compress points by storing the x - * coordinate and the parity of the y coordinate. - * - * Rearranging the curve equation, we obtain explicit formulae for the - * coordinates: - * - * x = sqrt((y^2-1) / (1+dy^2)) - * y = sqrt((x^2+1) / (1-dx^2)) - * - * Where d = (-121665/121666), or: - * - * d = 370957059346694393431380835087545651895 - * 42113879843219016388785533085940283555 - */ - -static const uint8_t ed25519_d[F25519_SIZE] = { - 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, - 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, - 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, - 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 -}; - -void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y) -{ - uint8_t tmp[F25519_SIZE]; - uint8_t parity; - - f25519_copy(tmp, x); - f25519_normalize(tmp); - parity = (tmp[0] & 1) << 7; - - f25519_copy(c, y); - f25519_normalize(c); - c[31] |= parity; -} - -uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *comp) -{ - const int parity = comp[31] >> 7; - uint8_t a[F25519_SIZE]; - uint8_t b[F25519_SIZE]; - uint8_t c[F25519_SIZE]; - - /* Unpack y */ - f25519_copy(y, comp); - y[31] &= 127; - - /* Compute c = y^2 */ - f25519_mul__distinct(c, y, y); - - /* Compute b = (1+dy^2)^-1 */ - f25519_mul__distinct(b, c, ed25519_d); - f25519_add(a, b, f25519_one); - f25519_inv__distinct(b, a); - - /* Compute a = y^2-1 */ - f25519_sub(a, c, f25519_one); - - /* Compute c = a*b = (y^2-1)/(1-dy^2) */ - f25519_mul__distinct(c, a, b); - - /* Compute a, b = +/-sqrt(c), if c is square */ - f25519_sqrt(a, c); - f25519_neg(b, a); - - /* Select one of them, based on the compressed parity bit */ - f25519_select(x, a, b, (a[0] ^ parity) & 1); - - /* Verify that x^2 = c */ - f25519_mul__distinct(a, x, x); - f25519_normalize(a); - f25519_normalize(c); - - return f25519_eq(a, c); -} - -/* k = 2d */ -static const uint8_t ed25519_k[F25519_SIZE] = { - 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb, - 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00, - 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19, - 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24 -}; - -void ed25519_add(struct ed25519_pt *r, - const struct ed25519_pt *p1, const struct ed25519_pt *p2) -{ - /* Explicit formulas database: add-2008-hwcd-3 - * - * source 2008 Hisil--Wong--Carter--Dawson, - * http://eprint.iacr.org/2008/522, Section 3.1 - * appliesto extended-1 - * parameter k - * assume k = 2 d - * compute A = (Y1-X1)(Y2-X2) - * compute B = (Y1+X1)(Y2+X2) - * compute C = T1 k T2 - * compute D = Z1 2 Z2 - * compute E = B - A - * compute F = D - C - * compute G = D + C - * compute H = B + A - * compute X3 = E F - * compute Y3 = G H - * compute T3 = E H - * compute Z3 = F G - */ - uint8_t a[F25519_SIZE]; - uint8_t b[F25519_SIZE]; - uint8_t c[F25519_SIZE]; - uint8_t d[F25519_SIZE]; - uint8_t e[F25519_SIZE]; - uint8_t f[F25519_SIZE]; - uint8_t g[F25519_SIZE]; - uint8_t h[F25519_SIZE]; - - /* A = (Y1-X1)(Y2-X2) */ - f25519_sub(c, p1->y, p1->x); - f25519_sub(d, p2->y, p2->x); - f25519_mul__distinct(a, c, d); - - /* B = (Y1+X1)(Y2+X2) */ - f25519_add(c, p1->y, p1->x); - f25519_add(d, p2->y, p2->x); - f25519_mul__distinct(b, c, d); - - /* C = T1 k T2 */ - f25519_mul__distinct(d, p1->t, p2->t); - f25519_mul__distinct(c, d, ed25519_k); - - /* D = Z1 2 Z2 */ - f25519_mul__distinct(d, p1->z, p2->z); - f25519_add(d, d, d); - - /* E = B - A */ - f25519_sub(e, b, a); - - /* F = D - C */ - f25519_sub(f, d, c); - - /* G = D + C */ - f25519_add(g, d, c); - - /* H = B + A */ - f25519_add(h, b, a); - - /* X3 = E F */ - f25519_mul__distinct(r->x, e, f); - - /* Y3 = G H */ - f25519_mul__distinct(r->y, g, h); - - /* T3 = E H */ - f25519_mul__distinct(r->t, e, h); - - /* Z3 = F G */ - f25519_mul__distinct(r->z, f, g); -} - -void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *p) -{ - /* Explicit formulas database: dbl-2008-hwcd - * - * source 2008 Hisil--Wong--Carter--Dawson, - * http://eprint.iacr.org/2008/522, Section 3.3 - * compute A = X1^2 - * compute B = Y1^2 - * compute C = 2 Z1^2 - * compute D = a A - * compute E = (X1+Y1)^2-A-B - * compute G = D + B - * compute F = G - C - * compute H = D - B - * compute X3 = E F - * compute Y3 = G H - * compute T3 = E H - * compute Z3 = F G - */ - uint8_t a[F25519_SIZE]; - uint8_t b[F25519_SIZE]; - uint8_t c[F25519_SIZE]; - uint8_t e[F25519_SIZE]; - uint8_t f[F25519_SIZE]; - uint8_t g[F25519_SIZE]; - uint8_t h[F25519_SIZE]; - - /* A = X1^2 */ - f25519_mul__distinct(a, p->x, p->x); - - /* B = Y1^2 */ - f25519_mul__distinct(b, p->y, p->y); - - /* C = 2 Z1^2 */ - f25519_mul__distinct(c, p->z, p->z); - f25519_add(c, c, c); - - /* D = a A (alter sign) */ - /* E = (X1+Y1)^2-A-B */ - f25519_add(f, p->x, p->y); - f25519_mul__distinct(e, f, f); - f25519_sub(e, e, a); - f25519_sub(e, e, b); - - /* G = D + B */ - f25519_sub(g, b, a); - - /* F = G - C */ - f25519_sub(f, g, c); - - /* H = D - B */ - f25519_neg(h, b); - f25519_sub(h, h, a); - - /* X3 = E F */ - f25519_mul__distinct(r->x, e, f); - - /* Y3 = G H */ - f25519_mul__distinct(r->y, g, h); - - /* T3 = E H */ - f25519_mul__distinct(r->t, e, h); - - /* Z3 = F G */ - f25519_mul__distinct(r->z, f, g); -} - -void ed25519_smult(struct ed25519_pt *r_out, const struct ed25519_pt *p, - const uint8_t *e) -{ - struct ed25519_pt r; - int i; - - ed25519_copy(&r, &ed25519_neutral); - - for (i = 255; i >= 0; i--) { - const uint8_t bit = (e[i >> 3] >> (i & 7)) & 1; - struct ed25519_pt s; - - ed25519_double(&r, &r); - ed25519_add(&s, &r, p); - - f25519_select(r.x, r.x, s.x, bit); - f25519_select(r.y, r.y, s.y, bit); - f25519_select(r.z, r.z, s.z, bit); - f25519_select(r.t, r.t, s.t, bit); - } - - ed25519_copy(r_out, &r); -} -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/ed25519.h b/src/microsui_core/lib/compact25519/c25519/ed25519.h deleted file mode 100644 index 0e63467..0000000 --- a/src/microsui_core/lib/compact25519/c25519/ed25519.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Edwards curve operations - * Daniel Beer , 9 Jan 2014 - * - * This file is in the public domain. - */ - -#ifndef ED25519_H_ -#define ED25519_H_ - -#ifndef COMPACT_DISABLE_ED25519 -#include "f25519.h" - -/* This is not the Ed25519 signature system. Rather, we're implementing - * basic operations on the twisted Edwards curve over (Z mod 2^255-19): - * - * -x^2 + y^2 = 1 - (121665/121666)x^2y^2 - * - * With the positive-x base point y = 4/5. - * - * These functions will not leak secret data through timing. - * - * For more information, see: - * - * Bernstein, D.J. & Lange, T. (2007) "Faster addition and doubling on - * elliptic curves". Document ID: 95616567a6ba20f575c5f25e7cebaf83. - * - * Hisil, H. & Wong, K K. & Carter, G. & Dawson, E. (2008) "Twisted - * Edwards curves revisited". Advances in Cryptology, ASIACRYPT 2008, - * Vol. 5350, pp. 326-343. - */ - -/* Projective coordinates */ -struct ed25519_pt { - uint8_t x[F25519_SIZE]; - uint8_t y[F25519_SIZE]; - uint8_t t[F25519_SIZE]; - uint8_t z[F25519_SIZE]; -}; - -extern const struct ed25519_pt ed25519_base; -extern const struct ed25519_pt ed25519_neutral; - -/* Convert between projective and affine coordinates (x/y in F25519) */ -void ed25519_project(struct ed25519_pt *p, - const uint8_t *x, const uint8_t *y); - -void ed25519_unproject(uint8_t *x, uint8_t *y, - const struct ed25519_pt *p); - -/* Compress/uncompress points. try_unpack() will check that the - * compressed point is on the curve, returning 1 if the unpacked point - * is valid, and 0 otherwise. - */ -#define ED25519_PACK_SIZE F25519_SIZE - -void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y); -uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *c); - -/* Add, double and scalar multiply */ -#define ED25519_EXPONENT_SIZE 32 - -/* Prepare an exponent by clamping appropriate bits */ -static inline void ed25519_prepare(uint8_t *e) -{ - e[0] &= 0xf8; - e[31] &= 0x7f; - e[31] |= 0x40; -} - -/* Order of the group generated by the base point */ -static inline void ed25519_copy(struct ed25519_pt *dst, - const struct ed25519_pt *src) -{ - memcpy(dst, src, sizeof(*dst)); -} - -void ed25519_add(struct ed25519_pt *r, - const struct ed25519_pt *a, const struct ed25519_pt *b); -void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *a); -void ed25519_smult(struct ed25519_pt *r, const struct ed25519_pt *a, - const uint8_t *e); - -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/edsign.c b/src/microsui_core/lib/compact25519/c25519/edsign.c deleted file mode 100644 index cee3538..0000000 --- a/src/microsui_core/lib/compact25519/c25519/edsign.c +++ /dev/null @@ -1,171 +0,0 @@ -/* Edwards curve signature system - * Daniel Beer , 22 Apr 2014 - * - * This file is in the public domain. - */ - -#include "ed25519.h" - -#ifndef COMPACT_DISABLE_ED25519 -#include "sha512.h" -#include "fprime.h" -#include "edsign.h" - -#define EXPANDED_SIZE 64 - -static const uint8_t ed25519_order[FPRIME_SIZE] = { - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, - 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 -}; - -static void expand_key(uint8_t *expanded, const uint8_t *secret) -{ - struct sha512_state s; - - sha512_init(&s); - sha512_final(&s, secret, EDSIGN_SECRET_KEY_SIZE); - sha512_get(&s, expanded, 0, EXPANDED_SIZE); - ed25519_prepare(expanded); -} - -static uint8_t upp(struct ed25519_pt *p, const uint8_t *packed) -{ - uint8_t x[F25519_SIZE]; - uint8_t y[F25519_SIZE]; - uint8_t ok = ed25519_try_unpack(x, y, packed); - - ed25519_project(p, x, y); - return ok; -} - -static void pp(uint8_t *packed, const struct ed25519_pt *p) -{ - uint8_t x[F25519_SIZE]; - uint8_t y[F25519_SIZE]; - - ed25519_unproject(x, y, p); - ed25519_pack(packed, x, y); -} - -static void sm_pack(uint8_t *r, const uint8_t *k) -{ - struct ed25519_pt p; - - ed25519_smult(&p, &ed25519_base, k); - pp(r, &p); -} - -void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret) -{ - uint8_t expanded[EXPANDED_SIZE]; - - expand_key(expanded, secret); - sm_pack(pub, expanded); -} - -static void hash_with_prefix(uint8_t *out_fp, - uint8_t *init_block, unsigned int prefix_size, - const uint8_t *message, size_t len) -{ - struct sha512_state s; - - sha512_init(&s); - - if (len < SHA512_BLOCK_SIZE && len + prefix_size < SHA512_BLOCK_SIZE) { - memcpy(init_block + prefix_size, message, len); - sha512_final(&s, init_block, len + prefix_size); - } else { - size_t i; - - memcpy(init_block + prefix_size, message, - SHA512_BLOCK_SIZE - prefix_size); - sha512_block(&s, init_block); - - for (i = SHA512_BLOCK_SIZE - prefix_size; - i + SHA512_BLOCK_SIZE <= len; - i += SHA512_BLOCK_SIZE) - sha512_block(&s, message + i); - - sha512_final(&s, message + i, len + prefix_size); - } - - sha512_get(&s, init_block, 0, SHA512_HASH_SIZE); - fprime_from_bytes(out_fp, init_block, SHA512_HASH_SIZE, ed25519_order); -} - -static void generate_k(uint8_t *k, const uint8_t *kgen_key, - const uint8_t *message, size_t len) -{ - uint8_t block[SHA512_BLOCK_SIZE]; - - memcpy(block, kgen_key, 32); - hash_with_prefix(k, block, 32, message, len); -} - -static void hash_message(uint8_t *z, const uint8_t *r, const uint8_t *a, - const uint8_t *m, size_t len) -{ - uint8_t block[SHA512_BLOCK_SIZE]; - - memcpy(block, r, 32); - memcpy(block + 32, a, 32); - hash_with_prefix(z, block, 64, m, len); -} - -void edsign_sign(uint8_t *signature, const uint8_t *pub, - const uint8_t *secret, - const uint8_t *message, size_t len) -{ - uint8_t expanded[EXPANDED_SIZE]; - uint8_t e[FPRIME_SIZE]; - uint8_t s[FPRIME_SIZE]; - uint8_t k[FPRIME_SIZE]; - uint8_t z[FPRIME_SIZE]; - - expand_key(expanded, secret); - - /* Generate k and R = kB */ - generate_k(k, expanded + 32, message, len); - sm_pack(signature, k); - - /* Compute z = H(R, A, M) */ - hash_message(z, signature, pub, message, len); - - /* Obtain e */ - fprime_from_bytes(e, expanded, 32, ed25519_order); - - /* Compute s = ze + k */ - fprime_mul(s, z, e, ed25519_order); - fprime_add(s, k, ed25519_order); - memcpy(signature + 32, s, 32); -} - -uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub, - const uint8_t *message, size_t len) -{ - struct ed25519_pt p; - struct ed25519_pt q; - uint8_t lhs[F25519_SIZE]; - uint8_t rhs[F25519_SIZE]; - uint8_t z[FPRIME_SIZE]; - uint8_t ok = 1; - - /* Compute z = H(R, A, M) */ - hash_message(z, signature, pub, message, len); - - /* sB = (ze + k)B = ... */ - sm_pack(lhs, signature + 32); - - /* ... = zA + R */ - ok &= upp(&p, pub); - ed25519_smult(&p, &p, z); - ok &= upp(&q, signature); - ed25519_add(&p, &p, &q); - pp(rhs, &p); - - /* Equal? */ - return ok & f25519_eq(lhs, rhs); -} -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/edsign.h b/src/microsui_core/lib/compact25519/c25519/edsign.h deleted file mode 100644 index cbdf904..0000000 --- a/src/microsui_core/lib/compact25519/c25519/edsign.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Edwards curve signature system - * Daniel Beer , 22 Apr 2014 - * - * This file is in the public domain. - */ - -#ifndef EDSIGN_H_ -#define EDSIGN_H_ - -#ifndef COMPACT_DISABLE_ED25519 -#include -#include - -/* This is the Ed25519 signature system, as described in: - * - * Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin - * Yang. High-speed high-security signatures. Journal of Cryptographic - * Engineering 2 (2012), 77-89. Document ID: - * a1a62a2f76d23f65d622484ddd09caf8. URL: - * http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26. - * - * The format and calculation of signatures is compatible with the - * Ed25519 implementation in SUPERCOP. Note, however, that our secret - * keys are half the size: we don't store a copy of the public key in - * the secret key (we generate it on demand). - */ - -/* Any string of 32 random bytes is a valid secret key. There is no - * clamping of bits, because we don't use the key directly as an - * exponent (the exponent is derived from part of a key expansion). - */ -#define EDSIGN_SECRET_KEY_SIZE 32 - -/* Given a secret key, produce the public key (a packed Edwards-curve - * point). - */ -#define EDSIGN_PUBLIC_KEY_SIZE 32 - -void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret); - -/* Produce a signature for a message. */ -#define EDSIGN_SIGNATURE_SIZE 64 - -void edsign_sign(uint8_t *signature, const uint8_t *pub, - const uint8_t *secret, - const uint8_t *message, size_t len); - -/* Verify a message signature. Returns non-zero if ok. */ -uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub, - const uint8_t *message, size_t len); - -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/f25519.c b/src/microsui_core/lib/compact25519/c25519/f25519.c deleted file mode 100644 index c6e1bff..0000000 --- a/src/microsui_core/lib/compact25519/c25519/f25519.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Arithmetic mod p = 2^255-19 - * Daniel Beer , 5 Jan 2014 - * - * This file is in the public domain. - */ - -#include "f25519.h" - -#ifdef FULL_C25519_CODE -const uint8_t f25519_zero[F25519_SIZE] = {0}; -#endif -const uint8_t f25519_one[F25519_SIZE] = {1}; - -void f25519_load(uint8_t *x, uint32_t c) -{ - unsigned int i; - - for (i = 0; i < sizeof(c); i++) { - x[i] = c; - c >>= 8; - } - - for (; i < F25519_SIZE; i++) - x[i] = 0; -} - -void f25519_normalize(uint8_t *x) -{ - uint8_t minusp[F25519_SIZE]; - uint16_t c; - int i; - - /* Reduce using 2^255 = 19 mod p */ - c = (x[31] >> 7) * 19; - x[31] &= 127; - - for (i = 0; i < F25519_SIZE; i++) { - c += x[i]; - x[i] = c; - c >>= 8; - } - - /* The number is now less than 2^255 + 18, and therefore less than - * 2p. Try subtracting p, and conditionally load the subtracted - * value if underflow did not occur. - */ - c = 19; - - for (i = 0; i + 1 < F25519_SIZE; i++) { - c += x[i]; - minusp[i] = c; - c >>= 8; - } - - c += ((uint16_t)x[i]) - 128; - minusp[31] = c; - - /* Load x-p if no underflow */ - f25519_select(x, minusp, x, (c >> 15) & 1); -} - -uint8_t f25519_eq(const uint8_t *x, const uint8_t *y) -{ - uint8_t sum = 0; - int i; - - for (i = 0; i < F25519_SIZE; i++) - sum |= x[i] ^ y[i]; - - sum |= (sum >> 4); - sum |= (sum >> 2); - sum |= (sum >> 1); - - return (sum ^ 1) & 1; -} - -void f25519_select(uint8_t *dst, - const uint8_t *zero, const uint8_t *one, - uint8_t condition) -{ - const uint8_t mask = -condition; - int i; - - for (i = 0; i < F25519_SIZE; i++) - dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); -} - -void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint16_t c = 0; - int i; - - /* Add */ - for (i = 0; i < F25519_SIZE; i++) { - c >>= 8; - c += ((uint16_t)a[i]) + ((uint16_t)b[i]); - r[i] = c; - } - - /* Reduce with 2^255 = 19 mod p */ - r[31] &= 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } -} - -void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint32_t c = 0; - int i; - - /* Calculate a + 2p - b, to avoid underflow */ - c = 218; - for (i = 0; i + 1 < F25519_SIZE; i++) { - c += 65280 + ((uint32_t)a[i]) - ((uint32_t)b[i]); - r[i] = c; - c >>= 8; - } - - c += ((uint32_t)a[31]) - ((uint32_t)b[31]); - r[31] = c & 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } -} - -void f25519_neg(uint8_t *r, const uint8_t *a) -{ - uint32_t c = 0; - int i; - - /* Calculate 2p - a, to avoid underflow */ - c = 218; - for (i = 0; i + 1 < F25519_SIZE; i++) { - c += 65280 - ((uint32_t)a[i]); - r[i] = c; - c >>= 8; - } - - c -= ((uint32_t)a[31]); - r[31] = c & 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } -} - -void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint32_t c = 0; - int i; - - for (i = 0; i < F25519_SIZE; i++) { - int j; - - c >>= 8; - for (j = 0; j <= i; j++) - c += ((uint32_t)a[j]) * ((uint32_t)b[i - j]); - - for (; j < F25519_SIZE; j++) - c += ((uint32_t)a[j]) * - ((uint32_t)b[i + F25519_SIZE - j]) * 38; - - r[i] = c; - } - - r[31] &= 127; - c = (c >> 7) * 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } -} - -#ifdef FULL_C25519_CODE -void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b) -{ - uint8_t tmp[F25519_SIZE]; - - f25519_mul__distinct(tmp, a, b); - f25519_copy(r, tmp); -} -#endif - -void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b) -{ - uint32_t c = 0; - int i; - - for (i = 0; i < F25519_SIZE; i++) { - c >>= 8; - c += b * ((uint32_t)a[i]); - r[i] = c; - } - - r[31] &= 127; - c >>= 7; - c *= 19; - - for (i = 0; i < F25519_SIZE; i++) { - c += r[i]; - r[i] = c; - c >>= 8; - } -} - -void f25519_inv__distinct(uint8_t *r, const uint8_t *x) -{ - uint8_t s[F25519_SIZE]; - int i; - - /* This is a prime field, so by Fermat's little theorem: - * - * x^(p-1) = 1 mod p - * - * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative - * inverse. - * - * This is a 255-bit binary number with the digits: - * - * 11111111... 01011 - * - * We compute the result by the usual binary chain, but - * alternate between keeping the accumulator in r and s, so as - * to avoid copying temporaries. - */ - - /* 1 1 */ - f25519_mul__distinct(s, x, x); - f25519_mul__distinct(r, s, x); - - /* 1 x 248 */ - for (i = 0; i < 248; i++) { - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); - } - - /* 0 */ - f25519_mul__distinct(s, r, r); - - /* 1 */ - f25519_mul__distinct(r, s, s); - f25519_mul__distinct(s, r, x); - - /* 0 */ - f25519_mul__distinct(r, s, s); - - /* 1 */ - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); - - /* 1 */ - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); -} - -#ifdef FULL_C25519_CODE -void f25519_inv(uint8_t *r, const uint8_t *x) -{ - uint8_t tmp[F25519_SIZE]; - - f25519_inv__distinct(tmp, x); - f25519_copy(r, tmp); -} -#endif - -/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary - * storage. - */ -static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s) -{ - int i; - - /* This number is a 252-bit number with the binary expansion: - * - * 111111... 01 - */ - - /* 1 1 */ - f25519_mul__distinct(r, x, x); - f25519_mul__distinct(s, r, x); - - /* 1 x 248 */ - for (i = 0; i < 248; i++) { - f25519_mul__distinct(r, s, s); - f25519_mul__distinct(s, r, x); - } - - /* 0 */ - f25519_mul__distinct(r, s, s); - - /* 1 */ - f25519_mul__distinct(s, r, r); - f25519_mul__distinct(r, s, x); -} - -void f25519_sqrt(uint8_t *r, const uint8_t *a) -{ - uint8_t v[F25519_SIZE]; - uint8_t i[F25519_SIZE]; - uint8_t x[F25519_SIZE]; - uint8_t y[F25519_SIZE]; - - /* v = (2a)^((p-5)/8) [x = 2a] */ - f25519_mul_c(x, a, 2); - exp2523(v, x, y); - - /* i = 2av^2 - 1 */ - f25519_mul__distinct(y, v, v); - f25519_mul__distinct(i, x, y); - f25519_load(y, 1); - f25519_sub(i, i, y); - - /* r = avi */ - f25519_mul__distinct(x, v, a); - f25519_mul__distinct(r, x, i); -} diff --git a/src/microsui_core/lib/compact25519/c25519/f25519.h b/src/microsui_core/lib/compact25519/c25519/f25519.h deleted file mode 100644 index bb70fdc..0000000 --- a/src/microsui_core/lib/compact25519/c25519/f25519.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Arithmetic mod p = 2^255-19 - * Daniel Beer , 8 Jan 2014 - * - * This file is in the public domain. - */ - -#ifndef F25519_H_ -#define F25519_H_ - -#include -#include - -/* Field elements are represented as little-endian byte strings. All - * operations have timings which are independent of input data, so they - * can be safely used for cryptography. - * - * Computation is performed on un-normalized elements. These are byte - * strings which fall into the range 0 <= x < 2p. Use f25519_normalize() - * to convert to a value 0 <= x < p. - * - * Elements received from the outside may greater even than 2p. - * f25519_normalize() will correctly deal with these numbers too. - */ -#define F25519_SIZE 32 - -/* Identity constants */ -#ifdef FULL_C25519_CODE -extern const uint8_t f25519_zero[F25519_SIZE]; -#endif -extern const uint8_t f25519_one[F25519_SIZE]; - -/* Load a small constant */ -void f25519_load(uint8_t *x, uint32_t c); - -/* Copy two points */ -static inline void f25519_copy(uint8_t *x, const uint8_t *a) -{ - memcpy(x, a, F25519_SIZE); -} - -/* Normalize a field point x < 2*p by subtracting p if necessary */ -void f25519_normalize(uint8_t *x); - -/* Compare two field points in constant time. Return one if equal, zero - * otherwise. This should be performed only on normalized values. - */ -uint8_t f25519_eq(const uint8_t *x, const uint8_t *y); - -/* Conditional copy. If condition == 0, then zero is copied to dst. If - * condition == 1, then one is copied to dst. Any other value results in - * undefined behaviour. - */ -void f25519_select(uint8_t *dst, - const uint8_t *zero, const uint8_t *one, - uint8_t condition); - -/* Add/subtract two field points. The three pointers are not required to - * be distinct. - */ -void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b); -void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b); - -/* Unary negation */ -void f25519_neg(uint8_t *r, const uint8_t *a); - -/* Multiply two field points. The __distinct variant is used when r is - * known to be in a different location to a and b. - */ -#ifdef FULL_C25519_CODE -void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b); -#endif -void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b); - -/* Multiply a point by a small constant. The two pointers are not - * required to be distinct. - * - * The constant must be less than 2^24. - */ -void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b); - -/* Take the reciprocal of a field point. The __distinct variant is used - * when r is known to be in a different location to x. - */ -#ifdef FULL_C25519_CODE -void f25519_inv(uint8_t *r, const uint8_t *x); -#endif -void f25519_inv__distinct(uint8_t *r, const uint8_t *x); - -/* Compute one of the square roots of the field element, if the element - * is square. The other square is -r. - * - * If the input is not square, the returned value is a valid field - * element, but not the correct answer. If you don't already know that - * your element is square, you should square the return value and test. - */ -void f25519_sqrt(uint8_t *r, const uint8_t *x); - -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/fprime.c b/src/microsui_core/lib/compact25519/c25519/fprime.c deleted file mode 100644 index c1ea4b3..0000000 --- a/src/microsui_core/lib/compact25519/c25519/fprime.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Arithmetic in prime fields - * Daniel Beer , 10 Jan 2014 - * - * This file is in the public domain. - */ - -#include "fprime.h" - -#ifndef COMPACT_DISABLE_ED25519 -#ifdef FULL_C25519_CODE -const uint8_t fprime_zero[FPRIME_SIZE] = {0}; -const uint8_t fprime_one[FPRIME_SIZE] = {1}; -#endif - -static void raw_add(uint8_t *x, const uint8_t *p) -{ - uint16_t c = 0; - int i; - - for (i = 0; i < FPRIME_SIZE; i++) { - c += ((uint16_t)x[i]) + ((uint16_t)p[i]); - x[i] = c; - c >>= 8; - } -} - -static void raw_try_sub(uint8_t *x, const uint8_t *p) -{ - uint8_t minusp[FPRIME_SIZE]; - uint16_t c = 0; - int i; - - for (i = 0; i < FPRIME_SIZE; i++) { - c = ((uint16_t)x[i]) - ((uint16_t)p[i]) - c; - minusp[i] = c; - c = (c >> 8) & 1; - } - - fprime_select(x, minusp, x, c); -} - -/* Warning: this function is variable-time */ -static int prime_msb(const uint8_t *p) -{ - int i; - uint8_t x; - - for (i = FPRIME_SIZE - 1; i >= 0; i--) - if (p[i]) - break; - - x = p[i]; - i <<= 3; - - while (x) { - x >>= 1; - i++; - } - - return i - 1; -} - -/* Warning: this function may be variable-time in the argument n */ -static void shift_n_bits(uint8_t *x, int n) -{ - uint16_t c = 0; - int i; - - for (i = 0; i < FPRIME_SIZE; i++) { - c |= ((uint16_t)x[i]) << n; - x[i] = c; - c >>= 8; - } -} - -#ifdef FULL_C25519_CODE -void fprime_load(uint8_t *x, uint32_t c) -{ - unsigned int i; - - for (i = 0; i < sizeof(c); i++) { - x[i] = c; - c >>= 8; - } - - for (; i < FPRIME_SIZE; i++) - x[i] = 0; -} -#endif - -static inline int min_int(int a, int b) -{ - return a < b ? a : b; -} - -void fprime_from_bytes(uint8_t *n, - const uint8_t *x, size_t len, - const uint8_t *modulus) -{ - const int preload_total = min_int(prime_msb(modulus) - 1, len << 3); - const int preload_bytes = preload_total >> 3; - const int preload_bits = preload_total & 7; - const int rbits = (len << 3) - preload_total; - int i; - - memset(n, 0, FPRIME_SIZE); - - for (i = 0; i < preload_bytes; i++) - n[i] = x[len - preload_bytes + i]; - - if (preload_bits) { - shift_n_bits(n, preload_bits); - n[0] |= x[len - preload_bytes - 1] >> (8 - preload_bits); - } - - for (i = rbits - 1; i >= 0; i--) { - const uint8_t bit = (x[i >> 3] >> (i & 7)) & 1; - - shift_n_bits(n, 1); - n[0] |= bit; - raw_try_sub(n, modulus); - } -} - -#ifdef FULL_C25519_CODE -void fprime_normalize(uint8_t *x, const uint8_t *modulus) -{ - uint8_t n[FPRIME_SIZE]; - - fprime_from_bytes(n, x, FPRIME_SIZE, modulus); - fprime_copy(x, n); -} - -uint8_t fprime_eq(const uint8_t *x, const uint8_t *y) -{ - uint8_t sum = 0; - int i; - - for (i = 0; i < FPRIME_SIZE; i++) - sum |= x[i] ^ y[i]; - - sum |= (sum >> 4); - sum |= (sum >> 2); - sum |= (sum >> 1); - - return (sum ^ 1) & 1; -} -#endif -void fprime_select(uint8_t *dst, - const uint8_t *zero, const uint8_t *one, - uint8_t condition) -{ - const uint8_t mask = -condition; - int i; - - for (i = 0; i < FPRIME_SIZE; i++) - dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); -} - -void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus) -{ - raw_add(r, a); - raw_try_sub(r, modulus); -} - -#ifdef FULL_C25519_CODE -void fprime_sub(uint8_t *r, const uint8_t *a, const uint8_t *modulus) -{ - raw_add(r, modulus); - raw_try_sub(r, a); - raw_try_sub(r, modulus); -} -#endif - -void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b, - const uint8_t *modulus) -{ - int i; - - memset(r, 0, FPRIME_SIZE); - - for (i = prime_msb(modulus); i >= 0; i--) { - const uint8_t bit = (b[i >> 3] >> (i & 7)) & 1; - uint8_t plusa[FPRIME_SIZE]; - - shift_n_bits(r, 1); - raw_try_sub(r, modulus); - - fprime_copy(plusa, r); - fprime_add(plusa, a, modulus); - - fprime_select(r, r, plusa, bit); - } -} - -#ifdef FULL_C25519_CODE -void fprime_inv(uint8_t *r, const uint8_t *a, const uint8_t *modulus) -{ - uint8_t pm2[FPRIME_SIZE]; - uint16_t c = 2; - int i; - - /* Compute (p-2) */ - fprime_copy(pm2, modulus); - for (i = 0; i < FPRIME_SIZE; i++) { - c = modulus[i] - c; - pm2[i] = c; - c >>= 8; - } - - /* Binary exponentiation */ - fprime_load(r, 1); - - for (i = prime_msb(modulus); i >= 0; i--) { - uint8_t r2[FPRIME_SIZE]; - - fprime_mul(r2, r, r, modulus); - - if ((pm2[i >> 3] >> (i & 7)) & 1) - fprime_mul(r, r2, a, modulus); - else - fprime_copy(r, r2); - } -} -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/fprime.h b/src/microsui_core/lib/compact25519/c25519/fprime.h deleted file mode 100644 index 50c962d..0000000 --- a/src/microsui_core/lib/compact25519/c25519/fprime.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Arithmetic in prime fields - * Daniel Beer , 10 Jan 2014 - * - * This file is in the public domain. - */ - -#ifndef FPRIME_H_ -#define FPRIME_H_ - -#ifndef COMPACT_DISABLE_ED25519 -#include -#include - -/* Maximum size of a field element (or a prime). Field elements are - * always manipulated and stored in normalized form, with 0 <= x < p. - * You can use normalize() to convert a denormalized bitstring to normal - * form. - * - * Operations are constant with respect to the value of field elements, - * but not with respect to the modulus. - * - * The modulus is a number p, such that 2p-1 fits in FPRIME_SIZE bytes. - */ -#define FPRIME_SIZE 32 - -#ifdef FULL_C25519_CODE -/* Useful constants */ -extern const uint8_t fprime_zero[FPRIME_SIZE]; -extern const uint8_t fprime_one[FPRIME_SIZE]; -#endif - -#ifdef FULL_C25519_CODE -/* Load a small constant */ -void fprime_load(uint8_t *x, uint32_t c); -#endif - -/* Load a large constant */ -void fprime_from_bytes(uint8_t *n, - const uint8_t *x, size_t len, - const uint8_t *modulus); - -/* Copy an element */ -static inline void fprime_copy(uint8_t *x, const uint8_t *a) -{ - memcpy(x, a, FPRIME_SIZE); -} - -#ifdef FULL_C25519_CODE -/* Normalize a field element */ -void fprime_normalize(uint8_t *x, const uint8_t *modulus); - -/* Compare two field points in constant time. Return one if equal, zero - * otherwise. This should be performed only on normalized values. - */ -uint8_t fprime_eq(const uint8_t *x, const uint8_t *y); - -#endif -/* Conditional copy. If condition == 0, then zero is copied to dst. If - * condition == 1, then one is copied to dst. Any other value results in - * undefined behaviour. - */ -void fprime_select(uint8_t *dst, - const uint8_t *zero, const uint8_t *one, - uint8_t condition); - -/* Add one value to another. The two pointers must be distinct. */ -void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus); -#ifdef FULL_C25519_CODE -void fprime_sub(uint8_t *r, const uint8_t *a, const uint8_t *modulus); -#endif - -/* Multiply two values to get a third. r must be distinct from a and b */ -void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b, - const uint8_t *modulus); - -#ifdef FULL_C25519_CODE -/* Compute multiplicative inverse. r must be distinct from a */ -void fprime_inv(uint8_t *r, const uint8_t *a, const uint8_t *modulus); -#endif -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/sha512.c b/src/microsui_core/lib/compact25519/c25519/sha512.c deleted file mode 100644 index 71f9a9d..0000000 --- a/src/microsui_core/lib/compact25519/c25519/sha512.c +++ /dev/null @@ -1,230 +0,0 @@ -/* SHA512 - * Daniel Beer , 22 Apr 2014 - * - * This file is in the public domain. - */ - -#include "sha512.h" - -#if !defined(COMPACT_DISABLE_ED25519) || !defined(COMPACT_DISABLE_X25519_DERIVE) -const struct sha512_state sha512_initial_state = { { - 0x6a09e667f3bcc908LL, 0xbb67ae8584caa73bLL, - 0x3c6ef372fe94f82bLL, 0xa54ff53a5f1d36f1LL, - 0x510e527fade682d1LL, 0x9b05688c2b3e6c1fLL, - 0x1f83d9abfb41bd6bLL, 0x5be0cd19137e2179LL, -} }; - -static const uint64_t round_k[80] = { - 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL, - 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL, - 0x3956c25bf348b538LL, 0x59f111f1b605d019LL, - 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL, - 0xd807aa98a3030242LL, 0x12835b0145706fbeLL, - 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL, - 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL, - 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL, - 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL, - 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL, - 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL, - 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL, - 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL, - 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL, - 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL, - 0x06ca6351e003826fLL, 0x142929670a0e6e70LL, - 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL, - 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL, - 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL, - 0x81c2c92e47edaee6LL, 0x92722c851482353bLL, - 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL, - 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL, - 0xd192e819d6ef5218LL, 0xd69906245565a910LL, - 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL, - 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL, - 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL, - 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL, - 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL, - 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL, - 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL, - 0x90befffa23631e28LL, 0xa4506cebde82bde9LL, - 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL, - 0xca273eceea26619cLL, 0xd186b8c721c0c207LL, - 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL, - 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL, - 0x113f9804bef90daeLL, 0x1b710b35131c471bLL, - 0x28db77f523047d84LL, 0x32caab7b40c72493LL, - 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL, - 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL, - 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL, -}; - -static inline uint64_t load64(const uint8_t *x) -{ - uint64_t r; - - r = *(x++); - r = (r << 8) | *(x++); - r = (r << 8) | *(x++); - r = (r << 8) | *(x++); - r = (r << 8) | *(x++); - r = (r << 8) | *(x++); - r = (r << 8) | *(x++); - r = (r << 8) | *(x++); - - return r; -} - -static inline void store64(uint8_t *x, uint64_t v) -{ - x += 7; - *(x--) = v; - v >>= 8; - *(x--) = v; - v >>= 8; - *(x--) = v; - v >>= 8; - *(x--) = v; - v >>= 8; - *(x--) = v; - v >>= 8; - *(x--) = v; - v >>= 8; - *(x--) = v; - v >>= 8; - *(x--) = v; -} - -static inline uint64_t rot64(uint64_t x, int bits) -{ - return (x >> bits) | (x << (64 - bits)); -} - -void sha512_block(struct sha512_state *s, const uint8_t *blk) -{ - uint64_t w[16]; - uint64_t a, b, c, d, e, f, g, h; - int i; - - for (i = 0; i < 16; i++) { - w[i] = load64(blk); - blk += 8; - } - - /* Load state */ - a = s->h[0]; - b = s->h[1]; - c = s->h[2]; - d = s->h[3]; - e = s->h[4]; - f = s->h[5]; - g = s->h[6]; - h = s->h[7]; - - for (i = 0; i < 80; i++) { - /* Compute value of w[i + 16]. w[wrap(i)] is currently w[i] */ - const uint64_t wi = w[i & 15]; - const uint64_t wi15 = w[(i + 1) & 15]; - const uint64_t wi2 = w[(i + 14) & 15]; - const uint64_t wi7 = w[(i + 9) & 15]; - const uint64_t s0 = - rot64(wi15, 1) ^ rot64(wi15, 8) ^ (wi15 >> 7); - const uint64_t s1 = - rot64(wi2, 19) ^ rot64(wi2, 61) ^ (wi2 >> 6); - - /* Round calculations */ - const uint64_t S0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39); - const uint64_t S1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41); - const uint64_t ch = (e & f) ^ ((~e) & g); - const uint64_t temp1 = h + S1 + ch + round_k[i] + wi; - const uint64_t maj = (a & b) ^ (a & c) ^ (b & c); - const uint64_t temp2 = S0 + maj; - - /* Update round state */ - h = g; - g = f; - f = e; - e = d + temp1; - d = c; - c = b; - b = a; - a = temp1 + temp2; - - /* w[wrap(i)] becomes w[i + 16] */ - w[i & 15] = wi + s0 + wi7 + s1; - } - - /* Store state */ - s->h[0] += a; - s->h[1] += b; - s->h[2] += c; - s->h[3] += d; - s->h[4] += e; - s->h[5] += f; - s->h[6] += g; - s->h[7] += h; -} - -void sha512_final(struct sha512_state *s, const uint8_t *blk, - size_t total_size) -{ - uint8_t temp[SHA512_BLOCK_SIZE] = {0}; - const size_t last_size = total_size & (SHA512_BLOCK_SIZE - 1); - - if (last_size) - memcpy(temp, blk, last_size); - temp[last_size] = 0x80; - - if (last_size > 111) { - sha512_block(s, temp); - memset(temp, 0, sizeof(temp)); - } - - /* Note: we assume total_size fits in 61 bits */ - store64(temp + SHA512_BLOCK_SIZE - 8, total_size << 3); - sha512_block(s, temp); -} - -void sha512_get(const struct sha512_state *s, uint8_t *hash, - unsigned int offset, unsigned int len) -{ - int i; - - if (offset > SHA512_BLOCK_SIZE) - return; - - if (len > SHA512_BLOCK_SIZE - offset) - len = SHA512_BLOCK_SIZE - offset; - - /* Skip whole words */ - i = offset >> 3; - offset &= 7; - - /* Skip/read out bytes */ - if (offset) { - uint8_t tmp[8]; - unsigned int c = 8 - offset; - - if (c > len) - c = len; - - store64(tmp, s->h[i++]); - memcpy(hash, tmp + offset, c); - len -= c; - hash += c; - } - - /* Read out whole words */ - while (len >= 8) { - store64(hash, s->h[i++]); - hash += 8; - len -= 8; - } - - /* Read out bytes */ - if (len) { - uint8_t tmp[8]; - - store64(tmp, s->h[i]); - memcpy(hash, tmp, len); - } -} -#endif diff --git a/src/microsui_core/lib/compact25519/c25519/sha512.h b/src/microsui_core/lib/compact25519/c25519/sha512.h deleted file mode 100644 index 881118e..0000000 --- a/src/microsui_core/lib/compact25519/c25519/sha512.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SHA512 - * Daniel Beer , 22 Apr 2014 - * - * This file is in the public domain. - */ - -#ifndef SHA512_H_ -#define SHA512_H_ - -#if !defined(COMPACT_DISABLE_ED25519) || !defined(COMPACT_DISABLE_X25519_DERIVE) -#include -#include -#include - -/* SHA512 state. State is updated as data is fed in, and then the final - * hash can be read out in slices. - * - * Data is fed in as a sequence of full blocks terminated by a single - * partial block. - */ -struct sha512_state { - uint64_t h[8]; -}; - -/* Initial state */ -extern const struct sha512_state sha512_initial_state; - -/* Set up a new context */ -static inline void sha512_init(struct sha512_state *s) -{ - memcpy(s, &sha512_initial_state, sizeof(*s)); -} - -/* Feed a full block in */ -#define SHA512_BLOCK_SIZE 128 - -void sha512_block(struct sha512_state *s, const uint8_t *blk); - -/* Feed the last partial block in. The total stream size must be - * specified. The size of the block given is assumed to be (total_size % - * SHA512_BLOCK_SIZE). This might be zero, but you still need to call - * this function to terminate the stream. - */ -void sha512_final(struct sha512_state *s, const uint8_t *blk, - size_t total_size); - -/* Fetch a slice of the hash result. */ -#define SHA512_HASH_SIZE 64 - -void sha512_get(const struct sha512_state *s, uint8_t *hash, - unsigned int offset, unsigned int len); - -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/compact_ed25519.c b/src/microsui_core/lib/compact25519/compact_ed25519.c deleted file mode 100644 index 26d07e9..0000000 --- a/src/microsui_core/lib/compact25519/compact_ed25519.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "compact_ed25519.h" - -#ifndef COMPACT_DISABLE_ED25519 -#include "c25519/edsign.h" -#include "compact_wipe.h" -#include - -#define __PUBLIC_KEY_OFFSET (32) - -void compact_ed25519_keygen( - uint8_t private_key[ED25519_PRIVATE_KEY_SIZE], - uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], - uint8_t random_seed[ED25519_SEED_SIZE] -) { - // private key is seed + public key, like golang and others - edsign_sec_to_pub(public_key, random_seed); - memcpy(private_key, random_seed, ED25519_SEED_SIZE); - memcpy(private_key + __PUBLIC_KEY_OFFSET, public_key, ED25519_PUBLIC_KEY_SIZE); - compact_wipe(random_seed, ED25519_SEED_SIZE); -} - -void compact_ed25519_calc_public_key( - uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], - const uint8_t private_key[ED25519_PRIVATE_KEY_SIZE] -) { - memcpy(public_key, private_key + __PUBLIC_KEY_OFFSET, ED25519_PUBLIC_KEY_SIZE); -} - -void compact_ed25519_sign( - uint8_t signature[ED25519_SIGNATURE_SIZE], - const uint8_t private_key[ED25519_PRIVATE_KEY_SIZE], - const void *message, - size_t msg_length -) { - edsign_sign(signature, private_key + __PUBLIC_KEY_OFFSET, private_key, message, msg_length); -} - -bool compact_ed25519_verify( - const uint8_t signature[ED25519_SIGNATURE_SIZE], - const uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], - const void *message, - size_t msg_length -) { - return edsign_verify(signature, public_key, message, msg_length) != 0; -} -#endif diff --git a/src/microsui_core/lib/compact25519/compact_ed25519.h b/src/microsui_core/lib/compact25519/compact_ed25519.h deleted file mode 100644 index a78a601..0000000 --- a/src/microsui_core/lib/compact25519/compact_ed25519.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef _COMPACT_ED25519_H -#define _COMPACT_ED25519_H - -#ifndef COMPACT_DISABLE_ED25519 -/* - Ed25519 signs messages using Curve25519. - - After pre-sharing a public key, it allows two parties to verify the other side - is who they say they are and that the communication is not altered. - - A signature is a ED25519_SIGNATURE_SIZE size byte array that can be only be - generated when you have the private key, but can be verified if you have - the public key. - - As an example: two parties want to have rotating keys for their encryption. - The only thing they need to know about eachother is their long term Ed25519 - public key. Per session they perform a X25519 key exchange, but sign their - "Ephemeral" public key with their long-term Ed25519 private key. Now they can - share this public key (and the signature) over a cleartext channel, nobody can - alter of impersonate this exchange. - - (this is roughly how TLS works) -*/ -#include -#include -#include - -#define ED25519_SEED_SIZE (32) -#define ED25519_PUBLIC_KEY_SIZE (32) -#define ED25519_PRIVATE_KEY_SIZE (64) -#define ED25519_SIGNATURE_SIZE (64) - -/* - Generate a private signing key from a random seed. - - input: - - random_seed = random bytes that need to be filled from a good source of - random entropy, PLEASE research the options on your platform! - - output: - - private_key = signing key than can be used for compact_ed25519_sign - - public_key = key to share with other parties - - (internally the format of the private key is the seed + public key, - this makes it compatible with keys coming from libsodium, golang, and - implentations that derive from SUPERCOP/ref10) -*/ -void compact_ed25519_keygen( - uint8_t private_key[ED25519_PRIVATE_KEY_SIZE], - uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], - uint8_t random_seed[ED25519_SEED_SIZE] -); - -/* - Extract public key from private key - - input: - - private_key = signing key generated with compact_ed25519_keygen - - output: - - public_key = public key corresponding to this private key, share with - interested parties -*/ -void compact_ed25519_calc_public_key( - uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], - const uint8_t private_key[ED25519_PRIVATE_KEY_SIZE] -); - -/* - Sign a message with the private key. - - input: - - private_key = signing key generated with compact_ed25519_keygen or from a - compatible source - - message = pointer to the data that needs to be signed - - msg_length = how many bytes to read from the start of the message pointer - output: - - signature = the signature that proves you hold the private key and that - nobody tried to change the message. (the second property only holds - if the attacker cannot change the size of the message) -*/ -void compact_ed25519_sign( - uint8_t signature[ED25519_SIGNATURE_SIZE], - const uint8_t private_key[ED25519_PRIVATE_KEY_SIZE], - const void *message, - size_t msg_length -); - -/* - Verify a signature against a public key. - - input: - - signature = which signature to verify - - public_key = the public key that it should be verified against - (should not have been part of the message that contained the signature) - - message = message to verify - - msg_length = size of the message to verify - - returns: - true if verified -*/ -bool compact_ed25519_verify( - const uint8_t signature[ED25519_SIGNATURE_SIZE], - const uint8_t public_key[ED25519_PUBLIC_KEY_SIZE], - const void *message, - size_t msg_length -); -#endif - -#endif diff --git a/src/microsui_core/lib/compact25519/compact_wipe.c b/src/microsui_core/lib/compact25519/compact_wipe.c deleted file mode 100644 index e3c7049..0000000 --- a/src/microsui_core/lib/compact25519/compact_wipe.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "compact_wipe.h" -#include -#include - -void *compact_wipe(void *data, size_t length) { -// simplification of: https://www.cryptologie.net/article/419/zeroing-memory-compiler-optimizations-and-memset_s/ - volatile unsigned char *p = data; - while (length--){ - *p++ = 0; - } - return data; -} diff --git a/src/microsui_core/lib/compact25519/compact_wipe.h b/src/microsui_core/lib/compact25519/compact_wipe.h deleted file mode 100644 index cd348e0..0000000 --- a/src/microsui_core/lib/compact25519/compact_wipe.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __COMPACT_WIPE_H -#define __COMPACT_WIPE_H -#include -#include -/* - Try to wipe contents of a buffer, as best as we can. - (memset can be ignored by the compiler) - - Use this to clear private key data if you do not need it anymore. - - returns the data pointer, makes for easier chaining -*/ -void *compact_wipe(void *data, size_t length); -#endif diff --git a/src/microsui_core/lib/compact25519/compact_x25519.c b/src/microsui_core/lib/compact25519/compact_x25519.c deleted file mode 100644 index 7733764..0000000 --- a/src/microsui_core/lib/compact25519/compact_x25519.c +++ /dev/null @@ -1,68 +0,0 @@ - -#ifndef COMPACT_DISABLE_X25519 -#include "compact_x25519.h" -#include "c25519/c25519.h" -#include "c25519/sha512.h" -#include "compact_wipe.h" - -void compact_x25519_keygen( - uint8_t private_key[X25519_KEY_SIZE], - uint8_t public_key[X25519_KEY_SIZE], - uint8_t random_seed[X25519_KEY_SIZE] -) { - memcpy(private_key, random_seed, X25519_KEY_SIZE); - compact_wipe(random_seed, X25519_KEY_SIZE); - c25519_prepare(private_key); - c25519_smult(public_key, c25519_base_x, private_key); -} - -void compact_x25519_shared( - uint8_t shared_secret[X25519_SHARED_SIZE], - const uint8_t my_private_key[X25519_KEY_SIZE], - const uint8_t their_public_key[X25519_KEY_SIZE] -) { - // Ensure that supplied private key is clamped (fix issue #1). - // Calling `c25519_prepare` multiple times for the same private key - // is OK because it won't modify already clamped key. - uint8_t clamped_private_key[X25519_KEY_SIZE]; - memcpy(clamped_private_key, my_private_key, X25519_KEY_SIZE); - c25519_prepare(clamped_private_key); - c25519_smult(shared_secret, their_public_key, clamped_private_key); - compact_wipe(clamped_private_key, X25519_KEY_SIZE); -} - -#ifndef COMPACT_DISABLE_X25519_DERIVE -#if (X25519_KEY_SIZE + (2 * X25519_KEY_SIZE)) > SHA512_BLOCK_SIZE -#error "Unexpected key sizes" -#endif - -static uint8_t* append(uint8_t *dst, const void * source, size_t length) { - memcpy(dst, source, length); - return dst + length; -} - -void compact_x25519_derive_encryption_key( - uint8_t *encryption_key, - size_t key_size, - const uint8_t shared_secret[X25519_SHARED_SIZE], - const uint8_t public_key1[X25519_KEY_SIZE], - const uint8_t public_key2[X25519_KEY_SIZE] -) { - if (key_size > SHA512_HASH_SIZE) { - key_size = SHA512_HASH_SIZE; - } - uint8_t key_data[X25519_SHARED_SIZE + 2 * X25519_KEY_SIZE]; - uint8_t *p = key_data; - p = append(p, shared_secret, X25519_SHARED_SIZE); - p = append(p, public_key1, X25519_KEY_SIZE); - append(p, public_key2, X25519_KEY_SIZE); - - struct sha512_state hasher; - sha512_init(&hasher); - sha512_final(&hasher, key_data, sizeof(key_data)); - sha512_get(&hasher, encryption_key, 0, key_size); - - compact_wipe(key_data, X25519_SHARED_SIZE); // clear the session key at least -} -#endif -#endif diff --git a/src/microsui_core/lib/compact25519/compact_x25519.h b/src/microsui_core/lib/compact25519/compact_x25519.h deleted file mode 100644 index 41879b8..0000000 --- a/src/microsui_core/lib/compact25519/compact_x25519.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef _COMPACT_X25519_H -#define _COMPACT_X25519_H - -#ifndef COMPACT_DISABLE_X25519 -/* - X25519 is a DH key exchange over Curve25519. - - Two parties can share their public keys over an open channel and agree upon - a shared secret, that a third party cannot derive. - - Security concern: if a third party can intercept and change your connection in - some way, then X25519 is not enough. The third party could for example run - two X25519 sessions, one between themselfs and you, and another one between - themselfs and the server. X25519 has no protection against this. - - A possible solution is to use Ed25519 to sign the public keys exchanged, with a - special set of keys that is known before hand. Depending on your scenario, this - either means embedding a set of long-term keys in your application or setting up - some kind of Public Key Infrastructure (PKI). - - If that sounds to complicated or would not work for your case, checkout - the Noise framework. It is a bit less compact than X25519 + Ed25519 but much - more flexible in the kind of session setup styles. -*/ - -#include -#include - -#define X25519_KEY_SIZE (32) -#define X25519_SHARED_SIZE (32) - -/* - Calculate public & private keypair for X25519 key exchange. - Never transmit the private_key! - - input: - - random_seed = random bytes that need to be filled from a good source of - random entropy, PLEASE research the options on your platform! - - output: - - private_key = resulting private key, never share this with the other party - - public_key = public key to be shared with the other party -*/ -void compact_x25519_keygen( - uint8_t private_key[X25519_KEY_SIZE], - uint8_t public_key[X25519_KEY_SIZE], - uint8_t random_seed[X25519_KEY_SIZE] -); - -/* - Calculate shared secret based on the others side public key. - The shared secret does not have a uniform distribution so common advice - is to avoid using it directly as a key. You can use - compact_x25519_derive_encryption_key to get a more suitable encryption - key out of this shared secret - - input: - - my_private_key = private key that came out of compact_x25519_keygen - - their_public_key = public key that was shared by the other party - - output: - - shared_secret = X25519_SHARED_SIZE bytes that both sides now share -*/ -void compact_x25519_shared( - uint8_t shared_secret[X25519_SHARED_SIZE], - const uint8_t my_private_key[X25519_KEY_SIZE], - const uint8_t their_public_key[X25519_KEY_SIZE] -); - -#ifndef COMPACT_DISABLE_X25519_DERIVE -/* - Derive an more suitable encryption key from the shared secret. - This is not part of the normal X25519 specification, but the specifications - does warn that the shared secret is less suited as symmetric encryption key. - - The encryption key is the result of - sha512(concat(shared_secret, public_key1, public_key2))[0..key_size] - - You have to make sure both parties agree which public key goes in first. - - input: - - key_size = number between 1 and 64, of how big your encryption_key - needs to be, make sure there is enough room where - the encryption_key points to - - shared_secret = result of compact_x25519_shared - - public_key1 = first public key to mix in with the key - - public_key2 = second public key to mix in with the key - - output: - - encryption_key = supplied buffer is filled with a encryption key -*/ -void compact_x25519_derive_encryption_key( - uint8_t *encryption_key, - size_t key_size, - const uint8_t shared_secret[X25519_SHARED_SIZE], - const uint8_t public_key1[X25519_KEY_SIZE], - const uint8_t public_key2[X25519_KEY_SIZE] -); -#endif -#endif -#endif diff --git a/src/microsui_core/lib/monocypher/monocypher.c b/src/microsui_core/lib/monocypher/monocypher.c index b9f26d4..840f238 100644 --- a/src/microsui_core/lib/monocypher/monocypher.c +++ b/src/microsui_core/lib/monocypher/monocypher.c @@ -3382,6 +3382,104 @@ int crypto_ed25519_ph_check(const uint8_t sig[64], const uint8_t pk[32], } +// Added by MicroSui: Ed25519 signature (pure / RFC 8032) using SHA-512. +// This function is not part of the original Monocypher distribution; it is added by MicroSui +// to provide compatibility with implementations that follow the standard SHA-512-based Ed25519.// It does NOT replace Monocypher's crypto_ed25519_sign (which uses BLAKE2b). +// secret_key layout: seed[32] || public_key[32] +// signature layout : R[32] || S[32] +// Precondition: if message_size > 0, message must be non-NULL. +void crypto_ed25519_sign_sha512(uint8_t signature[64], + const uint8_t secret_key[64], + const uint8_t *message, + size_t message_size) +{ + u8 a[64]; // a[0..31]=scalar (clamped), a[32..63]=prefix + u8 r64[64]; // full hash for r + u8 h64[64]; // full hash for h + u8 r[32]; + u8 h[32]; + u8 R[32]; + + crypto_sha512_ctx sha; + + // 1) a || prefix = SHA512(seed); clamp(a) + crypto_sha512_init(&sha); + crypto_sha512_update(&sha, secret_key, 32); // seed + crypto_sha512_final(&sha, a); + crypto_eddsa_trim_scalar(a, a); // clamp first 32 bytes + + // 2) r = SHA512(prefix || message) mod L + crypto_sha512_init(&sha); + crypto_sha512_update(&sha, a + 32, 32); // prefix + if (message_size) { crypto_sha512_update(&sha, message, message_size); } + crypto_sha512_final(&sha, r64); + crypto_eddsa_reduce(r, r64); + + // 3) R = [r]B + crypto_eddsa_scalarbase(R, r); + + // 4) h = SHA512(R || public_key || message) mod L + crypto_sha512_init(&sha); + crypto_sha512_update(&sha, R, 32); + crypto_sha512_update(&sha, secret_key + 32, 32); // public_key + if (message_size) { crypto_sha512_update(&sha, message, message_size); } + crypto_sha512_final(&sha, h64); + crypto_eddsa_reduce(h, h64); + + // 5) S = (h * a + r) mod L; signature = R || S + COPY(signature, R, 32); + crypto_eddsa_mul_add(signature + 32, h, a, r); + + // Wipe secrets + WIPE_CTX(&sha); + WIPE_BUFFER(a); WIPE_BUFFER(r64); WIPE_BUFFER(h64); + WIPE_BUFFER(r); WIPE_BUFFER(h); WIPE_BUFFER(R); + + // Optional (defense-in-depth; enable in debug builds): + // #ifdef MICROSUI_STRICT + // u8 pk_chk[32]; + // crypto_eddsa_scalarbase(pk_chk, a); // a[0..31] is the clamped scalar + // if (crypto_verify32(pk_chk, secret_key + 32)) { + // // Mismatched seed/public key; handle as you prefer (abort/log). + // } + // WIPE_BUFFER(pk_chk); + // #endif +} + +// Ed25519 signature verification (pure / RFC 8032) using SHA-512. +// This function is not part of the original Monocypher distribution; it is added by MicroSui +// to provide compatibility with implementations that follow the standard SHA-512-based Ed25519. +// It does NOT replace Monocypher's crypto_ed25519_check (which uses BLAKE2b). +// public_key layout: A[32] +// signature layout : R[32] || S[32] +// Precondition: if msg_size > 0, msg must be non-NULL. +int crypto_ed25519_check_sha512(const uint8_t signature[64], + const uint8_t public_key[32], + const uint8_t *msg, + size_t msg_size) +{ + u8 h_ram[32]; + u8 hash[64]; + crypto_sha512_ctx sha; + + // h = SHA512(R || A || M) mod L + crypto_sha512_init(&sha); + crypto_sha512_update(&sha, signature, 32); // R + crypto_sha512_update(&sha, public_key, 32); // A + if (msg_size) { crypto_sha512_update(&sha, msg, msg_size); } + crypto_sha512_final(&sha, hash); + + crypto_eddsa_reduce(h_ram, hash); + + // Clean hash state + crypto_wipe(&sha, sizeof sha); + WIPE_BUFFER(hash); + + // Check equation: [S]B = R + [h]A + return crypto_eddsa_check_equation(signature, public_key, h_ram); +} + + #ifdef MONOCYPHER_CPP_NAMESPACE } #endif \ No newline at end of file diff --git a/src/microsui_core/lib/monocypher/monocypher.h b/src/microsui_core/lib/monocypher/monocypher.h index d4781a2..36b2b69 100644 --- a/src/microsui_core/lib/monocypher/monocypher.h +++ b/src/microsui_core/lib/monocypher/monocypher.h @@ -383,6 +383,16 @@ int crypto_ed25519_ph_check(const uint8_t signature [64], const uint8_t public_key [32], const uint8_t message_hash[64]); +// Variants added by MicroSui +void crypto_ed25519_sign_sha512(uint8_t signature[64], + const uint8_t secret_key[64], + const uint8_t *message, + size_t message_size); + +int crypto_ed25519_check_sha512(const uint8_t signature[64], + const uint8_t public_key[32], + const uint8_t *msg, + size_t msg_size); #ifdef __cplusplus } diff --git a/src/microsui_core/sign.c b/src/microsui_core/sign.c index 9fc38bf..8869b7b 100644 --- a/src/microsui_core/sign.c +++ b/src/microsui_core/sign.c @@ -5,9 +5,9 @@ #include #include #include -#include "byte_conversions.h" #include "lib/monocypher/monocypher.h" -#include "lib/compact25519/compact_ed25519.h" + +#include "byte_conversions.h" /** * @brief Sign a Sui Transaction message using Ed25519 and produce a Sui-formatted signature. @@ -16,10 +16,10 @@ * signs the digest with Ed25519, and encodes the result in the Sui signature * format (scheme byte + 64-byte Ed25519 signature + 32-byte public key). * - * @param[out] sui_sig 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] private_key 32-byte Ed25519 private key seed. + * @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] seed 32-byte Ed25519 private key seed. * * @return 0 on success, negative value on error. * @@ -27,15 +27,15 @@ * [0x00 scheme | 64-byte signature | 32-byte public key]. * @note This function is specific to the Ed25519 scheme. */ -int microsui_sign_ed25519(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, const uint8_t private_key[32]) { - // 1. Copy private key to a local variable - uint8_t private_key_cp[32]; - memcpy(private_key_cp, private_key, 32); +int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const size_t message_len, const uint8_t seed[32]) { + // 1. Copy seed to a local variable + uint8_t seed_cp[32]; + memcpy(seed_cp, seed, 32); // 2. Generate public and secret key uint8_t public_key[32]; uint8_t secret_key[64]; - crypto_ed25519_key_pair(secret_key, public_key, private_key_cp); + crypto_ed25519_key_pair(secret_key, public_key, seed_cp); // 3. Generate digest using BLAKE2b with the message with the intent uint8_t digest[32]; @@ -49,17 +49,17 @@ int microsui_sign_ed25519(uint8_t sui_sig[97], const uint8_t* message, const siz crypto_blake2b_final(&ctx, digest); - // 4. Sign the digest using Ed25519 with the private key and public key + // 4. Sign the digest using Ed25519 with the secret key and public key uint8_t ed25519_signature[64]; - compact_ed25519_sign(ed25519_signature, secret_key, digest, 32); + crypto_ed25519_sign_sha512(ed25519_signature, secret_key, digest, 32); // 5. Build Sui signature - sui_sig[0] = 0x00; // Ed25519 Scheme - memcpy(sui_sig + 1, ed25519_signature, 64); - memcpy(sui_sig + 65, public_key, 32); + sui_sig_out[0] = 0x00; // Ed25519 Scheme + memcpy(sui_sig_out + 1, ed25519_signature, 64); + memcpy(sui_sig_out + 65, public_key, 32); crypto_wipe(secret_key, sizeof secret_key); - crypto_wipe(private_key_cp, sizeof private_key_cp); + crypto_wipe(seed_cp, sizeof seed_cp); crypto_wipe(&ctx, sizeof ctx); crypto_wipe(digest, sizeof digest); @@ -72,11 +72,11 @@ int microsui_sign_ed25519(uint8_t sui_sig[97], const uint8_t* message, const siz * Dispatches to the appropriate signing routine depending on the provided * scheme identifier. Currently only Ed25519 (0x00) is implemented. * - * @param[in] scheme Identifier of the signing scheme (0x00 = Ed25519). - * @param[out] sui_sig Output buffer for the Sui signature (must be 97 bytes). - * @param[in] message Pointer to the message/transaction bytes. - * @param[in] message_len Length of the message in bytes. - * @param[in] private_key 32-byte private key seed (scheme dependent). + * @param[out] sui_sig_out Output buffer for the Sui signature (must be 97 bytes). + * @param[in] scheme Identifier of the signing scheme (0x00 = Ed25519). + * @param[in] message Pointer to the message/transaction bytes. + * @param[in] message_len Length of the message in bytes. + * @param[in] seed 32-byte private key seed. * * @return 0 on success if scheme is supported, * -1 if the scheme is not implemented or unsupported. @@ -85,10 +85,10 @@ int microsui_sign_ed25519(uint8_t sui_sig[97], const uint8_t* message, const siz * - 0x00: Ed25519 (implemented). * - Others (Secp256k1, Secp256r1, Multisig, zkLogin, Passkey) are not yet implemented. */ -int microsui_sign(uint8_t scheme, uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, const uint8_t private_key[32]) { +int microsui_sign(uint8_t sui_sig_out[97], uint8_t scheme, const uint8_t* message, const size_t message_len, const uint8_t seed[32]) { switch (scheme) { case 0x00: // Pure Ed25519 - return microsui_sign_ed25519(sui_sig, message, message_len, private_key); + return microsui_sign_ed25519(sui_sig_out, message, message_len, seed); case 0x01: // ECDSA Secp256k1 fprintf(stderr, "Error: ECDSA Secp256k1 signing is not implemented yet in MicroSui.\n"); return -1; // Not implemented @@ -123,7 +123,8 @@ int microsui_sign(uint8_t scheme, uint8_t sui_sig[97], const uint8_t* message, c * @param[in] message_len Length of the transaction bytes. * * @return 0 if the signature is valid, - * -1 if the signature is invalid or the scheme byte is not Ed25519 (0x00). + * -1 if the scheme byte is not Ed25519 (0x00). + * -2 if the signature verification fails for a supported scheme * * @note The "intent" prefix used is {0x00, 0x00, 0x00}, matching the signing routine. * @note This function does not recover a public key; it verifies using the public key @@ -148,8 +149,73 @@ int microsui_verify_signature_ed25519(uint8_t sui_sig[97], const uint8_t* messag crypto_blake2b_update(&ctx, message, message_len); crypto_blake2b_final(&ctx, digest); - if(compact_ed25519_verify(signature, public_key, digest, 32)) return 0; - else return -1; + 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 and validate it against a known public key. + * + * Expects a Sui signature encoded as: + * [0x00 scheme | 64-byte Ed25519 signature | 32-byte public key] + * + * Rebuilds the Sui "message with intent" (prefix + tx bytes), digests it with + * BLAKE2b-256, verifies the Ed25519 signature using the public key embedded in + * the signature payload, and then confirms that the embedded public key matches + * the caller-supplied public key using a constant-time comparison. + * + * @param[in] sui_sig Pointer to the Sui signature buffer (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] 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 The "intent" prefix used is {0x00, 0x00, 0x00}, matching the signing routine. + * @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(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, 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); + + 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); + + 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 } /** @@ -163,11 +229,16 @@ int microsui_verify_signature_ed25519(uint8_t sui_sig[97], const uint8_t* messag * @param[in] message_len Length of the message in bytes. * * @return 0 if the signature is valid for the detected scheme, - * -1 if the scheme is unsupported or verification fails. + * -1 if the scheme is unsupported or not implemented, + * -2 if the signature verification fails for a supported scheme * * @note Currently supported schemes: - * - 0x00: Ed25519 (implemented). - * - Others (Secp256k1, Secp256r1, Multisig, zkLogin, Passkey) are not yet implemented. + * - 0x00: Ed25519. + * @note Not yet implemented: + * - Secp256k1 (0x01), Secp256r1 (0x02), Multisig (0x03), zkLogin (0x05), Passkey (0x06). + * @see microsui_verify_signature_ed25519() + * @see microsui_verify_signature_with_public_key() for the variant that also + * validates the embedded public key against a caller-supplied expected key. */ int microsui_verify_signature(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len) { switch (sui_sig[0]) { @@ -178,8 +249,44 @@ int microsui_verify_signature(uint8_t sui_sig[97], const uint8_t* message, const } } +/** + * @brief Generic signature verification entry point with expected public key validation. + * + * Dispatches to the appropriate verification routine based on the scheme byte + * found in the provided Sui signature (sui_sig[0]), and additionally confirms + * that the public key embedded in the signature matches the caller-supplied key. + * + * @param[in] sui_sig Pointer to the Sui signature buffer (must be 97 bytes). + * @param[in] message Pointer to the message/transaction bytes (already serialized). + * @param[in] message_len Length of the message in bytes. + * @param[in] public_key Pointer to the expected 32-byte public key for the detected scheme. + * + * @return 0 if the signature is valid and the embedded public key matches @p public_key, + * -1 if the scheme byte is unsupported or not yet implemented, + * -2 if the signature verification fails for a supported scheme, + * -3 if the public key embedded in the signature does not match @p public_key. + * + * @note Currently supported schemes: + * - 0x00: Ed25519. + * @note Not yet implemented: + * - Secp256k1 (0x01), Secp256r1 (0x02), Multisig (0x03), zkLogin (0x05), Passkey (0x06). + * @note The public key comparison is delegated to the scheme-specific routine + * and performed in constant time to mitigate timing attacks. + * @see microsui_verify_signature_ed25519_with_public_key() + * @see microsui_verify_signature() for the variant that does not validate + * the embedded public key against an expected value. + */ +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]) { + switch (sui_sig[0]) { + case 0x00: // Ed25519 + return microsui_verify_signature_ed25519_with_public_key(sui_sig, message, message_len, public_key); + default: + return -1; // Unsupported scheme + } +} + -/// DEPRECATED FUNCTIONS /// +/////////// DEPRECATED FUNCTIONS /////////// /** * @brief [DEPRECATED] Use microsui_sign() or microsui_sign_ed25519() instead. * @@ -187,20 +294,20 @@ int microsui_verify_signature(uint8_t sui_sig[97], const uint8_t* message, const * Please use microsui_sign() or microsui_sign_ed25519(), * which provide better compatibility and performance. * - * @param[out] sui_sig Output buffer for the Sui signature (must be 97 bytes). + * @param[out] sui_sig_out Output buffer for the Sui signature (must be 97 bytes). * @param[in] message_hex Null-terminated string containing the full serialized tx message in hexa form. - * @param[in] private_key 32-byte Ed25519 private key seed. + * @param[in] seed 32-byte Ed25519 private key seed. * * @return 0 on success, negative value on error. */ -int microsui_sign_message(uint8_t sui_sig[97], const char* message_hex, const uint8_t private_key[32]) { +int microsui_sign_message(uint8_t sui_sig_out[97], const char* message_hex, const uint8_t seed[32]) { // Convert the hex message to binary bytes size_t msg_len = strlen(message_hex) / 2; // 2 hex chars = 1 byte uint8_t* message = (uint8_t*)malloc(msg_len); hex_to_bytes(message_hex, message, msg_len); // Call the new ED25519 sign function version - int res = microsui_sign_ed25519(sui_sig, message, msg_len, private_key); + int res = microsui_sign_ed25519(sui_sig_out, message, msg_len, seed); free(message); return res; diff --git a/src/microsui_core/sign.h b/src/microsui_core/sign.h index 38cc75f..26fbbdc 100644 --- a/src/microsui_core/sign.h +++ b/src/microsui_core/sign.h @@ -4,17 +4,21 @@ #include #include -int microsui_sign(uint8_t scheme, uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, const uint8_t private_key[32]); +int microsui_sign(uint8_t sui_sig_out[97], uint8_t scheme, const uint8_t* message, const size_t message_len, const uint8_t seed[32]); -int microsui_sign_ed25519(uint8_t sui_sig[97], const uint8_t* message, const size_t message_len, const uint8_t private_key[32]); +int microsui_sign_ed25519(uint8_t sui_sig_out[97], const uint8_t* message, const size_t message_len, const uint8_t seed[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_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(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]); + /** * @deprecated Use microsui_sign() or microsui_sign_ed25519() instead. */ -int microsui_sign_message(uint8_t sui_sig[97], const char* message_hex, const uint8_t private_key[32]); +int microsui_sign_message(uint8_t sui_sig_out[97], const char* message_hex, const uint8_t seed[32]); #endif \ No newline at end of file