remove exposed .h crypto headers

This commit is contained in:
2025-09-02 12:36:52 -04:00
parent c0d095e57b
commit 33129d82fd
22 changed files with 562 additions and 883 deletions

View File

@@ -1,15 +1,76 @@
/*
* NOSTR AES Implementation
*
*
* Based on tiny-AES-c by kokke (public domain)
* Configured specifically for NIP-04: AES-256-CBC only
*
*
* This is an implementation of the AES algorithm, specifically CBC mode.
* Configured for AES-256 as required by NIP-04.
*/
#include <stdint.h>
#include <stddef.h>
#include <string.h> // CBC mode, for memset
#include "nostr_aes.h"
// Configure for NIP-04 requirements: AES-256-CBC only
#define CBC 1
#define ECB 0
#define CTR 0
// Configure for AES-256 (required by NIP-04)
#define AES128 0
#define AES192 0
#define AES256 1
#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif
struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};
// state - array holding the intermediate results during decryption.
typedef uint8_t state_t[4][4];
// Function prototypes (internal use only)
static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key);
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey);
static void SubBytes(state_t* state);
static void ShiftRows(state_t* state);
static uint8_t xtime(uint8_t x);
static void MixColumns(state_t* state);
static void InvMixColumns(state_t* state);
static void InvSubBytes(state_t* state);
static void InvShiftRows(state_t* state);
static void Cipher(state_t* state, const uint8_t* RoundKey);
static void InvCipher(state_t* state, const uint8_t* RoundKey);
static void XorWithIv(uint8_t* buf, const uint8_t* Iv);
// Public functions (used by NIP-04 implementation)
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(CBC) && (CBC == 1)
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
#endif
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4

View File

@@ -1,53 +0,0 @@
#ifndef _NOSTR_AES_H_
#define _NOSTR_AES_H_
#include <stdint.h>
#include <stddef.h>
// Configure for NIP-04 requirements: AES-256-CBC only
#define CBC 1
#define ECB 0
#define CTR 0
// Configure for AES-256 (required by NIP-04)
#define AES128 0
#define AES192 0
#define AES256 1
#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif
struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(CBC) && (CBC == 1)
// buffer size MUST be multiple of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
#endif // #if defined(CBC) && (CBC == 1)
#endif // _NOSTR_AES_H_

View File

