# NOSTR Core Library

A C library for NOSTR protocol implementation. Work in progress.

[![Version](https://img.shields.io/badge/version-0.2.1-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
- [ ] [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
- [ ] [NIP-46](nips/46.md) - Nostr Connect
- [ ] [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

**Implementation Summary:** 12 of 96+ NIPs fully implemented (12.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 lib
   ```

3. **Run examples:**
   ```bash
   ./build.sh examples
   ./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.a -lm
./example
```

## 🏗️ Building

### Build Targets

```bash
./build.sh lib        # Build static library (default)
./build.sh examples   # Build examples
./build.sh test       # Run test suite
./build.sh clean      # Clean build artifacts
./build.sh install    # Install to system
```

### Manual Building

```bash
# Build static library
make

# Build examples  
make examples

# Run tests
make test-crypto

# Clean
make clean
```

### 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);
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);

// Run event loop (handles reconnection automatically)
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
- **`version_test`** - Library version information

Run all examples:
```bash
./build.sh examples
ls -la examples/
```

## 🧪 Testing

The library includes extensive tests:

```bash
# Run all tests
./build.sh test

# Individual test categories
cd tests && make test

# Interactive relay pool testing
cd tests && ./pool_test
```

**Test Categories:**
- **Core Functionality**: `simple_init_test`, `header_test`
- **Cryptography**: `chacha20_test`, `nostr_crypto_test`
- **NIP-04 Encryption**: `nip04_test`
- **NIP-05 Identifiers**: `nip05_test`
- **NIP-11 Relay Info**: `nip11_test`
- **NIP-44 Encryption**: `nip44_test`, `nip44_debug_test`
- **Key Derivation**: `nostr_test_bip32`
- **Relay Communication**: `relay_pool_test`, `sync_test`
- **HTTP/WebSocket**: `http_test`, `wss_test`
- **Proof of Work**: `test_pow_loop`
- **Interactive Pool Testing**: `pool_test` (menu-driven interface with reconnection testing)

## 🏗️ 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.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.a -lssl -lcrypto -lcurl -lsecp256k1 -lm -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 all logging
make LOGGING_FLAGS="-DENABLE_FILE_LOGGING -DENABLE_WEBSOCKET_LOGGING -DENABLE_DEBUG_LOGGING"

# Debug build
make debug

# ARM64 cross-compile
make arm64
```

## 🌐 Supported Platforms

- **Linux** (x86_64, ARM64)
- **macOS** (Intel, Apple Silicon)
- **Windows** (MinGW, MSYS2)
- **Embedded Systems** (resource-constrained environments)

## 📄 Documentation

- **[LIBRARY_USAGE.md](LIBRARY_USAGE.md)** - Detailed integration guide
- **[EXPORT_GUIDE.md](EXPORT_GUIDE.md)** - Library export instructions
- **[AUTOMATIC_VERSIONING.md](AUTOMATIC_VERSIONING.md)** - Version management
- **API Reference** - Complete documentation in `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. Run the test suite: `./build.sh 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.2.1**

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.2.x` - Current development releases with enhanced NIP support
- `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-42, NIP-44, 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.a -lm  # Note the -lm flag
```

### Getting Help

- Check the `examples/` directory for working code
- Run `./build.sh test` 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*
