9.2 KiB
NOSTR Core Library - Usage Guide
Overview
The NOSTR Core Library (libnostr_core
) is a self-contained, exportable C library for NOSTR protocol implementation. It requires no external cryptographic dependencies (no OpenSSL, no libwally) and can be easily integrated into other projects.
Key Features
- Self-Contained Crypto: All cryptographic operations implemented from scratch
- Zero External Dependencies: Only requires standard C library, cJSON, and libwebsockets
- Cross-Platform: Builds on Linux, macOS, Windows (with appropriate toolchain)
- NIP-06 Compliant: Proper BIP39/BIP32 implementation for key derivation
- Thread-Safe: Core cryptographic functions are stateless and thread-safe
- Easy Integration: Simple C API with clear error handling
File Structure for Export
Core Library Files (Required)
libnostr_core/
├── nostr_core.h # Main public API header
├── nostr_core.c # Core implementation
├── nostr_crypto.h # Crypto implementation header
├── nostr_crypto.c # Self-contained crypto implementation
├── Makefile # Build configuration
└── cjson/ # JSON library (can be replaced with system cJSON)
├── cJSON.h
└── cJSON.c
Optional Files
├── examples/ # Usage examples (helpful for integration)
├── LIBRARY_USAGE.md # This usage guide
├── SELF_CONTAINED_CRYPTO.md # Crypto implementation details
└── CROSS_PLATFORM_GUIDE.md # Platform-specific build notes
Integration Methods
Method 1: Static Library Integration
-
Copy Required Files:
cp nostr_core.h nostr_core.c nostr_crypto.h nostr_crypto.c /path/to/your/project/ cp -r cjson/ /path/to/your/project/
-
Build Static Library:
gcc -c -fPIC nostr_core.c nostr_crypto.c cjson/cJSON.c ar rcs libnostr_core.a nostr_core.o nostr_crypto.o cJSON.o
-
Link in Your Project:
gcc your_project.c -L. -lnostr_core -lm -o your_project
Method 2: Direct Source Integration
Simply include the source files directly in your project:
// In your project
#include "nostr_core.h"
// Compile with:
// gcc your_project.c nostr_core.c nostr_crypto.c cjson/cJSON.c -lm
Method 3: Shared Library Integration
-
Build Shared Library:
make libnostr_core.so
-
Install System-Wide (optional):
sudo cp libnostr_core.so /usr/local/lib/ sudo cp nostr_core.h /usr/local/include/ sudo ldconfig
-
Use in Projects:
gcc your_project.c -lnostr_core -lm
Building the Library
Using the Provided Build Script
The library includes an automated build script that handles all dependencies and creates a self-contained static library.
IMPORTANT: The build script must be run from within the nostr_core_lib
directory:
# Correct usage:
cd nostr_core_lib
./build.sh
# If you need to use it from your project directory:
cd nostr_core_lib
./build.sh
cd ..
gcc your_app.c nostr_core_lib/libnostr_core_x64.a -lz -ldl -lpthread -lm -o your_app
Common Error: Running ./nostr_core_lib/build.sh
from outside the library directory will fail with:
[ERROR] Build script must be run from the nostr_core_lib directory
Build Script Options
# Auto-detect NIPs from your source code
./build.sh
# Force specific NIPs
./build.sh --nips=1,6,19
# Build all available NIPs
./build.sh --nips=all
# Build for specific architecture
./build.sh arm64
# Build with tests
./build.sh --tests
# Get help
./build.sh --help
The build script automatically:
- Scans your
.c
files for#include "nip*.h"
statements - Compiles only the needed NIPs
- Creates a self-contained static library (
libnostr_core_x64.a
) - Includes all dependencies (OpenSSL, curl, secp256k1, cJSON)
Basic Usage Example
#include "nostr_core.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Generate a keypair
unsigned char private_key[32];
unsigned char public_key[32];
if (nostr_generate_keypair(private_key, public_key) != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to generate keypair\n");
nostr_cleanup();
return 1;
}
// Convert to hex and bech32
char private_hex[65], public_hex[65];
char nsec[100], npub[100];
nostr_bytes_to_hex(private_key, 32, private_hex);
nostr_bytes_to_hex(public_key, 32, public_hex);
nostr_key_to_bech32(private_key, "nsec", nsec);
nostr_key_to_bech32(public_key, "npub", npub);
printf("Private Key: %s\n", private_hex);
printf("Public Key: %s\n", public_hex);
printf("nsec: %s\n", nsec);
printf("npub: %s\n", npub);
// Create and sign an event
cJSON* event = nostr_create_text_event("Hello NOSTR!", private_key);
if (event) {
char* event_json = cJSON_Print(event);
printf("Signed Event: %s\n", event_json);
free(event_json);
cJSON_Delete(event);
}
// Cleanup
nostr_cleanup();
return 0;
}
Dependency Management
Required Dependencies
- Standard C Library: malloc, string functions, file I/O
- Math Library:
-lm
(for cryptographic calculations) - cJSON: JSON parsing (included, or use system version)
Optional Dependencies
- libwebsockets: Only needed for relay communication functions
- System cJSON: Can replace bundled version
Minimal Integration (Crypto Only)
If you only need key generation and signing:
# Build with minimal dependencies
gcc -DNOSTR_CRYPTO_ONLY your_project.c nostr_crypto.c -lm
Cross-Platform Considerations
Linux
- Works out of the box with GCC
- Install build-essential:
sudo apt install build-essential
macOS
- Works with Xcode command line tools
- May need:
xcode-select --install
Windows
- Use MinGW-w64 or MSYS2
- Or integrate with Visual Studio project
Embedded Systems
- Library is designed to work on resource-constrained systems
- No heap allocations in core crypto functions
- Stack usage is predictable and bounded
API Reference
Initialization
int nostr_init(void); // Initialize library
void nostr_cleanup(void); // Cleanup resources
const char* nostr_strerror(int error); // Get error string
Key Generation
int nostr_generate_keypair(unsigned char* private_key, unsigned char* public_key);
int nostr_generate_mnemonic_and_keys(char* mnemonic, size_t mnemonic_size,
int account, unsigned char* private_key,
unsigned char* public_key);
int nostr_derive_keys_from_mnemonic(const char* mnemonic, int account,
unsigned char* private_key, unsigned char* public_key);
Event Creation
cJSON* nostr_create_text_event(const char* content, const unsigned char* private_key);
cJSON* nostr_create_profile_event(const char* name, const char* about,
const unsigned char* private_key);
int nostr_sign_event(cJSON* event, const unsigned char* private_key);
Utilities
void nostr_bytes_to_hex(const unsigned char* bytes, size_t len, char* hex);
int nostr_hex_to_bytes(const char* hex, unsigned char* bytes, size_t len);
int nostr_key_to_bech32(const unsigned char* key, const char* hrp, char* output);
nostr_input_type_t nostr_detect_input_type(const char* input);
Error Handling
All functions return standardized error codes:
NOSTR_SUCCESS
(0): Operation successfulNOSTR_ERROR_INVALID_INPUT
(-1): Invalid parametersNOSTR_ERROR_CRYPTO_FAILED
(-2): Cryptographic operation failedNOSTR_ERROR_MEMORY_FAILED
(-3): Memory allocation failedNOSTR_ERROR_IO_FAILED
(-4): File I/O operation failedNOSTR_ERROR_NETWORK_FAILED
(-5): Network operation failed
Security Considerations
- Private Key Handling: Always clear private keys from memory when done
- Random Number Generation: Uses
/dev/urandom
on Unix systems - Memory Safety: All buffers are bounds-checked
- Constant-Time Operations: Critical crypto operations are timing-attack resistant
Testing Your Integration
Use the provided examples to verify your integration:
# Test key generation
./examples/simple_keygen
# Test mnemonic functionality
./examples/mnemonic_generation
# Test event creation
./examples/text_event
# Test all functionality
./examples/utility_functions
Support and Documentation
- See
examples/
directory for comprehensive usage examples - Check
SELF_CONTAINED_CRYPTO.md
for cryptographic implementation details - Review
CROSS_PLATFORM_GUIDE.md
for platform-specific notes - All functions are documented in
nostr_core.h
License
This library is designed to be freely integrable into other projects. Check the individual file headers for specific licensing information.
Quick Start: Copy nostr_core.h
, nostr_core.c
, nostr_crypto.h
, nostr_crypto.c
, and the cjson/
folder to your project, then compile with -lm
. That's it!