Fixed error in nip04 implementation. Now working
This commit is contained in:
Binary file not shown.
@@ -6,32 +6,87 @@
|
||||
#include "../nostr_core/utils.h"
|
||||
|
||||
int main(void) {
|
||||
// Test vector 1 from the existing test
|
||||
printf("=== NIP-04 DEBUG COMPARISON (C) ===\n");
|
||||
|
||||
// Initialize NOSTR library - REQUIRED for secp256k1 operations
|
||||
if (nostr_init() != NOSTR_SUCCESS) {
|
||||
printf("❌ Failed to initialize NOSTR library\n");
|
||||
return 1;
|
||||
}
|
||||
printf("✓ NOSTR library initialized successfully\n");
|
||||
|
||||
// Test vectors matching JavaScript
|
||||
const char* sk1_hex = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe";
|
||||
const char* pk1_hex = "b38ce15d3d9874ee710dfabb7ff9801b1e0e20aace6e9a1a05fa7482a04387d1";
|
||||
const char* sk2_hex = "96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220";
|
||||
const char* pk2_hex = "dcb33a629560280a0ee3b6b99b68c044fe8914ad8a984001ebf6099a9b474dc3";
|
||||
const char* plaintext = "nanana";
|
||||
const char* expectedCiphertext = "d6Joav5EciPI9hdHw31vmQ==?iv=fWs5rfv2+532arG/k83kcA==";
|
||||
|
||||
// Convert hex keys to bytes using the system function
|
||||
unsigned char sk1[32], pk2[32];
|
||||
// Convert hex keys to bytes
|
||||
unsigned char sk1[32], pk1[32], sk2[32], pk2[32];
|
||||
nostr_hex_to_bytes(sk1_hex, sk1, 32);
|
||||
nostr_hex_to_bytes(pk1_hex, pk1, 32);
|
||||
nostr_hex_to_bytes(sk2_hex, sk2, 32);
|
||||
nostr_hex_to_bytes(pk2_hex, pk2, 32);
|
||||
|
||||
// Allocate output buffer
|
||||
// Print keys for comparison
|
||||
printf("[C] Private Key sk1: %s\n", sk1_hex);
|
||||
printf("[C] Public Key pk2: %s\n", pk2_hex);
|
||||
|
||||
// Allocate output buffer for encryption
|
||||
char* encrypted = malloc(NOSTR_NIP04_MAX_ENCRYPTED_SIZE);
|
||||
if (!encrypted) {
|
||||
printf("Memory allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n--- ENCRYPTION TEST ---\n");
|
||||
printf("[C] Encrypting \"%s\" using sk1 -> pk2\n", plaintext);
|
||||
|
||||
// Call the encryption function
|
||||
int result = nostr_nip04_encrypt(sk1, pk2, plaintext, encrypted, NOSTR_NIP04_MAX_ENCRYPTED_SIZE);
|
||||
|
||||
if (result == NOSTR_SUCCESS) {
|
||||
printf("%s\n", encrypted);
|
||||
printf("[C] Encrypted Result: %s\n", encrypted);
|
||||
} else {
|
||||
printf("Error: %s\n", nostr_strerror(result));
|
||||
printf("Encryption Error: %s\n", nostr_strerror(result));
|
||||
free(encrypted);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n--- DECRYPTION TEST ---\n");
|
||||
printf("[C] Decrypting \"%s\" using sk2 + pk1\n", expectedCiphertext);
|
||||
printf("[C] Private Key sk2: %s\n", sk2_hex);
|
||||
printf("[C] Public Key pk1: %s\n", pk1_hex);
|
||||
|
||||
// Allocate output buffer for decryption
|
||||
char* decrypted = malloc(1000);
|
||||
if (!decrypted) {
|
||||
printf("Memory allocation failed\n");
|
||||
free(encrypted);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Call the decryption function
|
||||
result = nostr_nip04_decrypt(sk2, pk1, expectedCiphertext, decrypted, 1000);
|
||||
|
||||
if (result == NOSTR_SUCCESS) {
|
||||
printf("[C] UTF-8 Decoded: \"%s\"\n", decrypted);
|
||||
|
||||
printf("\n--- RESULTS ---\n");
|
||||
printf("Encryption Success: Generated ciphertext\n");
|
||||
printf("Decryption Success: %s\n", strcmp(decrypted, plaintext) == 0 ? "true" : "false");
|
||||
printf("Expected: \"%s\"\n", plaintext);
|
||||
printf("Got: \"%s\"\n", decrypted);
|
||||
} else {
|
||||
printf("Decryption Error: %s\n", nostr_strerror(result));
|
||||
}
|
||||
|
||||
free(encrypted);
|
||||
free(decrypted);
|
||||
|
||||
// Cleanup NOSTR library
|
||||
nostr_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* NIP-04 Encryption DEBUG Test
|
||||
* This test shows intermediate values to compare with JavaScript implementation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../nostr_core/nip004.h"
|
||||
#include "../nostr_core/nostr_common.h"
|
||||
#include "../nostr_core/crypto/nostr_secp256k1.h"
|
||||
#include "../nostr_core/utils.h"
|
||||
|
||||
void print_hex_debug(const char* label, const unsigned char* data, size_t len) {
|
||||
printf("%s (%zu bytes): ", label, len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
printf("%02x", data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void hex_to_bytes(const char* hex_str, unsigned char* bytes) {
|
||||
size_t len = strlen(hex_str);
|
||||
for (size_t i = 0; i < len; i += 2) {
|
||||
sscanf(hex_str + i, "%2hhx", &bytes[i / 2]);
|
||||
}
|
||||
}
|
||||
|
||||
int test_ecdh_debug(void) {
|
||||
printf("\n=== ECDH DEBUG TEST ===\n");
|
||||
|
||||
// Test vector from JavaScript debug output
|
||||
const char* sk1_hex = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe";
|
||||
const char* pk2_hex = "dcb33a629560280a0ee3b6b99b68c044fe8914ad8a984001ebf6099a9b474dc3";
|
||||
|
||||
// Expected values from JavaScript:
|
||||
// Shared Secret (33 bytes): 037ce22696eb0e303ddaa491bdf2a56b79d249f2d861b8e012a933e01dc4beba81
|
||||
// Normalized Key (32 bytes): 7ce22696eb0e303ddaa491bdf2a56b79d249f2d861b8e012a933e01dc4beba81
|
||||
|
||||
unsigned char sk1[32], pk2[32];
|
||||
hex_to_bytes(sk1_hex, sk1);
|
||||
hex_to_bytes(pk2_hex, pk2);
|
||||
|
||||
printf("Private Key: %s\n", sk1_hex);
|
||||
printf("Public Key: %s\n", pk2_hex);
|
||||
|
||||
print_hex_debug("SK1", sk1, 32);
|
||||
print_hex_debug("PK2", pk2, 32);
|
||||
|
||||
// Test ECDH shared secret computation
|
||||
unsigned char shared_secret[32];
|
||||
printf("\nCalling ecdh_shared_secret...\n");
|
||||
int result = ecdh_shared_secret(sk1, pk2, shared_secret);
|
||||
printf("ecdh_shared_secret returned: %d\n", result);
|
||||
|
||||
if (result == 0) {
|
||||
print_hex_debug("C Shared Secret", shared_secret, 32);
|
||||
printf("Expected: 7ce22696eb0e303ddaa491bdf2a56b79d249f2d861b8e012a933e01dc4beba81\n");
|
||||
|
||||
// Check if it matches expected
|
||||
const char* expected_hex = "7ce22696eb0e303ddaa491bdf2a56b79d249f2d861b8e012a933e01dc4beba81";
|
||||
unsigned char expected[32];
|
||||
hex_to_bytes(expected_hex, expected);
|
||||
|
||||
if (memcmp(shared_secret, expected, 32) == 0) {
|
||||
printf("✅ ECDH matches expected value!\n");
|
||||
return 1;
|
||||
} else {
|
||||
printf("❌ ECDH does NOT match expected value\n");
|
||||
print_hex_debug("Expected", expected, 32);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
printf("❌ ECDH computation failed with error code: %d\n", result);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int test_encryption_step_by_step(void) {
|
||||
printf("\n=== STEP-BY-STEP ENCRYPTION DEBUG ===\n");
|
||||
|
||||
// Test vector 1 data
|
||||
const char* sk1_hex = "91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe";
|
||||
const char* pk2_hex = "dcb33a629560280a0ee3b6b99b68c044fe8914ad8a984001ebf6099a9b474dc3";
|
||||
const char* plaintext = "nanana";
|
||||
|
||||
// Known IV from JavaScript test (to get deterministic results)
|
||||
const char* fixed_iv_hex = "115e5b52371ce0e5f62a6ff33e9e2775";
|
||||
|
||||
printf("Private Key: %s\n", sk1_hex);
|
||||
printf("Public Key: %s\n", pk2_hex);
|
||||
printf("Plaintext: \"%s\"\n", plaintext);
|
||||
printf("Fixed IV: %s\n", fixed_iv_hex);
|
||||
|
||||
unsigned char sk1[32], pk2[32], fixed_iv[16];
|
||||
hex_to_bytes(sk1_hex, sk1);
|
||||
hex_to_bytes(pk2_hex, pk2);
|
||||
hex_to_bytes(fixed_iv_hex, fixed_iv);
|
||||
|
||||
// Step 1: ECDH
|
||||
printf("\n--- Step 1: ECDH Shared Secret ---\n");
|
||||
unsigned char shared_secret[32];
|
||||
if (ecdh_shared_secret(sk1, pk2, shared_secret) != 0) {
|
||||
printf("❌ ECDH failed\n");
|
||||
return 0;
|
||||
}
|
||||
print_hex_debug("Shared Secret", shared_secret, 32);
|
||||
printf("Expected: 7ce22696eb0e303ddaa491bdf2a56b79d249f2d861b8e012a933e01dc4beba81\n");
|
||||
|
||||
// Step 2: Convert plaintext to bytes
|
||||
printf("\n--- Step 2: Plaintext to UTF-8 bytes ---\n");
|
||||
size_t plaintext_len = strlen(plaintext);
|
||||
printf("UTF-8 Plaintext (%zu bytes): ", plaintext_len);
|
||||
for (size_t i = 0; i < plaintext_len; i++) {
|
||||
printf("%02x", (unsigned char)plaintext[i]);
|
||||
}
|
||||
printf("\n");
|
||||
printf("Expected: 6e616e616e61\n");
|
||||
|
||||
// Step 3: PKCS#7 padding
|
||||
printf("\n--- Step 3: PKCS#7 Padding ---\n");
|
||||
size_t padded_len = ((plaintext_len / 16) + 1) * 16;
|
||||
unsigned char* padded_data = malloc(padded_len);
|
||||
if (!padded_data) {
|
||||
printf("❌ Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(padded_data, plaintext, plaintext_len);
|
||||
|
||||
// Manual PKCS#7 padding for debugging
|
||||
size_t padding_needed = 16 - (plaintext_len % 16);
|
||||
for (size_t i = 0; i < padding_needed; i++) {
|
||||
padded_data[plaintext_len + i] = (unsigned char)padding_needed;
|
||||
}
|
||||
size_t actual_padded_len = plaintext_len + padding_needed;
|
||||
|
||||
print_hex_debug("Padded Data", padded_data, actual_padded_len);
|
||||
printf("Padding bytes added: %zu (value: 0x%02x)\n", padding_needed, (unsigned char)padding_needed);
|
||||
|
||||
// Step 4: Try calling the full encryption function
|
||||
printf("\n--- Step 4: Full Encryption Function ---\n");
|
||||
char* encrypted = malloc(NOSTR_NIP04_MAX_ENCRYPTED_SIZE);
|
||||
if (!encrypted) {
|
||||
printf("❌ Memory allocation failed\n");
|
||||
free(padded_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Calling nostr_nip04_encrypt...\n");
|
||||
int result = nostr_nip04_encrypt(sk1, pk2, plaintext, encrypted, NOSTR_NIP04_MAX_ENCRYPTED_SIZE);
|
||||
printf("nostr_nip04_encrypt returned: %d (%s)\n", result, nostr_strerror(result));
|
||||
|
||||
if (result == NOSTR_SUCCESS) {
|
||||
printf("✅ Encryption succeeded!\n");
|
||||
printf("Result: %s\n", encrypted);
|
||||
printf("Expected: zJxfaJ32rN5Dg1ODjOlEew==?iv=EV5bUjcc4OX2Km/zPp4ndQ==\n");
|
||||
} else {
|
||||
printf("❌ Encryption failed with error: %s\n", nostr_strerror(result));
|
||||
}
|
||||
|
||||
free(padded_data);
|
||||
free(encrypted);
|
||||
return result == NOSTR_SUCCESS ? 1 : 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("=== NIP-04 DEBUG TEST ===\n");
|
||||
printf("This test shows intermediate values for comparison with JavaScript implementation\n\n");
|
||||
|
||||
// Initialize secp256k1 context
|
||||
printf("Initializing secp256k1 context...\n");
|
||||
if (!nostr_secp256k1_context_create()) {
|
||||
printf("❌ Failed to initialize secp256k1 context!\n");
|
||||
return 1;
|
||||
}
|
||||
printf("✅ secp256k1 context initialized successfully\n\n");
|
||||
|
||||
int all_passed = 1;
|
||||
|
||||
// Test 1: ECDH computation
|
||||
if (!test_ecdh_debug()) {
|
||||
all_passed = 0;
|
||||
printf("❌ ECDH test failed - this is likely the root cause!\n");
|
||||
}
|
||||
|
||||
// Test 2: Step by step encryption
|
||||
if (!test_encryption_step_by_step()) {
|
||||
all_passed = 0;
|
||||
}
|
||||
|
||||
// Summary
|
||||
printf("\n=== SUMMARY ===\n");
|
||||
if (all_passed) {
|
||||
printf("✅ All debug tests passed!\n");
|
||||
} else {
|
||||
printf("❌ Some debug tests failed - compare values with JavaScript output\n");
|
||||
}
|
||||
|
||||
// Clean up secp256k1 context
|
||||
nostr_secp256k1_context_destroy();
|
||||
|
||||
return all_passed ? 0 : 1;
|
||||
}
|
||||
BIN
tests/nip04_test
BIN
tests/nip04_test
Binary file not shown.
BIN
tests/nip44_test
Executable file
BIN
tests/nip44_test
Executable file
Binary file not shown.
@@ -20,24 +20,26 @@ typedef struct {
|
||||
const char* expected_encrypted; // Optional - for known test vectors
|
||||
} nip44_test_vector_t;
|
||||
|
||||
// Known test vectors from nostr-tools nip44.vectors.json
|
||||
static nip44_test_vector_t known_test_vectors[] = {
|
||||
// Known decryption-only test vectors from nostr-tools (for cross-compatibility testing)
|
||||
// Note: NIP-44 encryption is non-deterministic - ciphertext varies each time
|
||||
// These vectors test our ability to decrypt known good ciphertext from reference implementations
|
||||
static nip44_test_vector_t decryption_test_vectors[] = {
|
||||
{
|
||||
"Known vector: single char 'a'",
|
||||
"Decryption test: single char 'a'",
|
||||
"0000000000000000000000000000000000000000000000000000000000000001", // sec1
|
||||
"0000000000000000000000000000000000000000000000000000000000000002", // sec2
|
||||
"a",
|
||||
"AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABee0G5VSK0/9YypIObAtDKfYEAjD35uVkHyB0F4DwrcNaCXlCWZKaArsGrY6M9wnuTMxWfp1RTN9Xga8no+kF5Vsb"
|
||||
},
|
||||
{
|
||||
"Known vector: emoji",
|
||||
"Decryption test: emoji",
|
||||
"0000000000000000000000000000000000000000000000000000000000000002", // sec1
|
||||
"0000000000000000000000000000000000000000000000000000000000000001", // sec2
|
||||
"🍕🫃",
|
||||
"AvAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAPSKSK6is9ngkX2+cSq85Th16oRTISAOfhStnixqZziKMDvB0QQzgFZdjLTPicCJaV8nDITO+QfaQ61+KbWQIOO2Yj"
|
||||
},
|
||||
{
|
||||
"Known vector: wide unicode",
|
||||
"Decryption test: wide unicode",
|
||||
"5c0c523f52a5b6fad39ed2403092df8cebc36318b39383bca6c00808626fab3a", // sec1
|
||||
"4b22aa260e4acb7021e32f38a6cdf4b673c6a277755bfce287e370c924dc936d", // sec2
|
||||
"表ポあA鷗ŒéB逍Üߪąñ丂㐀𠀀",
|
||||
@@ -89,19 +91,19 @@ static void bytes_to_hex(const unsigned char* bytes, size_t len, char* hex) {
|
||||
}
|
||||
|
||||
static int test_nip44_round_trip(const nip44_test_vector_t* tv) {
|
||||
printf("Testing: %s\n", tv->name);
|
||||
printf("Test: %s\n", tv->name);
|
||||
|
||||
// Parse keys - both private keys
|
||||
unsigned char sender_private_key[32];
|
||||
unsigned char recipient_private_key[32];
|
||||
|
||||
if (hex_to_bytes(tv->sender_private_key_hex, sender_private_key, 32) != 0) {
|
||||
printf(" ❌ Failed to parse sender private key\n");
|
||||
printf(" FAIL: Failed to parse sender private key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hex_to_bytes(tv->recipient_private_key_hex, recipient_private_key, 32) != 0) {
|
||||
printf(" ❌ Failed to parse recipient private key\n");
|
||||
printf(" FAIL: Failed to parse recipient private key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -110,17 +112,17 @@ static int test_nip44_round_trip(const nip44_test_vector_t* tv) {
|
||||
unsigned char recipient_public_key[32];
|
||||
|
||||
if (nostr_ec_public_key_from_private_key(sender_private_key, sender_public_key) != 0) {
|
||||
printf(" ❌ Failed to derive sender public key\n");
|
||||
printf(" FAIL: Failed to derive sender public key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nostr_ec_public_key_from_private_key(recipient_private_key, recipient_public_key) != 0) {
|
||||
printf(" ❌ Failed to derive recipient public key\n");
|
||||
printf(" FAIL: Failed to derive recipient public key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Test encryption
|
||||
char encrypted[8192]; // Large buffer for encrypted data
|
||||
char encrypted[8192];
|
||||
int encrypt_result = nostr_nip44_encrypt(
|
||||
sender_private_key,
|
||||
recipient_public_key,
|
||||
@@ -130,15 +132,12 @@ static int test_nip44_round_trip(const nip44_test_vector_t* tv) {
|
||||
);
|
||||
|
||||
if (encrypt_result != NOSTR_SUCCESS) {
|
||||
printf(" ❌ Encryption failed with error: %d\n", encrypt_result);
|
||||
printf(" FAIL: Encryption - Expected: %d, Actual: %d\n", NOSTR_SUCCESS, encrypt_result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" ✅ Encryption successful\n");
|
||||
printf(" 📦 Encrypted length: %zu bytes\n", strlen(encrypted));
|
||||
|
||||
// Test decryption - use recipient private key + sender public key
|
||||
char decrypted[8192]; // Large buffer for decrypted data
|
||||
char decrypted[8192];
|
||||
int decrypt_result = nostr_nip44_decrypt(
|
||||
recipient_private_key,
|
||||
sender_public_key,
|
||||
@@ -148,27 +147,26 @@ static int test_nip44_round_trip(const nip44_test_vector_t* tv) {
|
||||
);
|
||||
|
||||
if (decrypt_result != NOSTR_SUCCESS) {
|
||||
printf(" ❌ Decryption failed with error: %d\n", decrypt_result);
|
||||
printf(" FAIL: Decryption - Expected: %d, Actual: %d\n", NOSTR_SUCCESS, decrypt_result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Verify round-trip
|
||||
if (strcmp(tv->plaintext, decrypted) != 0) {
|
||||
printf(" ❌ Round-trip failed!\n");
|
||||
printf(" 📝 Original: \"%s\"\n", tv->plaintext);
|
||||
printf(" 📝 Decrypted: \"%s\"\n", decrypted);
|
||||
printf(" FAIL: Round-trip mismatch\n");
|
||||
printf(" Expected: \"%s\"\n", tv->plaintext);
|
||||
printf(" Actual: \"%s\"\n", decrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" ✅ Round-trip successful!\n");
|
||||
printf(" 📝 Message: \"%s\"\n", tv->plaintext);
|
||||
printf("\n");
|
||||
printf(" PASS: Expected: \"%s\", Actual: \"%s\"\n", tv->plaintext, decrypted);
|
||||
printf(" Encrypted output: %s\n", encrypted);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_nip44_error_conditions() {
|
||||
printf("Testing NIP-44 error conditions:\n");
|
||||
printf("Test: NIP-44 error conditions\n");
|
||||
|
||||
// Use proper valid secp256k1 private keys
|
||||
unsigned char valid_sender_key[32];
|
||||
@@ -180,7 +178,7 @@ static int test_nip44_error_conditions() {
|
||||
|
||||
// Generate the recipient's public key
|
||||
if (nostr_ec_public_key_from_private_key(valid_recipient_key, valid_recipient_pubkey) != 0) {
|
||||
printf(" ❌ Failed to generate recipient public key\n");
|
||||
printf(" FAIL: Failed to generate recipient public key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -189,25 +187,25 @@ static int test_nip44_error_conditions() {
|
||||
// Test NULL parameters
|
||||
int result = nostr_nip44_encrypt(NULL, valid_recipient_pubkey, "test", output, sizeof(output));
|
||||
if (result != NOSTR_ERROR_INVALID_INPUT) {
|
||||
printf(" ❌ Should reject NULL sender key\n");
|
||||
printf(" FAIL: NULL sender key - Expected: %d, Actual: %d\n", NOSTR_ERROR_INVALID_INPUT, result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = nostr_nip44_encrypt(valid_sender_key, NULL, "test", output, sizeof(output));
|
||||
if (result != NOSTR_ERROR_INVALID_INPUT) {
|
||||
printf(" ❌ Should reject NULL recipient key\n");
|
||||
printf(" FAIL: NULL recipient key - Expected: %d, Actual: %d\n", NOSTR_ERROR_INVALID_INPUT, result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = nostr_nip44_encrypt(valid_sender_key, valid_recipient_pubkey, NULL, output, sizeof(output));
|
||||
if (result != NOSTR_ERROR_INVALID_INPUT) {
|
||||
printf(" ❌ Should reject NULL plaintext\n");
|
||||
printf(" FAIL: NULL plaintext - Expected: %d, Actual: %d\n", NOSTR_ERROR_INVALID_INPUT, result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = nostr_nip44_encrypt(valid_sender_key, valid_recipient_pubkey, "test", NULL, sizeof(output));
|
||||
if (result != NOSTR_ERROR_INVALID_INPUT) {
|
||||
printf(" ❌ Should reject NULL output buffer\n");
|
||||
printf(" FAIL: NULL output buffer - Expected: %d, Actual: %d\n", NOSTR_ERROR_INVALID_INPUT, result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -215,28 +213,28 @@ static int test_nip44_error_conditions() {
|
||||
char small_buffer[10];
|
||||
result = nostr_nip44_encrypt(valid_sender_key, valid_recipient_pubkey, "test message", small_buffer, sizeof(small_buffer));
|
||||
if (result != NOSTR_ERROR_NIP44_BUFFER_TOO_SMALL) {
|
||||
printf(" ❌ Should detect buffer too small, got error: %d\n", result);
|
||||
printf(" FAIL: Buffer too small - Expected: %d, Actual: %d\n", NOSTR_ERROR_NIP44_BUFFER_TOO_SMALL, result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" ✅ All error conditions handled correctly\n\n");
|
||||
printf(" PASS: All error conditions handled correctly\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_nip44_known_vector(const nip44_test_vector_t* tv) {
|
||||
printf("Testing known vector: %s\n", tv->name);
|
||||
static int test_nip44_decryption_vector(const nip44_test_vector_t* tv) {
|
||||
printf("Test: %s\n", tv->name);
|
||||
|
||||
// Parse keys
|
||||
unsigned char sender_private_key[32];
|
||||
unsigned char recipient_private_key[32];
|
||||
|
||||
if (hex_to_bytes(tv->sender_private_key_hex, sender_private_key, 32) != 0) {
|
||||
printf(" ❌ Failed to parse sender private key\n");
|
||||
printf(" FAIL: Failed to parse sender private key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hex_to_bytes(tv->recipient_private_key_hex, recipient_private_key, 32) != 0) {
|
||||
printf(" ❌ Failed to parse recipient private key\n");
|
||||
printf(" FAIL: Failed to parse recipient private key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -244,7 +242,7 @@ static int test_nip44_known_vector(const nip44_test_vector_t* tv) {
|
||||
unsigned char sender_public_key[32];
|
||||
|
||||
if (nostr_ec_public_key_from_private_key(sender_private_key, sender_public_key) != 0) {
|
||||
printf(" ❌ Failed to derive sender public key\n");
|
||||
printf(" FAIL: Failed to derive sender public key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -259,87 +257,103 @@ static int test_nip44_known_vector(const nip44_test_vector_t* tv) {
|
||||
);
|
||||
|
||||
if (decrypt_result != NOSTR_SUCCESS) {
|
||||
printf(" ❌ Decryption of known vector failed with error: %d\n", decrypt_result);
|
||||
printf(" 📦 Expected payload: %.80s...\n", tv->expected_encrypted);
|
||||
printf(" FAIL: Decryption - Expected: %d, Actual: %d\n", NOSTR_SUCCESS, decrypt_result);
|
||||
printf(" Input payload: %s\n", tv->expected_encrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Verify decrypted plaintext matches expected
|
||||
if (strcmp(tv->plaintext, decrypted) != 0) {
|
||||
printf(" ❌ Decrypted plaintext doesn't match!\n");
|
||||
printf(" 📝 Expected: \"%s\"\n", tv->plaintext);
|
||||
printf(" 📝 Got: \"%s\"\n", decrypted);
|
||||
printf(" FAIL: Plaintext mismatch\n");
|
||||
printf(" Expected: \"%s\"\n", tv->plaintext);
|
||||
printf(" Actual: \"%s\"\n", decrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" ✅ Known vector decryption successful!\n");
|
||||
printf(" 📝 Message: \"%s\"\n", tv->plaintext);
|
||||
printf("\n");
|
||||
printf(" PASS: Expected: \"%s\", Actual: \"%s\"\n", tv->plaintext, decrypted);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_nip44_vs_nip04_comparison() {
|
||||
printf("Testing NIP-44 vs NIP-04 comparison:\n");
|
||||
|
||||
const char* test_message = "This is a test message for comparing NIP-04 and NIP-44 encryption methods.";
|
||||
static int test_nip44_encryption_variability() {
|
||||
printf("Test: NIP-44 encryption variability (non-deterministic)\n");
|
||||
|
||||
const char* test_message = "Test message for variability";
|
||||
unsigned char sender_key[32], recipient_key[32];
|
||||
memset(sender_key, 0x11, 32);
|
||||
memset(recipient_key, 0x22, 32);
|
||||
|
||||
// Generate proper public keys
|
||||
unsigned char sender_pubkey[32], recipient_pubkey[32];
|
||||
if (nostr_ec_public_key_from_private_key(sender_key, sender_pubkey) != 0 ||
|
||||
nostr_ec_public_key_from_private_key(recipient_key, recipient_pubkey) != 0) {
|
||||
printf(" ❌ Failed to generate public keys\n");
|
||||
// Use fixed test keys
|
||||
hex_to_bytes("1111111111111111111111111111111111111111111111111111111111111111", sender_key, 32);
|
||||
hex_to_bytes("2222222222222222222222222222222222222222222222222222222222222222", recipient_key, 32);
|
||||
|
||||
// Generate recipient public key
|
||||
unsigned char recipient_pubkey[32];
|
||||
if (nostr_ec_public_key_from_private_key(recipient_key, recipient_pubkey) != 0) {
|
||||
printf(" FAIL: Failed to generate recipient public key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Test NIP-04 encryption
|
||||
char nip04_encrypted[8192];
|
||||
int nip04_result = nostr_nip04_encrypt(sender_key, recipient_pubkey,
|
||||
test_message, nip04_encrypted, sizeof(nip04_encrypted));
|
||||
// Encrypt the same message multiple times
|
||||
char encrypted1[8192], encrypted2[8192], encrypted3[8192];
|
||||
|
||||
// Test NIP-44 encryption
|
||||
char nip44_encrypted[8192];
|
||||
int nip44_result = nostr_nip44_encrypt(sender_key, recipient_pubkey,
|
||||
test_message, nip44_encrypted, sizeof(nip44_encrypted));
|
||||
int result1 = nostr_nip44_encrypt(sender_key, recipient_pubkey, test_message, encrypted1, sizeof(encrypted1));
|
||||
int result2 = nostr_nip44_encrypt(sender_key, recipient_pubkey, test_message, encrypted2, sizeof(encrypted2));
|
||||
int result3 = nostr_nip44_encrypt(sender_key, recipient_pubkey, test_message, encrypted3, sizeof(encrypted3));
|
||||
|
||||
if (nip04_result == NOSTR_SUCCESS && nip44_result == NOSTR_SUCCESS) {
|
||||
printf(" ✅ Both NIP-04 and NIP-44 encryption successful\n");
|
||||
printf(" 📊 NIP-04 output length: %zu bytes\n", strlen(nip04_encrypted));
|
||||
printf(" 📊 NIP-44 output length: %zu bytes\n", strlen(nip44_encrypted));
|
||||
printf(" 📊 Size difference: %+ld bytes\n",
|
||||
(long)strlen(nip44_encrypted) - (long)strlen(nip04_encrypted));
|
||||
|
||||
// Verify they produce different outputs (they use different algorithms)
|
||||
if (strcmp(nip04_encrypted, nip44_encrypted) == 0) {
|
||||
printf(" ⚠️ Warning: NIP-04 and NIP-44 produced identical output (unexpected)\n");
|
||||
} else {
|
||||
printf(" ✅ NIP-04 and NIP-44 produce different outputs (expected)\n");
|
||||
}
|
||||
} else {
|
||||
if (nip04_result != NOSTR_SUCCESS) {
|
||||
printf(" ❌ NIP-04 encryption failed: %d\n", nip04_result);
|
||||
}
|
||||
if (nip44_result != NOSTR_SUCCESS) {
|
||||
printf(" ❌ NIP-44 encryption failed: %d\n", nip44_result);
|
||||
}
|
||||
if (result1 != NOSTR_SUCCESS || result2 != NOSTR_SUCCESS || result3 != NOSTR_SUCCESS) {
|
||||
printf(" FAIL: Encryption failed - Results: %d, %d, %d\n", result1, result2, result3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
// Verify all ciphertexts are different (non-deterministic)
|
||||
if (strcmp(encrypted1, encrypted2) == 0 || strcmp(encrypted1, encrypted3) == 0 || strcmp(encrypted2, encrypted3) == 0) {
|
||||
printf(" FAIL: NIP-44 encryption should produce different ciphertext each time\n");
|
||||
printf(" Encryption 1: %.50s...\n", encrypted1);
|
||||
printf(" Encryption 2: %.50s...\n", encrypted2);
|
||||
printf(" Encryption 3: %.50s...\n", encrypted3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Verify all decrypt to the same plaintext
|
||||
unsigned char sender_pubkey[32];
|
||||
if (nostr_ec_public_key_from_private_key(sender_key, sender_pubkey) != 0) {
|
||||
printf(" FAIL: Failed to generate sender public key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char decrypted1[8192], decrypted2[8192], decrypted3[8192];
|
||||
|
||||
int decrypt1 = nostr_nip44_decrypt(recipient_key, sender_pubkey, encrypted1, decrypted1, sizeof(decrypted1));
|
||||
int decrypt2 = nostr_nip44_decrypt(recipient_key, sender_pubkey, encrypted2, decrypted2, sizeof(decrypted2));
|
||||
int decrypt3 = nostr_nip44_decrypt(recipient_key, sender_pubkey, encrypted3, decrypted3, sizeof(decrypted3));
|
||||
|
||||
if (decrypt1 != NOSTR_SUCCESS || decrypt2 != NOSTR_SUCCESS || decrypt3 != NOSTR_SUCCESS) {
|
||||
printf(" FAIL: Decryption failed - Results: %d, %d, %d\n", decrypt1, decrypt2, decrypt3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(decrypted1, test_message) != 0 || strcmp(decrypted2, test_message) != 0 || strcmp(decrypted3, test_message) != 0) {
|
||||
printf(" FAIL: Decryption mismatch\n");
|
||||
printf(" Expected: \"%s\"\n", test_message);
|
||||
printf(" Decrypted1: \"%s\"\n", decrypted1);
|
||||
printf(" Decrypted2: \"%s\"\n", decrypted2);
|
||||
printf(" Decrypted3: \"%s\"\n", decrypted3);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf(" PASS: All encryptions different, all decrypt to: \"%s\"\n", test_message);
|
||||
printf(" Sample ciphertext lengths: %zu, %zu, %zu bytes\n", strlen(encrypted1), strlen(encrypted2), strlen(encrypted3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
printf("🧪 NIP-44 Encryption Test Suite\n");
|
||||
printf("================================\n\n");
|
||||
printf("NIP-44 Encryption Test Suite\n");
|
||||
printf("=============================\n");
|
||||
|
||||
// Initialize the library
|
||||
if (nostr_init() != NOSTR_SUCCESS) {
|
||||
printf("❌ Failed to initialize NOSTR library\n");
|
||||
printf("FAIL: Failed to initialize NOSTR library\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -355,38 +369,36 @@ int main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Test known vectors
|
||||
size_t num_known_vectors = sizeof(known_test_vectors) / sizeof(known_test_vectors[0]);
|
||||
for (size_t i = 0; i < num_known_vectors; i++) {
|
||||
// Test decryption vectors (cross-compatibility)
|
||||
size_t num_decryption_vectors = sizeof(decryption_test_vectors) / sizeof(decryption_test_vectors[0]);
|
||||
for (size_t i = 0; i < num_decryption_vectors; i++) {
|
||||
total_tests++;
|
||||
if (test_nip44_known_vector(&known_test_vectors[i]) == 0) {
|
||||
if (test_nip44_decryption_vector(&decryption_test_vectors[i]) == 0) {
|
||||
passed_tests++;
|
||||
}
|
||||
}
|
||||
|
||||
// Test encryption variability (NIP-44 non-deterministic behavior)
|
||||
total_tests++;
|
||||
if (test_nip44_encryption_variability() == 0) {
|
||||
passed_tests++;
|
||||
}
|
||||
|
||||
// Test error conditions
|
||||
total_tests++;
|
||||
if (test_nip44_error_conditions() == 0) {
|
||||
passed_tests++;
|
||||
}
|
||||
|
||||
// Test comparison with NIP-04
|
||||
total_tests++;
|
||||
if (test_nip44_vs_nip04_comparison() == 0) {
|
||||
passed_tests++;
|
||||
}
|
||||
|
||||
// Final results
|
||||
printf("🏁 Test Results:\n");
|
||||
printf("================\n");
|
||||
printf("Tests passed: %d/%d\n", passed_tests, total_tests);
|
||||
printf("\nTest Results: %d/%d passed\n", passed_tests, total_tests);
|
||||
|
||||
if (passed_tests == total_tests) {
|
||||
printf("✅ All NIP-44 tests PASSED! 🎉\n");
|
||||
printf("All NIP-44 tests PASSED\n");
|
||||
nostr_cleanup();
|
||||
return 0;
|
||||
} else {
|
||||
printf("❌ Some tests FAILED! 😞\n");
|
||||
printf("Some tests FAILED\n");
|
||||
nostr_cleanup();
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user