First commit on a late git install

This commit is contained in:
2025-08-09 10:23:28 -04:00
commit ca6b4754f9
88 changed files with 18219 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
/*
* Example: Input Type Detection
* Demonstrates nostr_detect_input_type() and nostr_decode_nsec()
*/
#include <stdio.h>
#include <stdlib.h>
#include "nostr_core.h"
int main() {
printf("=== NOSTR Input Type Detection Example ===\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Test various input types
const char* test_inputs[] = {
// Mnemonic
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
// Hex nsec (64 chars)
"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
// Bech32 nsec
"nsec1tkks0lxyf9x2jetlzluxsqqwudlnwvef9xx2muxvt7tsh7lgmrhqvfmaqg",
// Invalid input
"not-a-valid-input",
// Empty string
""
};
const char* type_names[] = {
"UNKNOWN",
"MNEMONIC",
"HEX_NSEC",
"BECH32_NSEC"
};
int num_tests = sizeof(test_inputs) / sizeof(test_inputs[0]);
for (int i = 0; i < num_tests; i++) {
printf("Test %d:\n", i + 1);
printf("Input: \"%s\"\n", test_inputs[i]);
// Detect input type
nostr_input_type_t type = nostr_detect_input_type(test_inputs[i]);
printf("Detected Type: %s\n", type_names[type]);
// Try to decode if it's an nsec
if (type == NOSTR_INPUT_NSEC_HEX || type == NOSTR_INPUT_NSEC_BECH32) {
unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
int result = nostr_decode_nsec(test_inputs[i], private_key);
if (result == NOSTR_SUCCESS) {
// Convert back to hex and bech32 to verify
char private_hex[NOSTR_HEX_KEY_SIZE];
char nsec_bech32[NOSTR_BECH32_KEY_SIZE];
nostr_bytes_to_hex(private_key, NOSTR_PRIVATE_KEY_SIZE, private_hex);
nostr_key_to_bech32(private_key, "nsec", nsec_bech32);
printf("✓ Successfully decoded nsec!\n");
printf(" Hex format: %s\n", private_hex);
printf(" Bech32 format: %s\n", nsec_bech32);
} else {
printf("✗ Failed to decode nsec: %s\n", nostr_strerror(result));
}
}
printf("\n");
}
// Cleanup
nostr_cleanup();
printf("✓ Example completed successfully!\n");
printf("💡 Input detection helps handle different key formats automatically\n");
return 0;
}

View File

@@ -0,0 +1,39 @@
# Example CMakeLists.txt for a project using nostr_core library
cmake_minimum_required(VERSION 3.12)
project(my_nostr_app VERSION 1.0.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
# Method 1: Find installed package
# Uncomment if nostr_core is installed system-wide
# find_package(nostr_core REQUIRED)
# Method 2: Use as subdirectory
# Uncomment if nostr_core is a subdirectory
# add_subdirectory(nostr_core)
# Method 3: Use pkg-config
# Uncomment if using pkg-config
# find_package(PkgConfig REQUIRED)
# pkg_check_modules(NOSTR_CORE REQUIRED nostr_core)
# Create executable
add_executable(my_nostr_app main.c)
# Link with nostr_core
# Choose one of the following based on your integration method:
# Method 1: Installed package
# target_link_libraries(my_nostr_app nostr_core::static)
# Method 2: Subdirectory
# target_link_libraries(my_nostr_app nostr_core_static)
# Method 3: pkg-config
# target_include_directories(my_nostr_app PRIVATE ${NOSTR_CORE_INCLUDE_DIRS})
# target_link_libraries(my_nostr_app ${NOSTR_CORE_LIBRARIES})
# For this example, we'll assume Method 2 (subdirectory)
# Add the parent nostr_core directory
add_subdirectory(../.. nostr_core)
target_link_libraries(my_nostr_app nostr_core_static)

View File

@@ -0,0 +1,186 @@
# NOSTR Core Integration Example
This directory contains a complete example showing how to integrate the NOSTR Core library into your own projects.
## What This Example Demonstrates
- **Library Initialization**: Proper setup and cleanup of the NOSTR library
- **Identity Management**: Key generation, bech32 encoding, and format detection
- **Event Creation**: Creating and signing different types of NOSTR events
- **Input Handling**: Processing various input formats (mnemonic, hex, bech32)
- **Utility Functions**: Using helper functions for hex conversion and error handling
- **CMake Integration**: How to integrate the library in your CMake-based project
## Building and Running
### Method 1: Using CMake
```bash
# Create build directory
mkdir build && cd build
# Configure with CMake
cmake ..
# Build
make
# Run the example
./my_nostr_app
```
### Method 2: Manual Compilation
```bash
# Compile directly (assuming you're in the c_nostr root directory)
gcc -I. examples/integration_example/main.c nostr_core.c nostr_crypto.c cjson/cJSON.c -lm -o integration_example
# Run
./integration_example
```
## Expected Output
The example will demonstrate:
1. **Identity Management Demo**
- Generate a new keypair
- Display keys in hex and bech32 format
2. **Event Creation Demo**
- Create a text note event
- Create a profile event
- Display the JSON for both events
3. **Input Handling Demo**
- Process different input formats
- Show format detection and decoding
4. **Utility Functions Demo**
- Hex conversion round-trip
- Error message display
## Integration Patterns
### Pattern 1: CMake Find Package
If NOSTR Core is installed system-wide:
```cmake
find_package(nostr_core REQUIRED)
target_link_libraries(your_app nostr_core::static)
```
### Pattern 2: CMake Subdirectory
If NOSTR Core is a subdirectory of your project:
```cmake
add_subdirectory(nostr_core)
target_link_libraries(your_app nostr_core_static)
```
### Pattern 3: pkg-config
If using pkg-config:
```cmake
find_package(PkgConfig REQUIRED)
pkg_check_modules(NOSTR_CORE REQUIRED nostr_core)
target_include_directories(your_app PRIVATE ${NOSTR_CORE_INCLUDE_DIRS})
target_link_libraries(your_app ${NOSTR_CORE_LIBRARIES})
```
### Pattern 4: Direct Source Integration
Copy the essential files to your project:
```bash
cp nostr_core.{c,h} nostr_crypto.{c,h} your_project/src/
cp -r cjson/ your_project/src/
```
Then compile them with your project sources.
## Code Structure
### main.c Structure
The example is organized into clear demonstration functions:
- `demo_identity_management()` - Key generation and encoding
- `demo_event_creation()` - Creating different event types
- `demo_input_handling()` - Processing various input formats
- `demo_utilities()` - Using utility functions
Each function demonstrates specific aspects of the library while maintaining proper error handling and resource cleanup.
### Key Integration Points
1. **Initialization**
```c
int ret = nostr_init();
if (ret != NOSTR_SUCCESS) {
// Handle error
}
```
2. **Resource Cleanup**
```c
// Always clean up JSON objects
cJSON_Delete(event);
// Clean up library on exit
nostr_cleanup();
```
3. **Error Handling**
```c
if (ret != NOSTR_SUCCESS) {
printf("Error: %s\n", nostr_strerror(ret));
return ret;
}
```
## Customization
You can modify this example for your specific needs:
- Change the `app_config_t` structure to match your application's configuration
- Add additional event types or custom event creation logic
- Integrate with your existing error handling and logging systems
- Add networking functionality using the WebSocket layer
## Dependencies
This example requires:
- C99 compiler (gcc, clang)
- CMake 3.12+ (for CMake build)
- NOSTR Core library and its dependencies
## Testing
You can test different input formats by passing them as command line arguments:
```bash
# Test with mnemonic
./my_nostr_app "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
# Test with hex private key
./my_nostr_app "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
# Test with bech32 nsec
./my_nostr_app "nsec1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```
## Next Steps
After studying this example, you can:
1. Integrate the patterns into your own application
2. Explore the WebSocket functionality for relay communication
3. Add support for additional NOSTR event types
4. Implement your own identity persistence layer
5. Add networking and relay management features
For more examples, see the other files in the `examples/` directory.

View File

@@ -0,0 +1,271 @@
/*
* Example application demonstrating how to integrate nostr_core into other projects
* This shows a complete workflow from key generation to event publishing
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nostr_core.h"
// Example application configuration
typedef struct {
char* app_name;
char* version;
int debug_mode;
} app_config_t;
static app_config_t g_config = {
.app_name = "My NOSTR App",
.version = "1.0.0",
.debug_mode = 1
};
// Helper function to print hex data
static void print_hex(const char* label, const unsigned char* data, size_t len) {
if (g_config.debug_mode) {
printf("%s: ", label);
for (size_t i = 0; i < len; i++) {
printf("%02x", data[i]);
}
printf("\n");
}
}
// Helper function to print JSON nicely
static void print_event(const char* label, cJSON* event) {
if (!event) {
printf("%s: NULL\n", label);
return;
}
char* json_string = cJSON_Print(event);
if (json_string) {
printf("%s:\n%s\n", label, json_string);
free(json_string);
}
}
// Example: Generate and manage identity
static int demo_identity_management(void) {
printf("\n=== Identity Management Demo ===\n");
unsigned char private_key[32], public_key[32];
char nsec[100], npub[100];
// Generate a new keypair
printf("Generating new keypair...\n");
int ret = nostr_generate_keypair(private_key, public_key);
if (ret != NOSTR_SUCCESS) {
printf("Error generating keypair: %s\n", nostr_strerror(ret));
return ret;
}
print_hex("Private Key", private_key, 32);
print_hex("Public Key", public_key, 32);
// Convert to bech32 format
ret = nostr_key_to_bech32(private_key, "nsec", nsec);
if (ret != NOSTR_SUCCESS) {
printf("Error encoding nsec: %s\n", nostr_strerror(ret));
return ret;
}
ret = nostr_key_to_bech32(public_key, "npub", npub);
if (ret != NOSTR_SUCCESS) {
printf("Error encoding npub: %s\n", nostr_strerror(ret));
return ret;
}
printf("nsec: %s\n", nsec);
printf("npub: %s\n", npub);
return NOSTR_SUCCESS;
}
// Example: Create different types of events
static int demo_event_creation(const unsigned char* private_key) {
printf("\n=== Event Creation Demo ===\n");
// Create a text note
printf("Creating text note...\n");
cJSON* text_event = nostr_create_text_event("Hello from my NOSTR app!", private_key);
if (!text_event) {
printf("Error creating text event\n");
return NOSTR_ERROR_JSON_PARSE;
}
print_event("Text Event", text_event);
// Create a profile event
printf("\nCreating profile event...\n");
cJSON* profile_event = nostr_create_profile_event(
g_config.app_name,
"A sample application demonstrating NOSTR integration",
private_key
);
if (!profile_event) {
printf("Error creating profile event\n");
cJSON_Delete(text_event);
return NOSTR_ERROR_JSON_PARSE;
}
print_event("Profile Event", profile_event);
// Cleanup
cJSON_Delete(text_event);
cJSON_Delete(profile_event);
return NOSTR_SUCCESS;
}
// Example: Handle different input formats
static int demo_input_handling(const char* user_input) {
printf("\n=== Input Handling Demo ===\n");
printf("Processing input: %s\n", user_input);
// Detect input type
int input_type = nostr_detect_input_type(user_input);
switch (input_type) {
case NOSTR_INPUT_MNEMONIC:
printf("Detected: BIP39 Mnemonic\n");
{
unsigned char priv[32], pub[32];
int ret = nostr_derive_keys_from_mnemonic(user_input, 0, priv, pub);
if (ret == NOSTR_SUCCESS) {
print_hex("Derived Private Key", priv, 32);
print_hex("Derived Public Key", pub, 32);
}
}
break;
case NOSTR_INPUT_NSEC_HEX:
printf("Detected: Hex-encoded private key\n");
{
unsigned char decoded[32];
int ret = nostr_decode_nsec(user_input, decoded);
if (ret == NOSTR_SUCCESS) {
print_hex("Decoded Private Key", decoded, 32);
}
}
break;
case NOSTR_INPUT_NSEC_BECH32:
printf("Detected: Bech32-encoded private key (nsec)\n");
{
unsigned char decoded[32];
int ret = nostr_decode_nsec(user_input, decoded);
if (ret == NOSTR_SUCCESS) {
print_hex("Decoded Private Key", decoded, 32);
}
}
break;
default:
printf("Unknown input format\n");
return NOSTR_ERROR_INVALID_INPUT;
}
return NOSTR_SUCCESS;
}
// Example: Demonstrate utility functions
static int demo_utilities(void) {
printf("\n=== Utility Functions Demo ===\n");
// Hex conversion
const char* test_hex = "deadbeef";
unsigned char bytes[4];
char hex_result[9];
printf("Testing hex conversion with: %s\n", test_hex);
int ret = nostr_hex_to_bytes(test_hex, bytes, 4);
if (ret != NOSTR_SUCCESS) {
printf("Error in hex_to_bytes: %s\n", nostr_strerror(ret));
return ret;
}
nostr_bytes_to_hex(bytes, 4, hex_result);
printf("Round-trip result: %s\n", hex_result);
// Error message testing
printf("\nTesting error messages:\n");
for (int i = 0; i >= -10; i--) {
const char* msg = nostr_strerror(i);
if (msg && strlen(msg) > 0) {
printf(" %d: %s\n", i, msg);
}
}
return NOSTR_SUCCESS;
}
int main(int argc, char* argv[]) {
printf("%s v%s\n", g_config.app_name, g_config.version);
printf("NOSTR Core Integration Example\n");
printf("=====================================\n");
// Initialize the NOSTR library
printf("Initializing NOSTR core library...\n");
int ret = nostr_init();
if (ret != NOSTR_SUCCESS) {
printf("Failed to initialize NOSTR library: %s\n", nostr_strerror(ret));
return 1;
}
// Run demonstrations
unsigned char demo_private_key[32];
// 1. Identity management
ret = demo_identity_management();
if (ret != NOSTR_SUCCESS) {
goto cleanup;
}
// Generate a key for other demos
nostr_generate_keypair(demo_private_key, NULL);
// 2. Event creation
ret = demo_event_creation(demo_private_key);
if (ret != NOSTR_SUCCESS) {
goto cleanup;
}
// 3. Input handling (use command line argument if provided)
const char* test_input = (argc > 1) ? argv[1] :
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
ret = demo_input_handling(test_input);
if (ret != NOSTR_SUCCESS && ret != NOSTR_ERROR_INVALID_INPUT) {
goto cleanup;
}
// 4. Utility functions
ret = demo_utilities();
if (ret != NOSTR_SUCCESS) {
goto cleanup;
}
printf("\n=====================================\n");
printf("All demonstrations completed successfully!\n");
printf("\nThis example shows how to:\n");
printf(" • Initialize the NOSTR library\n");
printf(" • Generate and manage keypairs\n");
printf(" • Create and sign different event types\n");
printf(" • Handle various input formats\n");
printf(" • Use utility functions\n");
printf(" • Clean up resources properly\n");
ret = NOSTR_SUCCESS;
cleanup:
// Clean up the NOSTR library
printf("\nCleaning up NOSTR library...\n");
nostr_cleanup();
if (ret == NOSTR_SUCCESS) {
printf("Example completed successfully.\n");
return 0;
} else {
printf("Example failed with error: %s\n", nostr_strerror(ret));
return 1;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Example: Random Keypair Generation
* Demonstrates nostr_generate_keypair()
*/
#include <stdio.h>
#include <stdlib.h>
#include "nostr_core.h"
int main() {
printf("=== NOSTR Random Keypair Generation Example ===\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Generate a random keypair
unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
unsigned char public_key[NOSTR_PUBLIC_KEY_SIZE];
int result = nostr_generate_keypair(private_key, public_key);
if (result != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to generate keypair: %s\n", nostr_strerror(result));
nostr_cleanup();
return 1;
}
// Convert to hex format
char private_hex[NOSTR_HEX_KEY_SIZE];
char public_hex[NOSTR_HEX_KEY_SIZE];
nostr_bytes_to_hex(private_key, NOSTR_PRIVATE_KEY_SIZE, private_hex);
nostr_bytes_to_hex(public_key, NOSTR_PUBLIC_KEY_SIZE, public_hex);
// Convert to bech32 format
char nsec[NOSTR_BECH32_KEY_SIZE];
char npub[NOSTR_BECH32_KEY_SIZE];
nostr_key_to_bech32(private_key, "nsec", nsec);
nostr_key_to_bech32(public_key, "npub", npub);
// Display results
printf("✓ Successfully generated random NOSTR keypair\n\n");
printf("Private Key (hex): %s\n", private_hex);
printf("Public Key (hex): %s\n", public_hex);
printf("nsec (bech32): %s\n", nsec);
printf("npub (bech32): %s\n", npub);
// Cleanup
nostr_cleanup();
printf("\n✓ Example completed successfully!\n");
return 0;
}

View File

@@ -0,0 +1,57 @@
/*
* Example: Key Derivation from Existing Mnemonic
* Demonstrates nostr_derive_keys_from_mnemonic()
*/
#include <stdio.h>
#include <stdlib.h>
#include "nostr_core.h"
int main() {
printf("=== NOSTR Key Derivation from Mnemonic Example ===\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Use a well-known test mnemonic
const char* test_mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
printf("Using test mnemonic: %s\n\n", test_mnemonic);
// Derive keys for multiple accounts
for (int account = 0; account < 3; account++) {
unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
unsigned char public_key[NOSTR_PUBLIC_KEY_SIZE];
int result = nostr_derive_keys_from_mnemonic(test_mnemonic, account,
private_key, public_key);
if (result != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to derive keys for account %d: %s\n",
account, nostr_strerror(result));
continue;
}
// Convert to bech32 format
char nsec[NOSTR_BECH32_KEY_SIZE];
char npub[NOSTR_BECH32_KEY_SIZE];
nostr_key_to_bech32(private_key, "nsec", nsec);
nostr_key_to_bech32(public_key, "npub", npub);
// Display results for this account
printf("Account %d (m/44'/1237'/%d'/0/0):\n", account, account);
printf(" nsec: %s\n", nsec);
printf(" npub: %s\n", npub);
printf("\n");
}
// Cleanup
nostr_cleanup();
printf("✓ Example completed successfully!\n");
printf("💡 The same mnemonic always produces the same keys (deterministic)\n");
return 0;
}

View File

@@ -0,0 +1,60 @@
/*
* Example: Mnemonic Generation and Key Derivation
* Demonstrates nostr_generate_mnemonic_and_keys()
*/
#include <stdio.h>
#include <stdlib.h>
#include "nostr_core.h"
int main() {
printf("=== NOSTR Mnemonic Generation Example ===\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Generate mnemonic and derive keys for account 0
char mnemonic[256];
unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
unsigned char public_key[NOSTR_PUBLIC_KEY_SIZE];
int account = 0;
int result = nostr_generate_mnemonic_and_keys(mnemonic, sizeof(mnemonic),
account, private_key, public_key);
if (result != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to generate mnemonic and keys: %s\n", nostr_strerror(result));
nostr_cleanup();
return 1;
}
// Convert keys to various formats
char private_hex[NOSTR_HEX_KEY_SIZE];
char public_hex[NOSTR_HEX_KEY_SIZE];
char nsec[NOSTR_BECH32_KEY_SIZE];
char npub[NOSTR_BECH32_KEY_SIZE];
nostr_bytes_to_hex(private_key, NOSTR_PRIVATE_KEY_SIZE, private_hex);
nostr_bytes_to_hex(public_key, NOSTR_PUBLIC_KEY_SIZE, public_hex);
nostr_key_to_bech32(private_key, "nsec", nsec);
nostr_key_to_bech32(public_key, "npub", npub);
// Display results
printf("✓ Successfully generated BIP39 mnemonic and derived NOSTR keys\n\n");
printf("BIP39 Mnemonic: %s\n\n", mnemonic);
printf("Account: %d\n", account);
printf("Derivation Path: m/44'/1237'/%d'/0/0 (NIP-06)\n\n", account);
printf("Private Key (hex): %s\n", private_hex);
printf("Public Key (hex): %s\n", public_hex);
printf("nsec (bech32): %s\n", nsec);
printf("npub (bech32): %s\n", npub);
// Cleanup
nostr_cleanup();
printf("\n✓ Example completed successfully!\n");
printf("💡 Save the mnemonic safely - it can restore your NOSTR identity\n");
return 0;
}

BIN
examples/simple_keygen Executable file

Binary file not shown.

95
examples/simple_keygen.c Normal file
View File

@@ -0,0 +1,95 @@
/*
* Simple Key Generation Example
*
* This example demonstrates basic NOSTR key generation using the nostr_core library.
*/
#include <stdio.h>
#include <stdlib.h>
#include "nostr_core.h"
int main() {
printf("NOSTR Core Library - Simple Key Generation Example\n");
printf("==================================================\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR core library\n");
return 1;
}
printf("✓ NOSTR core library initialized\n\n");
// Generate a random keypair
unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
unsigned char public_key[NOSTR_PUBLIC_KEY_SIZE];
printf("Generating random NOSTR keypair...\n");
int result = nostr_generate_keypair(private_key, public_key);
if (result != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to generate keypair: %s\n", nostr_strerror(result));
nostr_cleanup();
return 1;
}
// Convert keys to hex format
char private_hex[NOSTR_HEX_KEY_SIZE];
char public_hex[NOSTR_HEX_KEY_SIZE];
nostr_bytes_to_hex(private_key, NOSTR_PRIVATE_KEY_SIZE, private_hex);
nostr_bytes_to_hex(public_key, NOSTR_PUBLIC_KEY_SIZE, public_hex);
// Convert keys to bech32 format
char nsec_bech32[NOSTR_BECH32_KEY_SIZE];
char npub_bech32[NOSTR_BECH32_KEY_SIZE];
if (nostr_key_to_bech32(private_key, "nsec", nsec_bech32) != NOSTR_SUCCESS ||
nostr_key_to_bech32(public_key, "npub", npub_bech32) != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to convert keys to bech32 format\n");
nostr_cleanup();
return 1;
}
// Display the generated keys
printf("✓ Keypair generated successfully!\n\n");
printf("Private Key (hex): %s\n", private_hex);
printf("Public Key (hex): %s\n", public_hex);
printf("nsec (bech32): %s\n", nsec_bech32);
printf("npub (bech32): %s\n", npub_bech32);
printf("\n=== Key Validation Test ===\n");
// Test key validation by decoding the generated nsec
unsigned char decoded_private_key[NOSTR_PRIVATE_KEY_SIZE];
result = nostr_decode_nsec(nsec_bech32, decoded_private_key);
if (result == NOSTR_SUCCESS) {
printf("✓ nsec validation: PASSED\n");
// Verify the decoded key matches the original
int keys_match = 1;
for (int i = 0; i < NOSTR_PRIVATE_KEY_SIZE; i++) {
if (private_key[i] != decoded_private_key[i]) {
keys_match = 0;
break;
}
}
if (keys_match) {
printf("✓ Key consistency: PASSED\n");
} else {
printf("✗ Key consistency: FAILED\n");
}
} else {
printf("✗ nsec validation: FAILED (%s)\n", nostr_strerror(result));
}
// Cleanup
nostr_cleanup();
printf("\nExample completed successfully!\n");
printf("You can now use these keys with NOSTR applications.\n");
return 0;
}

View File

@@ -0,0 +1,165 @@
/*
* Example: Utility Functions
* Demonstrates nostr_bytes_to_hex(), nostr_hex_to_bytes(), nostr_strerror()
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "nostr_core.h"
int main() {
printf("=== NOSTR Utility Functions Example ===\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Test 1: Bytes to Hex conversion
printf("Test 1: Bytes to Hex Conversion\n");
printf("-------------------------------\n");
unsigned char test_bytes[] = {
0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b,
0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6,
0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd,
0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb
};
char hex_output[65]; // 32 bytes * 2 + null terminator
nostr_bytes_to_hex(test_bytes, sizeof(test_bytes), hex_output);
printf("Input bytes (%zu bytes):\n", sizeof(test_bytes));
printf(" ");
for (size_t i = 0; i < sizeof(test_bytes); i++) {
printf("%02x ", test_bytes[i]);
if ((i + 1) % 16 == 0) printf("\n ");
}
printf("\n");
printf("Hex output: %s\n\n", hex_output);
// Test 2: Hex to Bytes conversion
printf("Test 2: Hex to Bytes Conversion\n");
printf("-------------------------------\n");
const char* test_hex = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb";
unsigned char bytes_output[32];
printf("Input hex: %s\n", test_hex);
int result = nostr_hex_to_bytes(test_hex, bytes_output, sizeof(bytes_output));
if (result == NOSTR_SUCCESS) {
printf("✓ Successfully converted hex to bytes\n");
printf("Output bytes (%zu bytes):\n", sizeof(bytes_output));
printf(" ");
for (size_t i = 0; i < sizeof(bytes_output); i++) {
printf("%02x ", bytes_output[i]);
if ((i + 1) % 16 == 0) printf("\n ");
}
printf("\n");
// Verify round-trip conversion
int match = memcmp(test_bytes, bytes_output, sizeof(test_bytes)) == 0;
printf("Round-trip verification: %s\n\n", match ? "✓ PASSED" : "✗ FAILED");
} else {
printf("✗ Failed to convert hex to bytes: %s\n\n", nostr_strerror(result));
}
// Test 3: Error code to string conversion
printf("Test 3: Error Code to String Conversion\n");
printf("---------------------------------------\n");
int error_codes[] = {
NOSTR_SUCCESS,
NOSTR_ERROR_INVALID_INPUT,
NOSTR_ERROR_CRYPTO_FAILED,
NOSTR_ERROR_MEMORY_FAILED,
NOSTR_ERROR_IO_FAILED,
NOSTR_ERROR_NETWORK_FAILED,
-999 // Unknown error code
};
int num_errors = sizeof(error_codes) / sizeof(error_codes[0]);
for (int i = 0; i < num_errors; i++) {
int code = error_codes[i];
const char* message = nostr_strerror(code);
printf("Error code %d: %s\n", code, message);
}
printf("\n");
// Test 4: Invalid hex string handling
printf("Test 4: Invalid Hex String Handling\n");
printf("------------------------------------\n");
const char* invalid_hex_strings[] = {
"invalid_hex_string", // Non-hex characters
"5dab087e624a8a4b79e17f8b", // Too short (24 chars, need 64)
"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0ebaa", // Too long (66 chars)
"", // Empty string
"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eZ" // Invalid hex char 'Z'
};
int num_invalid = sizeof(invalid_hex_strings) / sizeof(invalid_hex_strings[0]);
for (int i = 0; i < num_invalid; i++) {
printf("Testing invalid hex: \"%s\"\n", invalid_hex_strings[i]);
unsigned char invalid_output[32];
result = nostr_hex_to_bytes(invalid_hex_strings[i], invalid_output, sizeof(invalid_output));
if (result == NOSTR_SUCCESS) {
printf(" ✗ Unexpectedly succeeded (should have failed)\n");
} else {
printf(" ✓ Correctly failed: %s\n", nostr_strerror(result));
}
}
printf("\n");
// Test 5: Working with real NOSTR keys
printf("Test 5: Real NOSTR Key Conversion\n");
printf("---------------------------------\n");
// Generate a real keypair
unsigned char private_key[NOSTR_PRIVATE_KEY_SIZE];
unsigned char public_key[NOSTR_PUBLIC_KEY_SIZE];
result = nostr_generate_keypair(private_key, public_key);
if (result == NOSTR_SUCCESS) {
// Convert to hex
char private_hex[NOSTR_HEX_KEY_SIZE];
char public_hex[NOSTR_HEX_KEY_SIZE];
nostr_bytes_to_hex(private_key, NOSTR_PRIVATE_KEY_SIZE, private_hex);
nostr_bytes_to_hex(public_key, NOSTR_PUBLIC_KEY_SIZE, public_hex);
printf("Generated NOSTR keys:\n");
printf("Private key (hex): %s\n", private_hex);
printf("Public key (hex): %s\n", public_hex);
// Convert back to bytes to verify
unsigned char recovered_private[NOSTR_PRIVATE_KEY_SIZE];
unsigned char recovered_public[NOSTR_PUBLIC_KEY_SIZE];
int priv_result = nostr_hex_to_bytes(private_hex, recovered_private, NOSTR_PRIVATE_KEY_SIZE);
int pub_result = nostr_hex_to_bytes(public_hex, recovered_public, NOSTR_PUBLIC_KEY_SIZE);
if (priv_result == NOSTR_SUCCESS && pub_result == NOSTR_SUCCESS) {
int priv_match = memcmp(private_key, recovered_private, NOSTR_PRIVATE_KEY_SIZE) == 0;
int pub_match = memcmp(public_key, recovered_public, NOSTR_PUBLIC_KEY_SIZE) == 0;
printf("Key recovery verification:\n");
printf(" Private key: %s\n", priv_match ? "✓ PASSED" : "✗ FAILED");
printf(" Public key: %s\n", pub_match ? "✓ PASSED" : "✗ FAILED");
}
}
// Cleanup
nostr_cleanup();
printf("\n✓ Example completed successfully!\n");
printf("💡 Utility functions handle format conversions and error reporting\n");
return 0;
}