Files
nostr_core_lib/README.md
T

604 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NOSTR Core Library
A C library for NOSTR protocol implementation. Work in progress.
[![Version](https://img.shields.io/badge/version-0.5.12-blue.svg)](VERSION)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](#license)
[![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg)](#building)
## 📋 NIP Implementation Status
### Core Protocol NIPs
- [x] [NIP-01](nips/01.md) - Basic protocol flow - event creation, signing, and validation
- [ ] [NIP-02](nips/02.md) - Contact List and Petnames
- [x] [NIP-03](nips/03.md) - OpenTimestamps Attestations for Events
- [x] [NIP-04](nips/04.md) - Encrypted Direct Messages (legacy)
- [x] [NIP-05](nips/05.md) - Mapping Nostr keys to DNS-based internet identifiers
- [x] [NIP-06](nips/06.md) - Basic key derivation from mnemonic seed phrase
- [-] [NIP-07](nips/07.md) - `window.nostr` capability for web browsers
- [ ] [NIP-08](nips/08.md) - Handling Mentions
- [ ] [NIP-09](nips/09.md) - Event Deletion
- [ ] [NIP-10](nips/10.md) - Conventions for clients' use of `e` and `p` tags in text events
- [x] [NIP-11](nips/11.md) - Relay Information Document
- [ ] [NIP-12](nips/12.md) - Generic Tag Queries
- [x] [NIP-13](nips/13.md) - Proof of Work
- [ ] [NIP-14](nips/14.md) - Subject tag in text events
- [ ] [NIP-15](nips/15.md) - Nostr Marketplace (for resilient marketplaces)
- [ ] [NIP-16](nips/16.md) - Event Treatment
- [x] [NIP-17](nips/17.md) - Private Direct Messages
- [ ] [NIP-18](nips/18.md) - Reposts
- [x] [NIP-19](nips/19.md) - bech32-encoded entities
- [ ] [NIP-20](nips/20.md) - Command Results
- [x] [NIP-21](nips/21.md) - `nostr:` URI scheme
- [ ] [NIP-22](nips/22.md) - Event `created_at` Limits
- [ ] [NIP-23](nips/23.md) - Long-form Content
- [ ] [NIP-24](nips/24.md) - Extra metadata fields and tags
- [ ] [NIP-25](nips/25.md) - Reactions
- [ ] [NIP-26](nips/26.md) - Delegated Event Signing
- [ ] [NIP-27](nips/27.md) - Text Note References
- [ ] [NIP-28](nips/28.md) - Public Chat
- [ ] [NIP-29](nips/29.md) - Relay-based Groups
- [ ] [NIP-30](nips/30.md) - Custom Emoji
- [ ] [NIP-31](nips/31.md) - Dealing with Unknown Events
- [ ] [NIP-32](nips/32.md) - Labeling
- [ ] [NIP-33](nips/33.md) - Parameterized Replaceable Events
- [ ] [NIP-34](nips/34.md) - `git` stuff
- [ ] [NIP-35](nips/35.md) - Torrents
- [ ] [NIP-36](nips/36.md) - Sensitive Content / Content Warning
- [ ] [NIP-37](nips/37.md) - Draft Events
- [ ] [NIP-38](nips/38.md) - User Statuses
- [ ] [NIP-39](nips/39.md) - External Identities in Profiles
- [ ] [NIP-40](nips/40.md) - Expiration Timestamp
- [x] [NIP-42](nips/42.md) - Authentication of clients to relays
- [x] [NIP-44](nips/44.md) - Versioned Encryption
- [ ] [NIP-45](nips/45.md) - Counting results
- [x] [NIP-46](nips/46.md) - Nostr Remote Signing
- [ ] [NIP-47](nips/47.md) - Wallet Connect
- [ ] [NIP-48](nips/48.md) - Proxy Tags
- [ ] [NIP-49](nips/49.md) - Private Key Encryption
- [ ] [NIP-50](nips/50.md) - Search Capability
- [ ] [NIP-51](nips/51.md) - Lists
- [ ] [NIP-52](nips/52.md) - Calendar Events
- [ ] [NIP-53](nips/53.md) - Live Activities
- [ ] [NIP-54](nips/54.md) - Wiki
- [-] [NIP-55](nips/55.md) - Android Signer Application
- [ ] [NIP-56](nips/56.md) - Reporting
- [ ] [NIP-57](nips/57.md) - Lightning Zaps
- [ ] [NIP-58](nips/58.md) - Badges
- [x] [NIP-59](nips/59.md) - Gift Wrap
- [ ] [NIP-60](nips/60.md) - Cashu Wallet
- [ ] [NIP-61](nips/61.md) - Nutzaps
- [ ] [NIP-62](nips/62.md) - Log events
- [-] [NIP-64](nips/64.md) - Chess (PGN)
- [ ] [NIP-65](nips/65.md) - Relay List Metadata
- [ ] [NIP-66](nips/66.md) - Relay Monitor
- [-] [NIP-68](nips/68.md) - Web badges
- [ ] [NIP-69](nips/69.md) - Peer-to-peer Order events
- [ ] [NIP-70](nips/70.md) - Protected Events
- [ ] [NIP-71](nips/71.md) - Video Events
- [ ] [NIP-72](nips/72.md) - Moderated Communities
- [ ] [NIP-73](nips/73.md) - External Content IDs
- [ ] [NIP-75](nips/75.md) - Zap Goals
- [ ] [NIP-77](nips/77.md) - Arbitrary custom app data
- [ ] [NIP-78](nips/78.md) - Application-specific data
- [ ] [NIP-84](nips/84.md) - Highlights
- [ ] [NIP-86](nips/86.md) - Relay Management API
- [ ] [NIP-87](nips/87.md) - Relay List Recommendations
- [-] [NIP-88](nips/88.md) - Stella: A Stellar Relay
- [ ] [NIP-89](nips/89.md) - Recommended Application Handlers
- [ ] [NIP-90](nips/90.md) - Data Vending Machines
- [ ] [NIP-92](nips/92.md) - Media Attachments
- [ ] [NIP-94](nips/94.md) - File Metadata
- [ ] [NIP-96](nips/96.md) - HTTP File Storage Integration
- [ ] [NIP-98](nips/98.md) - HTTP Auth
- [ ] [NIP-99](nips/99.md) - Classified Listings
**Legend:** ✅ Fully Implemented | ⚠️ Partial Implementation | ❌ Not Implemented | Not Applicable
**Implementation Summary:** 13 of 96+ NIPs fully implemented (13.5%)
## 📦 Quick Start
### Installation
1. **Clone the repository:**
```bash
git clone https://github.com/yourusername/nostr_core_lib.git
cd nostr_core_lib
```
2. **Build the library:**
```bash
./build.sh
```
3. **Build and run examples:**
```bash
./build.sh -e
./examples/simple_keygen
```
### Usage Example
```c
#include "nostr_core/nostr_core.h"
#include <stdio.h>
int main() {
// Initialize library
if (nostr_init() != NOSTR_SUCCESS) {
fprintf(stderr, "Failed to initialize NOSTR library\n");
return 1;
}
// Generate keypair
unsigned char private_key[32], public_key[32];
nostr_generate_keypair(private_key, public_key);
// Convert to bech32 format
char nsec[100], npub[100];
nostr_key_to_bech32(private_key, "nsec", nsec);
nostr_key_to_bech32(public_key, "npub", npub);
printf("Private key: %s\n", nsec);
printf("Public key: %s\n", npub);
// Create and sign event
cJSON* event = nostr_create_and_sign_event(1, "Hello NOSTR!", NULL, private_key, 0);
if (event) {
char* json = cJSON_Print(event);
printf("Event: %s\n", json);
free(json);
cJSON_Delete(event);
}
nostr_cleanup();
return 0;
}
```
**Compile and run:**
```bash
gcc example.c -o example ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1
./example
```
## 🏗️ Building
### Build Targets
```bash
./build.sh # Build static library (default)
./build.sh --nips=all # Force build with all available NIPs
./build.sh -t # Build all test executables in tests/
./build.sh -e # Build all examples in examples/
./build.sh -t -e # Build library + tests + examples
./build.sh --nips=46 # Build specifically with NIP-046 support
./build.sh --help # Show all options
```
### Dependencies
**Required System Dependencies:**
- GCC or compatible C compiler
- Standard C library and math library (`-lm`)
- OpenSSL development libraries (`-lssl -lcrypto`)
- curl development libraries (`-lcurl`)
- secp256k1 development libraries (`-lsecp256k1`)
**Install on Ubuntu/Debian:**
```bash
sudo apt install build-essential libssl-dev libcurl4-openssl-dev libsecp256k1-dev
```
**Install on CentOS/RHEL:**
```bash
sudo yum install gcc openssl-devel libcurl-devel libsecp256k1-devel
```
**Install on macOS:**
```bash
brew install openssl curl secp256k1
```
**Still Bundled:**
- cJSON (JSON parsing - internal copy)
- TinyAES-c (AES encryption for NIP-04)
- ChaCha20 (stream cipher for NIP-44)
## 📚 API Documentation
### Initialization
```c
int nostr_init(void); // Initialize library (call first)
void nostr_cleanup(void); // Cleanup resources (call last)
const char* nostr_strerror(int error); // Get error message
```
### Key Management
```c
// Generate random keypair
int nostr_generate_keypair(unsigned char* private_key, unsigned char* public_key);
// Generate from mnemonic
int nostr_generate_mnemonic_and_keys(char* mnemonic, size_t mnemonic_size,
int account, unsigned char* private_key,
unsigned char* public_key);
// Derive from existing mnemonic
int nostr_derive_keys_from_mnemonic(const char* mnemonic, int account,
unsigned char* private_key, unsigned char* public_key);
// Format conversion
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);
```
### Event Creation
```c
// Create and sign event
cJSON* nostr_create_and_sign_event(int kind, const char* content, cJSON* tags,
const unsigned char* private_key, time_t timestamp);
// Add proof of work
int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key,
int target_difficulty, void (*progress_callback)(...), void* user_data);
```
### Encryption (NIP-04 & NIP-44)
```c
// NIP-04 (AES-CBC)
int nostr_nip04_encrypt(const unsigned char* sender_private_key,
const unsigned char* recipient_public_key,
const char* plaintext, char* output, size_t output_size);
int nostr_nip04_decrypt(const unsigned char* recipient_private_key,
const unsigned char* sender_public_key,
const char* encrypted_data, char* output, size_t output_size);
// NIP-44 (ChaCha20)
int nostr_nip44_encrypt(const unsigned char* sender_private_key,
const unsigned char* recipient_public_key,
const char* plaintext, char* output, size_t output_size);
int nostr_nip44_decrypt(const unsigned char* recipient_private_key,
const unsigned char* sender_public_key,
const char* encrypted_data, char* output, size_t output_size);
```
### Relay Communication
```c
// Simple relay query
cJSON* nostr_query_relay_for_event(const char* relay_url, const char* pubkey_hex, int kind);
// Multi-relay synchronous queries
cJSON** synchronous_query_relays_with_progress(const char** relay_urls, int relay_count,
cJSON* filter, relay_query_mode_t mode,
int* result_count, int relay_timeout_seconds,
relay_progress_callback_t callback, void* user_data);
// Multi-relay publishing
publish_result_t* synchronous_publish_event_with_progress(const char** relay_urls, int relay_count,
cJSON* event, int* success_count,
int relay_timeout_seconds,
publish_progress_callback_t callback, void* user_data);
```
### Relay Pools (Asynchronous)
```c
// Create and manage relay pool with reconnection
nostr_pool_reconnect_config_t* config = nostr_pool_reconnect_config_default();
nostr_relay_pool_t* nostr_relay_pool_create(nostr_pool_reconnect_config_t* config);
int nostr_relay_pool_add_relay(nostr_relay_pool_t* pool, const char* relay_url);
int nostr_relay_pool_set_auth(nostr_relay_pool_t* pool, const unsigned char* private_key, int enable);
void nostr_relay_pool_destroy(nostr_relay_pool_t* pool);
// Subscribe to events (with auto-reconnection)
nostr_pool_subscription_t* nostr_relay_pool_subscribe(
nostr_relay_pool_t* pool, const char** relay_urls, int relay_count, cJSON* filter,
void (*on_event)(cJSON* event, const char* relay_url, void* user_data),
void (*on_eose)(void* user_data), void* user_data, int close_on_eose);
// Enable NIP-42 auth (auto-responds to relay AUTH challenges)
unsigned char private_key[32];
nostr_hex_to_bytes("91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe", private_key, 32);
nostr_relay_pool_set_auth(pool, private_key, 1);
// Run event loop (handles reconnection + incoming AUTH/NOTICE/OK messages)
int nostr_relay_pool_run(nostr_relay_pool_t* pool, int timeout_ms);
int nostr_relay_pool_poll(nostr_relay_pool_t* pool, int timeout_ms);
// Reconnection configuration
typedef struct {
int enable_auto_reconnect; // Enable automatic reconnection
int max_reconnect_attempts; // Maximum retry attempts
int initial_reconnect_delay_ms; // Initial delay between attempts
int max_reconnect_delay_ms; // Maximum delay cap
int reconnect_backoff_multiplier; // Exponential backoff factor
int ping_interval_seconds; // Health check ping interval
int pong_timeout_seconds; // Pong response timeout
} nostr_pool_reconnect_config_t;
```
### NIP-05 Identifier Verification
```c
// Lookup public key from NIP-05 identifier
int nostr_nip05_lookup(const char* nip05_identifier, char* pubkey_hex_out,
char*** relays, int* relay_count, int timeout_seconds);
// Verify NIP-05 identifier against public key
int nostr_nip05_verify(const char* nip05_identifier, const char* pubkey_hex,
char*** relays, int* relay_count, int timeout_seconds);
// Parse .well-known/nostr.json response
int nostr_nip05_parse_well_known(const char* json_response, const char* local_part,
char* pubkey_hex_out, char*** relays, int* relay_count);
```
### NIP-11 Relay Information
```c
// Fetch relay information document
int nostr_nip11_fetch_relay_info(const char* relay_url, nostr_relay_info_t** info_out, int timeout_seconds);
// Free relay information structure
void nostr_nip11_relay_info_free(nostr_relay_info_t* info);
```
## 📁 Examples
The library includes comprehensive examples:
- **`simple_keygen`** - Basic key generation and formatting
- **`keypair_generation`** - Advanced key management
- **`mnemonic_generation`** - BIP39 mnemonic handling
- **`mnemonic_derivation`** - NIP-06 key derivation
- **`utility_functions`** - General utility demonstrations
- **`input_detection`** - Input type detection and processing
- **`relay_pool`** - Interactive relay pool and subscription testing
- **`send_nip17_dm`** - NIP-17 private direct message send flow
- **`nip46_remote_signer`** - NIP-46 remote signer flow and bunker URL generation
- **`version_test`** - Library version information
Build all examples:
```bash
./build.sh -e
ls -la examples/
```
## 🧪 Testing
The library includes extensive tests:
```bash
# Build all test executables
./build.sh -t
# Run the new NIP-46 test
./tests/nip46_test
# Run selected tests
./tests/nip44_test
./tests/nip42_test
./tests/nip17_test
```
**Current test binaries live in [`tests/`](tests/) and are generated from `*_test.c` sources.**
## 🏗️ Integration
### Static Library Integration (Recommended)
1. **Install system dependencies first** (see Dependencies section above)
2. **Copy required files to your project:**
```bash
cp libnostr_core_x64.a /path/to/your/project/
cp nostr_core/nostr_core.h /path/to/your/project/
```
3. **Link in your project:**
```bash
gcc your_code.c -L. -lnostr_core -lssl -lcrypto -lcurl -lsecp256k1 -lm -o your_program
```
### Source Integration
1. **Install system dependencies first** (see Dependencies section above)
2. **Copy source files:**
```bash
cp -r nostr_core/ /path/to/your/project/
cp -r cjson/ /path/to/your/project/
```
3. **Include in your build:**
```bash
gcc your_code.c nostr_core/*.c cjson/cJSON.c -lssl -lcrypto -lcurl -lsecp256k1 -lm -o your_program
```
### System Dependencies Library
The `libnostr_core.a` library now uses **system dependencies** for all major crypto libraries:
- ✅ **Uses system OpenSSL** (`-lssl -lcrypto`)
- ✅ **Uses system curl** (`-lcurl`)
- ✅ **Uses system secp256k1** (`-lsecp256k1`)
- ✅ **Includes only internal code** (cJSON, TinyAES, ChaCha20)
**Complete linking example:**
```bash
gcc your_app.c ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1 -o your_app
```
**Check system dependencies:**
```bash
ldd your_app # Shows linked system libraries
```
## 🔧 Configuration
### Compile-Time Options
```c
// Enable debug output
#define NOSTR_DEBUG_ENABLED
// Crypto-only build (no networking)
#define NOSTR_CRYPTO_ONLY
// Enable specific NIPs
#define NOSTR_NIP04_ENABLED
#define NOSTR_NIP44_ENABLED
#define NOSTR_NIP13_ENABLED
```
### Build Flags
```bash
# Enable websocket and PoW debug emission (now callback-based)
make LOGGING_FLAGS="-DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING"
# Debug build
make debug
# ARM64 cross-compile
make arm64
```
### Logging Integration (Consumer-Controlled)
`nostr_core_lib` now supports a callback logging API so host applications can route library logs into their own logger and destination.
- API is exposed via [`nostr_core/nostr_log.h`](nostr_core/nostr_log.h)
- Included automatically from [`nostr_core/nostr_core.h`](nostr_core/nostr_core.h)
```c
#include "nostr_core/nostr_core.h"
static void my_log_cb(int level, const char* component, const char* message, void* user_data) {
(void)user_data;
fprintf(stderr, "[nostr][%s][%d] %s\n", component ? component : "unknown", level, message ? message : "");
}
int main(void) {
if (nostr_init() != NOSTR_SUCCESS) return 1;
nostr_set_log_callback(my_log_cb, NULL);
nostr_set_log_level(NOSTR_LOG_LEVEL_TRACE);
/* ... your code ... */
nostr_cleanup();
return 0;
}
```
#### Migration Notes
- Direct file logging to `debug.log` has been removed from websocket and NIP-13 internals.
- To receive logs, register a callback with [`nostr_set_log_callback()`](nostr_core/nostr_log.h:24).
- Use [`nostr_set_log_level()`](nostr_core/nostr_log.h:25) to reduce verbosity in production.
## 🌐 Supported Platforms
- **Linux** (x86_64, ARM64)
- **macOS** (Intel, Apple Silicon)
- **Windows** (MinGW, MSYS2)
- **Embedded Systems** (resource-constrained environments)
## 📄 Documentation
- **[POOL_API.md](POOL_API.md)** - Relay pool API notes
- **[nostr_websocket/README.md](nostr_websocket/README.md)** - WebSocket module details
- **[nostr_websocket/EXPORT_GUIDE.md](nostr_websocket/EXPORT_GUIDE.md)** - WebSocket export instructions
- **API Reference** - Complete documentation in [`nostr_core/nostr_core.h`](nostr_core/nostr_core.h)
## 🤝 Contributing
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/amazing-feature`
3. Make your changes and add tests
4. Build tests and run key suites: `./build.sh -t && ./tests/nip46_test`
5. Commit your changes: `git commit -m 'Add amazing feature'`
6. Push to the branch: `git push origin feature/amazing-feature`
7. Open a Pull Request
## 📈 Version History
Current version: **0.5.12**
The library uses automatic semantic versioning based on Git tags. Each build increments the patch version automatically.
**Recent Developments:**
- **OpenSSL Migration**: Transitioned from mbedTLS to OpenSSL for improved compatibility
- **NIP-05 Support**: DNS-based internet identifier verification
- **NIP-11 Support**: Relay information document fetching and parsing
- **NIP-19 Support**: Bech32-encoded entities (nsec/npub)
- **Enhanced WebSocket**: OpenSSL-based TLS WebSocket communication
- **Comprehensive Testing**: Extensive test suite and error handling
**Version Timeline:**
- `v0.4.x` - Current development releases with relay pool and expanded NIP support
- `v0.2.x` - Earlier OpenSSL-based development releases
- `v0.1.x` - Initial development releases
- Focus on core protocol implementation and OpenSSL-based crypto
- Full NIP-01, NIP-04, NIP-05, NIP-06, NIP-11, NIP-13, NIP-17, NIP-19, NIP-21, NIP-42, NIP-44, NIP-46, NIP-59 support
## 🐛 Troubleshooting
### Common Issues
**Build fails with secp256k1 errors:**
```bash
# Install secp256k1 with Schnorr support
sudo apt install libsecp256k1-dev # Ubuntu/Debian
# or
sudo yum install libsecp256k1-devel # CentOS/RHEL
# or
brew install secp256k1 # macOS
# If still failing, build from source with Schnorr support:
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
./autogen.sh
./configure --enable-module-schnorrsig --enable-module-ecdh
make
sudo make install
```
**Library size:**
The library is small (~500KB) as it links against system libraries (secp256k1, OpenSSL, curl) rather than including them statically. This keeps the binary size manageable while maintaining full functionality.
**Linking errors:**
Make sure to include the math library:
```bash
gcc your_code.c ./libnostr_core_x64.a -lz -ldl -lpthread -lm -lssl -lcrypto -lcurl -lsecp256k1
```
### Getting Help
- Check the `examples/` directory for working code
- Run `./build.sh -t` to verify your environment
- Review the comprehensive API documentation in `nostr_core/nostr_core.h`
## 📜 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- **NOSTR Protocol** - The decentralized social media protocol
- **OpenSSL** - Production-grade cryptographic library and TLS implementation
- **secp256k1** - Bitcoin's elliptic curve library
- **cJSON** - Lightweight JSON parser
- **curl** - HTTP/HTTPS client library for NIP-05/NIP-11
- **NOSTR Community** - For protocol specification and feedback
---
**Built with ❤️ for the decentralized web**
*OpenSSL-based • Minimal dependencies • Work in progress*