@@ -1,15 +1,47 @@
/*
* nostr_chacha20.c - ChaCha20 stream cipher implementation
*
*
* Implementation based on RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols"
*
*
* This implementation is adapted from the RFC 8439 reference specification.
* It prioritizes correctness and clarity over performance optimization.
*/
#include "nostr_chacha20.h"
#include <stdint.h>
#include <stddef.h>
#include <string.h>
/*
* ============================================================================
* CONSTANTS AND DEFINITIONS
* ============================================================================
*/
#define CHACHA20_KEY_SIZE 32 /* 256 bits */
#define CHACHA20_NONCE_SIZE 12 /* 96 bits */
#define CHACHA20_BLOCK_SIZE 64 /* 512 bits */
/*
* ============================================================================
* FUNCTION PROTOTYPES (INTERNAL USE ONLY)
* ============================================================================
*/
// Internal utility functions
static uint32_t bytes_to_u32_le(const uint8_t *bytes);
static void u32_to_bytes_le(uint32_t val, uint8_t *bytes);
// Public functions (used by NIP-44 implementation)
void chacha20_quarter_round(uint32_t state[16], int a, int b, int c, int d);
int chacha20_block(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], uint8_t output[64]);
int chacha20_encrypt(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], const uint8_t* input,
uint8_t* output, size_t length);
void chacha20_init_state(uint32_t state[16], const uint8_t key[32],
uint32_t counter, const uint8_t nonce[12]);
void chacha20_serialize_state(const uint32_t state[16], uint8_t output[64]);
/*
* ============================================================================
* UTILITY MACROS AND FUNCTIONS

View File

@@ -1,115 +0,0 @@
/*
* nostr_chacha20.h - ChaCha20 stream cipher implementation
*
* Implementation based on RFC 8439 "ChaCha20 and Poly1305 for IETF Protocols"
*
* This is a small, portable implementation for NIP-44 support in the NOSTR library.
* The implementation prioritizes correctness and simplicity over performance.
*/
#ifndef NOSTR_CHACHA20_H
#define NOSTR_CHACHA20_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* ============================================================================
* CONSTANTS AND DEFINITIONS
* ============================================================================
*/
#define CHACHA20_KEY_SIZE 32 /* 256 bits */
#define CHACHA20_NONCE_SIZE 12 /* 96 bits */
#define CHACHA20_BLOCK_SIZE 64 /* 512 bits */
/*
* ============================================================================
* CORE CHACHA20 FUNCTIONS
* ============================================================================
*/
/**
* ChaCha20 quarter round operation
*
* Operates on four 32-bit words performing the core ChaCha20 quarter round:
* a += b; d ^= a; d <<<= 16;
* c += d; b ^= c; b <<<= 12;
* a += b; d ^= a; d <<<= 8;
* c += d; b ^= c; b <<<= 7;
*
* @param state[in,out] ChaCha state as 16 32-bit words
* @param a, b, c, d Indices into state array for quarter round
*/
void chacha20_quarter_round(uint32_t state[16], int a, int b, int c, int d);
/**
* ChaCha20 block function
*
* Transforms a 64-byte input block using ChaCha20 algorithm with 20 rounds.
*
* @param key[in] 32-byte key
* @param counter[in] 32-bit block counter
* @param nonce[in] 12-byte nonce
* @param output[out] 64-byte output buffer
* @return 0 on success, negative on error
*/
int chacha20_block(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], uint8_t output[64]);
/**
* ChaCha20 encryption/decryption
*
* Encrypts or decrypts data using ChaCha20 stream cipher.
* Since ChaCha20 is a stream cipher, encryption and decryption are the same operation.
*
* @param key[in] 32-byte key
* @param counter[in] Initial 32-bit counter value
* @param nonce[in] 12-byte nonce
* @param input[in] Input data to encrypt/decrypt
* @param output[out] Output buffer (can be same as input)
* @param length[in] Length of input data in bytes
* @return 0 on success, negative on error
*/
int chacha20_encrypt(const uint8_t key[32], uint32_t counter,
const uint8_t nonce[12], const uint8_t* input,
uint8_t* output, size_t length);
/*
* ============================================================================
* UTILITY FUNCTIONS
* ============================================================================
*/
/**
* Initialize ChaCha20 state matrix
*
* Sets up the initial 16-word state matrix with constants, key, counter, and nonce.
*
* @param state[out] 16-word state array to initialize
* @param key[in] 32-byte key
* @param counter[in] 32-bit block counter
* @param nonce[in] 12-byte nonce
*/
void chacha20_init_state(uint32_t state[16], const uint8_t key[32],
uint32_t counter, const uint8_t nonce[12]);
/**
* Serialize ChaCha20 state to bytes
*
* Converts 16 32-bit words to 64 bytes in little-endian format.
*
* @param state[in] 16-word state array
* @param output[out] 64-byte output buffer
*/
void chacha20_serialize_state(const uint32_t state[16], uint8_t output[64]);
#ifdef __cplusplus
}
#endif
#endif /* NOSTR_CHACHA20_H */

View File

@@ -1,4 +1,3 @@
#include "nostr_secp256k1.h"
#include <secp256k1.h>
#include <secp256k1_schnorrsig.h>
#include <secp256k1_ecdh.h>
@@ -6,6 +5,33 @@
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stddef.h>
/*
* PRIVATE INTERNAL FUNCTIONS - NOT EXPORTED
* These functions are for internal library use only.
*/
/** Opaque data structure that holds a parsed and valid public key.
* Guaranteed to be 64 bytes in size, and can be safely copied/moved.
*/
typedef struct nostr_secp256k1_pubkey {
unsigned char data[64];
} nostr_secp256k1_pubkey;
/** Opaque data structure that holds a parsed keypair.
* Guaranteed to be 96 bytes in size, and can be safely copied/moved.
*/
typedef struct nostr_secp256k1_keypair {
unsigned char data[96];
} nostr_secp256k1_keypair;
/** Opaque data structure that holds a parsed x-only public key.
* Guaranteed to be 64 bytes in size, and can be safely copied/moved.
*/
typedef struct nostr_secp256k1_xonly_pubkey {
unsigned char data[64];
} nostr_secp256k1_xonly_pubkey;
// Global context for secp256k1 operations
static secp256k1_context* g_ctx = NULL;

