/* * NIP-44 Debug Test - Step-by-step comparison with nostr-tools vectors * * This test prints intermediate values for comparison with nostr-tools */ #include #include #include #include #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; }