This commit is contained in:
2025-08-17 14:14:52 -04:00
parent 3ebfdc06c0
commit 1da4f6751e
25 changed files with 0 additions and 4851 deletions

View File

@@ -1,249 +0,0 @@
/*
* NIP-44 Debug Test - Step-by-step comparison with nostr-tools vectors
*
* This test prints intermediate values for comparison with nostr-tools
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "../nostr_core/nostr_core.h"
static int hex_to_bytes(const char* hex, unsigned char* bytes, size_t len) {
if (strlen(hex) != len * 2) return -1;
for (size_t i = 0; i < len; i++) {
if (sscanf(hex + i * 2, "%2hhx", &bytes[i]) != 1) {
return -1;
}
}
return 0;
}
static void bytes_to_hex(const unsigned char* bytes, size_t len, char* hex) {
for (size_t i = 0; i < len; i++) {
sprintf(hex + i * 2, "%02x", bytes[i]);
}
hex[len * 2] = '\0';
}
// Test a specific vector from nostr-tools
static int test_vector_step_by_step(const char* name,
const char* sec1_hex,
const char* sec2_hex,
const char* expected_conversation_key_hex,
const char* nonce_hex,
const char* plaintext,
const char* expected_payload) {
printf("\n🔍 Testing Vector: %s\n", name);
printf("=====================================\n");
// Step 1: Parse keys
unsigned char sec1[32], sec2[32];
if (hex_to_bytes(sec1_hex, sec1, 32) != 0 || hex_to_bytes(sec2_hex, sec2, 32) != 0) {
printf("❌ Failed to parse private keys\n");
return -1;
}
printf("📝 sec1: %s\n", sec1_hex);
printf("📝 sec2: %s\n", sec2_hex);
// Step 2: Generate public keys
unsigned char pub1[32], pub2[32];
if (nostr_ec_public_key_from_private_key(sec1, pub1) != 0 ||
nostr_ec_public_key_from_private_key(sec2, pub2) != 0) {
printf("❌ Failed to derive public keys\n");
return -1;
}
char pub1_hex[65], pub2_hex[65];
bytes_to_hex(pub1, 32, pub1_hex);
bytes_to_hex(pub2, 32, pub2_hex);
printf("📝 pub1: %s\n", pub1_hex);
printf("📝 pub2: %s\n", pub2_hex);
// Step 3: Calculate ECDH shared secret (our raw implementation)
unsigned char shared_secret[32];
if (ecdh_shared_secret(sec1, pub2, shared_secret) != 0) {
printf("❌ Failed to compute ECDH shared secret\n");
return -1;
}
char shared_hex[65];
bytes_to_hex(shared_secret, 32, shared_hex);
printf("🔗 ECDH shared secret: %s\n", shared_hex);
// Step 4: Calculate conversation key using HKDF-extract
unsigned char conversation_key[32];
const char* salt_str = "nip44-v2";
if (nostr_hkdf_extract((const unsigned char*)salt_str, strlen(salt_str),
shared_secret, 32, conversation_key) != 0) {
printf("❌ Failed to derive conversation key\n");
return -1;
}
char conv_key_hex[65];
bytes_to_hex(conversation_key, 32, conv_key_hex);
printf("🗝️ Our conversation key: %s\n", conv_key_hex);
printf("🎯 Expected conv key: %s\n", expected_conversation_key_hex);
if (strcmp(conv_key_hex, expected_conversation_key_hex) == 0) {
printf("✅ Conversation key matches!\n");
} else {
printf("❌ Conversation key MISMATCH!\n");
return -1;
}
// Step 5: Parse nonce
unsigned char nonce[32];
if (hex_to_bytes(nonce_hex, nonce, 32) != 0) {
printf("❌ Failed to parse nonce\n");
return -1;
}
printf("🎲 Nonce: %s\n", nonce_hex);
// Step 6: Derive message keys using HKDF-expand
unsigned char message_keys[76]; // 32 chacha_key + 12 chacha_nonce + 32 hmac_key
if (nostr_hkdf_expand(conversation_key, 32, nonce, 32, message_keys, 76) != 0) {
printf("❌ Failed to derive message keys\n");
return -1;
}
char chacha_key_hex[65], chacha_nonce_hex[25], hmac_key_hex[65];
bytes_to_hex(message_keys, 32, chacha_key_hex);
bytes_to_hex(message_keys + 32, 12, chacha_nonce_hex);
bytes_to_hex(message_keys + 44, 32, hmac_key_hex);
printf("🔐 ChaCha key: %s\n", chacha_key_hex);
printf("🔐 ChaCha nonce: %s\n", chacha_nonce_hex);
printf("🔐 HMAC key: %s\n", hmac_key_hex);
// Step 7: Test encryption with known nonce
char our_payload[8192];
int encrypt_result = nostr_nip44_encrypt_with_nonce(sec1, pub2, plaintext, nonce, our_payload, sizeof(our_payload));
if (encrypt_result == NOSTR_SUCCESS) {
printf("🔒 Our payload: %s\n", our_payload);
printf("🎯 Expected payload: %s\n", expected_payload);
if (strcmp(our_payload, expected_payload) == 0) {
printf("✅ Payload matches perfectly!\n");
} else {
printf("❌ Payload MISMATCH!\n");
// Try to decrypt expected payload with our conversation key
printf("\n🔍 Debugging: Trying to decrypt expected payload...\n");
char decrypted[8192];
int decrypt_result = nostr_nip44_decrypt(sec2, pub1, expected_payload, decrypted, sizeof(decrypted));
if (decrypt_result == NOSTR_SUCCESS) {
printf("✅ Successfully decrypted expected payload!\n");
printf("📝 Decrypted text: \"%s\"\n", decrypted);
if (strcmp(decrypted, plaintext) == 0) {
printf("✅ Decrypted text matches original!\n");
} else {
printf("❌ Decrypted text doesn't match original!\n");
}
} else {
printf("❌ Failed to decrypt expected payload (error: %d)\n", decrypt_result);
}
}
} else {
printf("❌ Encryption failed with error: %d\n", encrypt_result);
return -1;
}
return 0;
}
int main() {
printf("🧪 NIP-44 Debug Test - Step-by-step Vector Comparison\n");
printf("======================================================\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
printf("❌ Failed to initialize NOSTR library\n");
return 1;
}
// Test the simple "a" vector
test_vector_step_by_step(
"Single char 'a'",
"0000000000000000000000000000000000000000000000000000000000000001",
"0000000000000000000000000000000000000000000000000000000000000002",
"c41c775356fd92eadc63ff5a0dc1da211b268cbea22316767095b2871ea1412d",
"0000000000000000000000000000000000000000000000000000000000000001",
"a",
"AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABee0G5VSK0/9YypIObAtDKfYEAjD35uVkHyB0F4DwrcNaCXlCWZKaArsGrY6M9wnuTMxWfp1RTN9Xga8no+kF5Vsb"
);
// Test the emoji vector
test_vector_step_by_step(
"Emoji 🍕🫃",
"0000000000000000000000000000000000000000000000000000000000000002",
"0000000000000000000000000000000000000000000000000000000000000001",
"c41c775356fd92eadc63ff5a0dc1da211b268cbea22316767095b2871ea1412d",
"f00000000000000000000000000000f00000000000000000000000000000000f",
"🍕🫃",
"AvAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAPSKSK6is9ngkX2+cSq85Th16oRTISAOfhStnixqZziKMDvB0QQzgFZdjLTPicCJaV8nDITO+QfaQ61+KbWQIOO2Yj"
);
// Test with get_message_keys test vector to verify HKDF-expand
printf("\n🔍 Testing get_message_keys vector from nostr-tools:\n");
printf("===========================================\n");
unsigned char conv_key[32];
if (hex_to_bytes("a1a3d60f3470a8612633924e91febf96dc5366ce130f658b1f0fc652c20b3b54", conv_key, 32) == 0) {
unsigned char test_nonce[32];
if (hex_to_bytes("e1e6f880560d6d149ed83dcc7e5861ee62a5ee051f7fde9975fe5d25d2a02d72", test_nonce, 32) == 0) {
unsigned char message_keys[76];
if (nostr_hkdf_expand(conv_key, 32, test_nonce, 32, message_keys, 76) == 0) {
char chacha_key_hex[65], chacha_nonce_hex[25], hmac_key_hex[65];
bytes_to_hex(message_keys, 32, chacha_key_hex);
bytes_to_hex(message_keys + 32, 12, chacha_nonce_hex);
bytes_to_hex(message_keys + 44, 32, hmac_key_hex);
printf("📝 Conv key: a1a3d60f3470a8612633924e91febf96dc5366ce130f658b1f0fc652c20b3b54\n");
printf("📝 Nonce: e1e6f880560d6d149ed83dcc7e5861ee62a5ee051f7fde9975fe5d25d2a02d72\n");
printf("🔐 Our ChaCha key: %s\n", chacha_key_hex);
printf("🎯 Expected ChaCha key: f145f3bed47cb70dbeaac07f3a3fe683e822b3715edb7c4fe310829014ce7d76\n");
printf("🔐 Our ChaCha nonce: %s\n", chacha_nonce_hex);
printf("🎯 Expected ChaCha nonce: c4ad129bb01180c0933a160c\n");
printf("🔐 Our HMAC key: %s\n", hmac_key_hex);
printf("🎯 Expected HMAC key: 027c1db445f05e2eee864a0975b0ddef5b7110583c8c192de3732571ca5838c4\n");
if (strcmp(chacha_key_hex, "f145f3bed47cb70dbeaac07f3a3fe683e822b3715edb7c4fe310829014ce7d76") == 0) {
printf("✅ ChaCha key matches!\n");
} else {
printf("❌ ChaCha key MISMATCH!\n");
}
if (strcmp(chacha_nonce_hex, "c4ad129bb01180c0933a160c") == 0) {
printf("✅ ChaCha nonce matches!\n");
} else {
printf("❌ ChaCha nonce MISMATCH!\n");
}
if (strcmp(hmac_key_hex, "027c1db445f05e2eee864a0975b0ddef5b7110583c8c192de3732571ca5838c4") == 0) {
printf("✅ HMAC key matches!\n");
} else {
printf("❌ HMAC key MISMATCH!\n");
}
} else {
printf("❌ Failed to expand message keys\n");
}
} else {
printf("❌ Failed to parse test nonce\n");
}
} else {
printf("❌ Failed to parse conversation key\n");
}
nostr_cleanup();
printf("\n🏁 Debug test completed\n");
return 0;
}

View File

@@ -1,255 +0,0 @@
/*
* NIP-44 Detailed Debug Test - Print every single intermediate step
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "../nostr_core/nostr_core.h"
static int hex_to_bytes(const char* hex, unsigned char* bytes, size_t len) {
if (strlen(hex) != len * 2) return -1;
for (size_t i = 0; i < len; i++) {
if (sscanf(hex + i * 2, "%2hhx", &bytes[i]) != 1) {
return -1;
}
}
return 0;
}
static void bytes_to_hex(const unsigned char* bytes, size_t len, char* hex) {
for (size_t i = 0; i < len; i++) {
sprintf(hex + i * 2, "%02x", bytes[i]);
}
hex[len * 2] = '\0';
}
static void print_bytes(const char* label, const unsigned char* bytes, size_t len) {
char hex[len * 2 + 1];
bytes_to_hex(bytes, len, hex);
printf("%s: %s\n", label, hex);
}
// Test NIP-44 padding calculation (replicate from our crypto.c)
static size_t calc_padded_len(size_t unpadded_len) {
if (unpadded_len <= 32) {
return 32;
}
size_t next_power = 1;
while (next_power < unpadded_len) {
next_power <<= 1;
}
size_t chunk = (next_power <= 256) ? 32 : (next_power / 8);
return chunk * ((unpadded_len - 1) / chunk + 1);
}
// Test NIP-44 padding (replicate from our crypto.c)
static unsigned char* pad_plaintext_debug(const char* plaintext, size_t* padded_len) {
size_t unpadded_len = strlen(plaintext);
if (unpadded_len > 65535) {
return NULL;
}
printf("🔍 PADDING DEBUG:\n");
printf(" unpadded_len: %zu\n", unpadded_len);
*padded_len = calc_padded_len(unpadded_len + 2); // +2 for length prefix
printf(" calculated_padded_len: %zu\n", *padded_len);
unsigned char* padded = malloc(*padded_len);
if (!padded) return NULL;
// Write length prefix (big-endian u16)
padded[0] = (unpadded_len >> 8) & 0xFF;
padded[1] = unpadded_len & 0xFF;
printf(" length_prefix: %02x%02x (big-endian u16 = %zu)\n", padded[0], padded[1], unpadded_len);
// Copy plaintext (if any)
if (unpadded_len > 0) {
memcpy(padded + 2, plaintext, unpadded_len);
}
// Zero-fill padding
memset(padded + 2 + unpadded_len, 0, *padded_len - 2 - unpadded_len);
print_bytes(" padded_plaintext", padded, *padded_len);
return padded;
}
int main() {
printf("🧪 NIP-44 DETAILED DEBUG TEST\n");
printf("===============================\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
printf("❌ Failed to initialize NOSTR library\n");
return 1;
}
printf("=== TESTING: Single char 'a' ===\n");
// Step 1: Parse private keys
unsigned char sec1[32], sec2[32];
hex_to_bytes("0000000000000000000000000000000000000000000000000000000000000001", sec1, 32);
hex_to_bytes("0000000000000000000000000000000000000000000000000000000000000002", sec2, 32);
print_bytes("sec1", sec1, 32);
print_bytes("sec2", sec2, 32);
// Step 2: Generate public keys
unsigned char pub1[32], pub2[32];
nostr_ec_public_key_from_private_key(sec1, pub1);
nostr_ec_public_key_from_private_key(sec2, pub2);
print_bytes("pub1", pub1, 32);
print_bytes("pub2", pub2, 32);
// Step 3: ECDH shared secret
unsigned char shared_secret[32];
ecdh_shared_secret(sec1, pub2, shared_secret);
print_bytes("ecdh_shared_secret", shared_secret, 32);
// Step 4: HKDF Extract (conversation key)
unsigned char conversation_key[32];
const char* salt_str = "nip44-v2";
nostr_hkdf_extract((const unsigned char*)salt_str, strlen(salt_str), shared_secret, 32, conversation_key);
print_bytes("conversation_key", conversation_key, 32);
// Step 5: Parse nonce
unsigned char nonce[32];
hex_to_bytes("0000000000000000000000000000000000000000000000000000000000000001", nonce, 32);
print_bytes("nonce", nonce, 32);
// Step 6: HKDF Expand (message keys)
unsigned char message_keys[76];
nostr_hkdf_expand(conversation_key, 32, nonce, 32, message_keys, 76);
print_bytes("chacha_key", message_keys, 32);
print_bytes("chacha_nonce", message_keys + 32, 12);
print_bytes("hmac_key", message_keys + 44, 32);
// Step 7: Pad plaintext
const char* plaintext = "a";
printf("\n🔍 PLAINTEXT: \"%s\" (length: %zu)\n", plaintext, strlen(plaintext));
size_t padded_len;
unsigned char* padded_plaintext = pad_plaintext_debug(plaintext, &padded_len);
if (!padded_plaintext) {
printf("❌ Failed to pad plaintext\n");
return 1;
}
// Step 8: ChaCha20 encrypt
printf("\n🔍 CHACHA20 ENCRYPTION:\n");
unsigned char* ciphertext = malloc(padded_len);
if (!ciphertext) {
printf("❌ Failed to allocate ciphertext buffer\n");
free(padded_plaintext);
return 1;
}
// Use our ChaCha20 function
if (chacha20_encrypt(message_keys, 0, message_keys + 32, padded_plaintext, ciphertext, padded_len) != 0) {
printf("❌ ChaCha20 encryption failed\n");
free(padded_plaintext);
free(ciphertext);
return 1;
}
print_bytes(" ciphertext", ciphertext, padded_len);
// Step 9: HMAC with AAD
printf("\n🔍 HMAC CALCULATION:\n");
unsigned char* aad_data = malloc(32 + padded_len);
if (!aad_data) {
printf("❌ Failed to allocate AAD buffer\n");
free(padded_plaintext);
free(ciphertext);
return 1;
}
memcpy(aad_data, nonce, 32);
memcpy(aad_data + 32, ciphertext, padded_len);
print_bytes(" aad_data", aad_data, 32 + padded_len);
unsigned char mac[32];
nostr_hmac_sha256(message_keys + 44, 32, aad_data, 32 + padded_len, mac);
print_bytes(" mac", mac, 32);
// Step 10: Construct final payload
printf("\n🔍 PAYLOAD CONSTRUCTION:\n");
size_t payload_len = 1 + 32 + padded_len + 32;
unsigned char* payload = malloc(payload_len);
if (!payload) {
printf("❌ Failed to allocate payload buffer\n");
free(padded_plaintext);
free(ciphertext);
free(aad_data);
return 1;
}
payload[0] = 0x02; // NIP-44 version 2
memcpy(payload + 1, nonce, 32);
memcpy(payload + 33, ciphertext, padded_len);
memcpy(payload + 33 + padded_len, mac, 32);
printf(" version: 0x%02x\n", payload[0]);
print_bytes(" payload_nonce", payload + 1, 32);
print_bytes(" payload_ciphertext", payload + 33, padded_len);
print_bytes(" payload_mac", payload + 33 + padded_len, 32);
print_bytes(" raw_payload", payload, payload_len);
// Step 11: Base64 encode
printf("\n🔍 BASE64 ENCODING:\n");
size_t b64_len = ((payload_len + 2) / 3) * 4 + 1;
char* base64_output = malloc(b64_len);
if (!base64_output) {
printf("❌ Failed to allocate base64 buffer\n");
free(padded_plaintext);
free(ciphertext);
free(aad_data);
free(payload);
return 1;
}
// Use our internal base64_encode function from crypto.c
extern size_t base64_encode(const unsigned char* data, size_t len, char* output, size_t output_size);
size_t actual_b64_len = base64_encode(payload, payload_len, base64_output, b64_len);
printf(" payload_length: %zu\n", payload_len);
printf(" base64_length: %zu\n", actual_b64_len);
printf(" our_base64: %s\n", base64_output);
printf(" expected: AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABee0G5VSK0/9YypIObAtDKfYEAjD35uVkHyB0F4DwrcNaCXlCWZKaArsGrY6M9wnuTMxWfp1RTN9Xga8no+kF5Vsb\n");
if (strcmp(base64_output, "AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABee0G5VSK0/9YypIObAtDKfYEAjD35uVkHyB0F4DwrcNaCXlCWZKaArsGrY6M9wnuTMxWfp1RTN9Xga8no+kF5Vsb") == 0) {
printf("✅ PERFECT MATCH!\n");
} else {
printf("❌ MISMATCH - need to investigate!\n");
// Let's also try our full encrypt function for comparison
printf("\n🔍 FULL ENCRYPT FUNCTION TEST:\n");
char full_encrypt_output[8192];
int result = nostr_nip44_encrypt_with_nonce(sec1, pub2, plaintext, nonce, full_encrypt_output, sizeof(full_encrypt_output));
if (result == NOSTR_SUCCESS) {
printf(" full_encrypt: %s\n", full_encrypt_output);
} else {
printf(" full_encrypt failed with error: %d\n", result);
}
}
// Cleanup
free(padded_plaintext);
free(ciphertext);
free(aad_data);
free(payload);
free(base64_output);
nostr_cleanup();
printf("\n🏁 Detailed debug test completed\n");
return 0;
}

View File

@@ -1,118 +0,0 @@
/*
* Simple NIP-44 Test
* Basic functionality test for NIP-44 encryption/decryption
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "../nostr_core/nostr_core.h"
int main() {
printf("🧪 Simple NIP-44 Test\n");
printf("=====================\n\n");
// Initialize the library
if (nostr_init() != NOSTR_SUCCESS) {
printf("❌ Failed to initialize NOSTR library\n");
return 1;
}
// Test keys (from successful NIP-04 test)
const char* sender_key_hex = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe";
const char* recipient_key_hex = "96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220";
unsigned char sender_private_key[32];
unsigned char recipient_private_key[32];
unsigned char recipient_public_key[32];
// Parse keys
if (nostr_hex_to_bytes(sender_key_hex, sender_private_key, 32) != 0) {
printf("❌ Failed to parse sender private key\n");
nostr_cleanup();
return 1;
}
if (nostr_hex_to_bytes(recipient_key_hex, recipient_private_key, 32) != 0) {
printf("❌ Failed to parse recipient private key\n");
nostr_cleanup();
return 1;
}
// Generate recipient's public key
if (nostr_ec_public_key_from_private_key(recipient_private_key, recipient_public_key) != 0) {
printf("❌ Failed to generate recipient public key\n");
nostr_cleanup();
return 1;
}
printf("✅ Keys parsed successfully\n");
// Test message
const char* test_message = "Hello, NIP-44! This is a test message.";
printf("📝 Test message: \"%s\"\n", test_message);
// Test encryption
char encrypted[8192];
printf("🔐 Testing NIP-44 encryption...\n");
int encrypt_result = nostr_nip44_encrypt(
sender_private_key,
recipient_public_key,
test_message,
encrypted,
sizeof(encrypted)
);
if (encrypt_result != NOSTR_SUCCESS) {
printf("❌ NIP-44 encryption failed with error: %d\n", encrypt_result);
nostr_cleanup();
return 1;
}
printf("✅ NIP-44 encryption successful!\n");
printf("📦 Encrypted length: %zu bytes\n", strlen(encrypted));
printf("📦 First 80 chars: %.80s...\n", encrypted);
// Test decryption
char decrypted[8192];
unsigned char sender_public_key[32];
// Generate sender's public key for decryption
if (nostr_ec_public_key_from_private_key(sender_private_key, sender_public_key) != 0) {
printf("❌ Failed to generate sender public key\n");
nostr_cleanup();
return 1;
}
printf("🔓 Testing NIP-44 decryption...\n");
int decrypt_result = nostr_nip44_decrypt(
recipient_private_key,
sender_public_key,
encrypted,
decrypted,
sizeof(decrypted)
);
if (decrypt_result != NOSTR_SUCCESS) {
printf("❌ NIP-44 decryption failed with error: %d\n", decrypt_result);
nostr_cleanup();
return 1;
}
printf("✅ NIP-44 decryption successful!\n");
printf("📝 Decrypted: \"%s\"\n", decrypted);
// Verify round-trip
if (strcmp(test_message, decrypted) == 0) {
printf("✅ Round-trip successful! Messages match perfectly.\n");
printf("\n🎉 NIP-44 TEST PASSED! 🎉\n");
nostr_cleanup();
return 0;
} else {
printf("❌ Round-trip failed! Messages don't match.\n");
printf("📝 Original: \"%s\"\n", test_message);
printf("📝 Decrypted: \"%s\"\n", decrypted);
nostr_cleanup();
return 1;
}
}