View File

@@ -1,141 +0,0 @@
#ifndef NOSTR_SECP256K1_H
#define NOSTR_SECP256K1_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
/** Opaque data structure that holds a parsed and valid public key.
* Guaranteed to be 64 bytes in size, and can be safely copied/moved.
*/
typedef struct nostr_secp256k1_pubkey {
unsigned char data[64];
} nostr_secp256k1_pubkey;
/** Opaque data structure that holds a parsed keypair.
* Guaranteed to be 96 bytes in size, and can be safely copied/moved.
*/
typedef struct nostr_secp256k1_keypair {
unsigned char data[96];
} nostr_secp256k1_keypair;
/** Opaque data structure that holds a parsed x-only public key.
* Guaranteed to be 64 bytes in size, and can be safely copied/moved.
*/
typedef struct nostr_secp256k1_xonly_pubkey {
unsigned char data[64];
} nostr_secp256k1_xonly_pubkey;
/** Initialize the secp256k1 library. Must be called before any other functions.
* Returns: 1 on success, 0 on failure.
*/
int nostr_secp256k1_context_create(void);
/** Clean up the secp256k1 library resources.
*/
void nostr_secp256k1_context_destroy(void);
/** Verify an elliptic curve secret key.
* Returns: 1: secret key is valid, 0: secret key is invalid
* In: seckey: pointer to a 32-byte secret key.
*/
int nostr_secp256k1_ec_seckey_verify(const unsigned char *seckey);
/** Compute the public key for a secret key.
* Returns: 1: secret was valid, public key stored. 0: secret was invalid.
* Out: pubkey: pointer to the created public key.
* In: seckey: pointer to a 32-byte secret key.
*/
int nostr_secp256k1_ec_pubkey_create(nostr_secp256k1_pubkey *pubkey, const unsigned char *seckey);
/** Create a keypair from a secret key.
* Returns: 1: keypair created, 0: secret key invalid.
* Out: keypair: pointer to the created keypair.
* In: seckey: pointer to a 32-byte secret key.
*/
int nostr_secp256k1_keypair_create(nostr_secp256k1_keypair *keypair, const unsigned char *seckey);
/** Get the x-only public key from a keypair.
* Returns: 1 always.
* Out: pubkey: pointer to storage for the x-only public key.
* In: keypair: pointer to a keypair.
*/
int nostr_secp256k1_keypair_xonly_pub(nostr_secp256k1_xonly_pubkey *pubkey, const nostr_secp256k1_keypair *keypair);
/** Parse an x-only public key from bytes.
* Returns: 1: public key parsed, 0: invalid public key.
* Out: pubkey: pointer to the created x-only public key.
* In: input32: pointer to a 32-byte x-only public key.
*/
int nostr_secp256k1_xonly_pubkey_parse(nostr_secp256k1_xonly_pubkey *pubkey, const unsigned char *input32);
/** Serialize an x-only public key to bytes.
* Returns: 1 always.
* Out: output32: pointer to a 32-byte array to store the serialized key.
* In: pubkey: pointer to an x-only public key.
*/
int nostr_secp256k1_xonly_pubkey_serialize(unsigned char *output32, const nostr_secp256k1_xonly_pubkey *pubkey);
/** Create a Schnorr signature.
* Returns: 1: signature created, 0: nonce generation failed or secret key invalid.
* Out: sig64: pointer to a 64-byte array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* keypair: pointer to an initialized keypair.
* aux_rand32: pointer to 32 bytes of auxiliary randomness (can be NULL).
*/
int nostr_secp256k1_schnorrsig_sign32(unsigned char *sig64, const unsigned char *msghash32, const nostr_secp256k1_keypair *keypair, const unsigned char *aux_rand32);
/** Verify a Schnorr signature.
* Returns: 1: correct signature, 0: incorrect signature
* In: sig64: pointer to the 64-byte signature being verified.
* msghash32: the 32-byte message hash being verified.
* pubkey: pointer to an x-only public key to verify with.
*/
int nostr_secp256k1_schnorrsig_verify(const unsigned char *sig64, const unsigned char *msghash32, const nostr_secp256k1_xonly_pubkey *pubkey);
/** Serialize a pubkey object into a serialized byte sequence.
* Returns: 1 always.
* Out: output: pointer to a 33-byte array to place the serialized key in.
* In: pubkey: pointer to a secp256k1_pubkey containing an initialized public key.
*
* The output will be a 33-byte compressed public key (0x02 or 0x03 prefix + 32 bytes x coordinate).
*/
int nostr_secp256k1_ec_pubkey_serialize_compressed(unsigned char *output, const nostr_secp256k1_pubkey *pubkey);
/** Tweak a secret key by adding a 32-byte tweak to it.
* Returns: 1: seckey was valid, 0: seckey invalid or resulting key invalid
* In/Out: seckey: pointer to a 32-byte secret key. Will be modified in-place.
* In: tweak: pointer to a 32-byte tweak.
*/
int nostr_secp256k1_ec_seckey_tweak_add(unsigned char *seckey, const unsigned char *tweak);
/** Parse a variable-length public key into the pubkey object.
* Returns: 1: public key parsed, 0: invalid public key.
* Out: pubkey: pointer to the created public key.
* In: input: pointer to a serialized public key
* inputlen: length of the array pointed to by input
*/
int nostr_secp256k1_ec_pubkey_parse(nostr_secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen);
/** Compute an EC Diffie-Hellman secret in constant time.
* Returns: 1: exponentiation was successful, 0: scalar was invalid (zero or overflow)
* Out: result: a 32-byte array which will be populated by an ECDH secret computed from point and scalar
* In: pubkey: a pointer to a secp256k1_pubkey containing an initialized public key
* seckey: a 32-byte scalar with which to multiply the point
*/
int nostr_secp256k1_ecdh(unsigned char *result, const nostr_secp256k1_pubkey *pubkey, const unsigned char *seckey, void *hashfp, void *data);
/** Generate cryptographically secure random bytes.
* Returns: 1: success, 0: failure
* Out: buf: buffer to fill with random bytes
* In: len: number of bytes to generate
*/
int nostr_secp256k1_get_random_bytes(unsigned char *buf, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* NOSTR_SECP256K1_H */

View File

@@ -6,7 +6,6 @@
#include "nip001.h"
#include "utils.h"
#include "crypto/nostr_secp256k1.h"
#include "../cjson/cJSON.h"
#include <stdio.h>
#include <stdlib.h>
@@ -14,9 +13,21 @@
#include <time.h>
#include "../nostr_core/nostr_common.h"
// Forward declarations for crypto functions (private API)
// These functions are implemented in crypto/ but not exposed through public headers
typedef struct {
unsigned char data[64];
} nostr_secp256k1_xonly_pubkey;
int nostr_secp256k1_xonly_pubkey_parse(nostr_secp256k1_xonly_pubkey* pubkey, const unsigned char* input32);
int nostr_secp256k1_schnorrsig_verify(const unsigned char* sig64, const unsigned char* msg32, const nostr_secp256k1_xonly_pubkey* pubkey);
// Declare utility functions
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_sha256(const unsigned char* data, size_t len, unsigned char* hash);
int nostr_ec_public_key_from_private_key(const unsigned char* private_key, unsigned char* public_key);
int nostr_ec_sign(const unsigned char* private_key, const unsigned char* hash, unsigned char* signature);
/**
* Create and sign a NOSTR event

View File

@@ -6,13 +6,24 @@
#include "nip004.h"
#include "utils.h"
#include "nostr_common.h"
#include "crypto/nostr_secp256k1.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Include our AES implementation
#include "crypto/nostr_aes.h"
// Forward declarations for crypto functions (private API)
// These functions are implemented in crypto/ but not exposed through public headers
int ecdh_shared_secret(const unsigned char* private_key, const unsigned char* public_key, unsigned char* shared_secret);
int nostr_secp256k1_get_random_bytes(unsigned char* buf, size_t len);
// AES context and functions for NIP-04 encryption
struct AES_ctx {
unsigned char RoundKey[240]; // AES-256 key expansion
unsigned char Iv[16]; // Initialization vector
};
void AES_init_ctx_iv(struct AES_ctx* ctx, const unsigned char* key, const unsigned char* iv);
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, unsigned char* buf, size_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, unsigned char* buf, size_t length);
// Forward declarations for internal functions
static int aes_cbc_encrypt(const unsigned char* key, const unsigned char* iv,

View File

@@ -9,10 +9,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./crypto/nostr_secp256k1.h"
// Include our ChaCha20 implementation
#include "crypto/nostr_chacha20.h"
// Forward declarations for crypto functions (private API)
// These functions are implemented in crypto/ but not exposed through public headers
int ecdh_shared_secret(const unsigned char* private_key, const unsigned char* public_key, unsigned char* shared_secret);
int nostr_secp256k1_get_random_bytes(unsigned char* buf, size_t len);
// ChaCha20 functions for NIP-44 encryption
int chacha20_encrypt(const unsigned char key[32], unsigned int counter,
const unsigned char nonce[12], const unsigned char* input,
unsigned char* output, size_t length);
// HKDF functions for NIP-44 key derivation
int nostr_hkdf_extract(const unsigned char* salt, size_t salt_len,
const unsigned char* ikm, size_t ikm_len,
unsigned char* prk);
int nostr_hkdf_expand(const unsigned char* prk, size_t prk_len,
const unsigned char* info, size_t info_len,
unsigned char* okm, size_t okm_len);
// HMAC-SHA256 function for NIP-44 authentication
int nostr_hmac_sha256(const unsigned char* key, size_t key_len,
const unsigned char* data, size_t data_len,
unsigned char* hmac);
// Forward declarations for internal functions
static size_t calc_padded_len(size_t unpadded_len);

View File

@@ -1,11 +1,103 @@
#ifndef NOSTR_CORE_H
#define NOSTR_CORE_H
/**
* NOSTR Core Library - Unified Header File
/*
* NOSTR Core Library - Complete API Reference
*
* This file provides a single include point for all NOSTR Core functionality.
* Include this file to access all available NIPs and core functions.
* This header includes ALL library functionality. For modular includes,
* use individual headers instead.
*
* ============================================================================
* QUICK FUNCTION REFERENCE - Find what you need fast!
* ============================================================================
*
* EVENT OPERATIONS (NIP-01):
* - nostr_create_and_sign_event() -> Create and sign new Nostr events
* - nostr_validate_event() -> Validate complete Nostr event
* - nostr_validate_event_structure() -> Check event structure only
* - nostr_verify_event_signature() -> Verify cryptographic signature
*
* CRYPTOGRAPHIC HASHING:
* - nostr_sha256() -> Single-call SHA-256 hash
* - nostr_sha256_init() -> Initialize streaming SHA-256 context
* - nostr_sha256_update() -> Process data chunks incrementally
* - nostr_sha256_final() -> Finalize hash and clear context
* - nostr_sha256_file_stream() -> Hash large files efficiently (NEW!)
* - nostr_sha512() -> SHA-512 hash function
* - nostr_hmac_sha256() -> HMAC with SHA-256
* - nostr_hmac_sha512() -> HMAC with SHA-512
*
* DIGITAL SIGNATURES & KEYS:
* - nostr_schnorr_sign() -> Create Schnorr signatures
* - nostr_ec_public_key_from_private_key() -> Generate public keys
* - nostr_ec_private_key_verify() -> Validate private key format
* - nostr_ec_sign() -> ECDSA signature creation
* - nostr_rfc6979_generate_k() -> Deterministic nonce generation
*
* NIP-04 ENCRYPTION (Legacy):
* - nostr_nip04_encrypt() -> Encrypt messages (AES-256-CBC)
* - nostr_nip04_decrypt() -> Decrypt messages (AES-256-CBC)
*
* NIP-44 ENCRYPTION (Modern - Recommended):
* - nostr_nip44_encrypt() -> Encrypt with ChaCha20 + HMAC
* - nostr_nip44_encrypt_with_nonce() -> Encrypt with specific nonce (testing)
* - nostr_nip44_decrypt() -> Decrypt ChaCha20 + HMAC messages
*
* BIP39 MNEMONICS:
* - nostr_bip39_mnemonic_from_bytes() -> Generate mnemonic from entropy
* - nostr_bip39_mnemonic_validate() -> Validate mnemonic phrase
* - nostr_bip39_mnemonic_to_seed() -> Convert mnemonic to seed
*
* BIP32 HD WALLETS:
* - nostr_bip32_key_from_seed() -> Create master key from seed
* - nostr_bip32_derive_child() -> Derive child key from parent
* - nostr_bip32_derive_path() -> Derive keys from derivation path
*
* KEY DERIVATION:
* - nostr_hkdf() -> HKDF key derivation (full)
* - nostr_hkdf_extract() -> HKDF extract step only
* - nostr_hkdf_expand() -> HKDF expand step only
* - nostr_pbkdf2_hmac_sha512() -> PBKDF2 with HMAC-SHA512
* - ecdh_shared_secret() -> ECDH shared secret computation
*
* UTILITIES & ENCODING:
* - nostr_bytes_to_hex() -> Convert bytes to hex string
* - nostr_hex_to_bytes() -> Convert hex string to bytes
* - base64_encode() -> Base64 encoding
* - base64_decode() -> Base64 decoding
*
* SYSTEM FUNCTIONS:
* - nostr_crypto_init() -> Initialize crypto subsystem
* - nostr_crypto_cleanup() -> Cleanup crypto subsystem
*
* ============================================================================
* USAGE EXAMPLES:
* ============================================================================
*
* Basic Event Creation:
* cJSON* event = nostr_create_and_sign_event(1, "Hello Nostr!", NULL, private_key, time(NULL));
* if (nostr_validate_event(event) == NOSTR_SUCCESS) { ... }
*
* Streaming SHA-256 (for large files):
* nostr_sha256_ctx_t ctx;
* nostr_sha256_init(&ctx);
* // Process data in chunks...
* nostr_sha256_update(&ctx, data, data_size);
* nostr_sha256_final(&ctx, hash_output);
*
* File Hashing:
* unsigned char file_hash[32];
* nostr_sha256_file_stream("large_video.mp4", file_hash);
*
* Modern Encryption (NIP-44):
* nostr_nip44_encrypt(sender_key, recipient_pubkey, "secret message", output, sizeof(output));
*
* HD Wallet Derivation:
* nostr_bip32_key_from_seed(seed, 64, &master_key);
* uint32_t path[] = {44, 1237, 0, 0, 0}; // m/44'/1237'/0'/0/0
* nostr_bip32_derive_path(&master_key, path, 5, &derived_key);
*
* ============================================================================
*/
#ifdef __cplusplus

View File

@@ -9,14 +9,28 @@
#include <stdlib.h>
#include <string.h>
// Include our secp256k1 wrapper for elliptic curve operations
#include "crypto/nostr_secp256k1.h"
// Forward declarations for crypto functions (private API)
// These functions are implemented in crypto/ but not exposed through public headers
// Include our self-contained AES implementation for NIP-04
#include "crypto/nostr_aes.h"
// secp256k1 functions
typedef struct {
unsigned char data[64];
} nostr_secp256k1_pubkey;
// Include our ChaCha20 implementation for NIP-44
#include "crypto/nostr_chacha20.h"
typedef struct {
unsigned char data[96];
} nostr_secp256k1_keypair;
int nostr_secp256k1_context_create(void);
void nostr_secp256k1_context_destroy(void);
int nostr_secp256k1_ec_pubkey_parse(nostr_secp256k1_pubkey* pubkey, const unsigned char* input, size_t inputlen);
int nostr_secp256k1_ecdh(unsigned char* output, const nostr_secp256k1_pubkey* pubkey, const unsigned char* privkey, void* hashfp, void* data);
int nostr_secp256k1_ec_seckey_verify(const unsigned char* seckey);
int nostr_secp256k1_ec_pubkey_create(nostr_secp256k1_pubkey* pubkey, const unsigned char* privkey);
int nostr_secp256k1_ec_pubkey_serialize_compressed(unsigned char* output, const nostr_secp256k1_pubkey* pubkey);
int nostr_secp256k1_keypair_create(nostr_secp256k1_keypair* keypair, const unsigned char* privkey);
int nostr_secp256k1_schnorrsig_sign32(unsigned char* sig, const unsigned char* msg32, const nostr_secp256k1_keypair* keypair, const unsigned char* aux_rand32);
int nostr_secp256k1_ec_seckey_tweak_add(unsigned char* seckey, const unsigned char* tweak);
// =============================================================================
@@ -328,6 +342,125 @@ int nostr_sha256(const unsigned char* data, size_t len, unsigned char* hash) {
return 0;
}
// =============================================================================
// STREAMING SHA-256 IMPLEMENTATION
// =============================================================================
int nostr_sha256_init(nostr_sha256_ctx_t* ctx) {
if (!ctx) return -1;
// Initialize SHA-256 state
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
// Initialize counters and buffer
ctx->bitlen = 0;
ctx->buflen = 0;
return 0;
}
int nostr_sha256_update(nostr_sha256_ctx_t* ctx, const unsigned char* data, size_t len) {
if (!ctx || !data) return -1;
for (size_t i = 0; i < len; i++) {
ctx->buffer[ctx->buflen] = data[i];
ctx->buflen++;
// Process complete blocks
if (ctx->buflen == 64) {
sha256_transform(ctx->state, ctx->buffer);
ctx->bitlen += 512; // 64 bytes * 8 bits
ctx->buflen = 0;
}
}
return 0;
}
int nostr_sha256_final(nostr_sha256_ctx_t* ctx, unsigned char* hash) {
if (!ctx || !hash) return -1;
// Calculate final bit length
uint64_t final_bitlen = ctx->bitlen + (ctx->buflen * 8);
// Pad the message
ctx->buffer[ctx->buflen] = 0x80;
ctx->buflen++;
// If not enough space for length, pad and process another block
if (ctx->buflen > 56) {
while (ctx->buflen < 64) {
ctx->buffer[ctx->buflen] = 0x00;
ctx->buflen++;
}
sha256_transform(ctx->state, ctx->buffer);
ctx->buflen = 0;
}
// Pad with zeros up to 56 bytes
while (ctx->buflen < 56) {
ctx->buffer[ctx->buflen] = 0x00;
ctx->buflen++;
}
// Append length as big-endian 64-bit integer
for (int i = 0; i < 8; i++) {
ctx->buffer[56 + i] = (final_bitlen >> (56 - i * 8)) & 0xff;
}
// Process final block
sha256_transform(ctx->state, ctx->buffer);
// Convert state to output bytes
for (int i = 0; i < 8; i++) {
hash[i * 4] = (ctx->state[i] >> 24) & 0xff;
hash[i * 4 + 1] = (ctx->state[i] >> 16) & 0xff;
hash[i * 4 + 2] = (ctx->state[i] >> 8) & 0xff;
hash[i * 4 + 3] = ctx->state[i] & 0xff;
}
// Clear sensitive data
memory_clear(ctx, sizeof(nostr_sha256_ctx_t));
return 0;
}
int nostr_sha256_file_stream(const char* filename, unsigned char* hash) {
if (!filename || !hash) return -1;
FILE* file = fopen(filename, "rb");
if (!file) return -1;
nostr_sha256_ctx_t ctx;
if (nostr_sha256_init(&ctx) != 0) {
fclose(file);
return -1;
}
// Process file in 4KB chunks for memory efficiency
unsigned char buffer[4096];
size_t bytes_read;
while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
if (nostr_sha256_update(&ctx, buffer, bytes_read) != 0) {
fclose(file);
return -1;
}
}
fclose(file);
// Finalize and return result
return nostr_sha256_final(&ctx, hash);
}
// =============================================================================
// HMAC IMPLEMENTATION
// =============================================================================

View File

@@ -45,6 +45,30 @@ void nostr_crypto_cleanup(void);
// SHA-256 hash function
int nostr_sha256(const unsigned char *data, size_t len, unsigned char *hash);
// =============================================================================
// STREAMING SHA-256 FUNCTIONS
// =============================================================================
// SHA-256 streaming context
typedef struct {
uint32_t state[8]; // Current hash state
unsigned char buffer[64]; // Input buffer for incomplete blocks
uint64_t bitlen; // Total bits processed
size_t buflen; // Current buffer length
} nostr_sha256_ctx_t;
// Initialize SHA-256 streaming context
int nostr_sha256_init(nostr_sha256_ctx_t* ctx);
// Update SHA-256 context with new data
int nostr_sha256_update(nostr_sha256_ctx_t* ctx, const unsigned char* data, size_t len);
// Finalize SHA-256 and output hash
int nostr_sha256_final(nostr_sha256_ctx_t* ctx, unsigned char* hash);
// Stream SHA-256 hash of a file
int nostr_sha256_file_stream(const char* filename, unsigned char* hash);
// HMAC-SHA256
int nostr_hmac_sha256(const unsigned char *key, size_t key_len,
const unsigned char *data, size_t data_len,