Fixed error in nip04 implementation. Now working

This commit is contained in:
2025-08-17 10:42:38 -04:00
parent df23fd618a
commit d8b342ca3f
15 changed files with 723 additions and 1129 deletions

View File

@@ -155,36 +155,85 @@ static int ecdh_hash_function_copy_x(unsigned char* output, const unsigned char*
int ecdh_shared_secret(const unsigned char* private_key,
const unsigned char* public_key_x,
unsigned char* shared_secret) {
if (!private_key || !public_key_x || !shared_secret) return -1;
/*
* WARNING: This function requires proper library initialization!
*
* Before calling this function, you must call nostr_init() to initialize
* the secp256k1 global context. All secp256k1 wrapper functions will fail
* with error code 0 if the global context g_ctx is not initialized.
*
* Example usage:
* if (nostr_init() != NOSTR_SUCCESS) {
* // Handle initialization error
* return -1;
* }
* // Now you can safely call ecdh_shared_secret() and other crypto functions
* int result = ecdh_shared_secret(private_key, public_key_x, shared_secret);
*
* // Don't forget to cleanup when done:
* nostr_cleanup();
*/
printf("[DEBUG] ecdh_shared_secret: Starting ECDH computation\n");
if (!private_key || !public_key_x || !shared_secret) {
printf("[DEBUG] ecdh_shared_secret: Invalid input - null pointer detected\n");
return -1;
}
printf("[DEBUG] ecdh_shared_secret: Input validation passed\n");
// NIP-04 ECDH: The key insight from the specification is that NOSTR requires
// "only the X coordinate of the shared point is used as the secret and it is NOT hashed"
//
// libsecp256k1's default ECDH hashes the shared point with SHA256.
// We need to use a custom hash function that just copies the X coordinate.
//
// This matches exactly what @noble/curves getSharedSecret() does:
// 1. Always use 0x02 prefix (compressed format)
// 2. Perform ECDH scalar multiplication
// 3. Extract only the X coordinate (bytes 1-33 from the compressed point)
// The issue was that we can't just assume the y-coordinate parity.
// We need to try both possible y-coordinate parities (0x02 and 0x03).
unsigned char compressed_pubkey[33];
compressed_pubkey[0] = 0x02; // Always use 0x02 prefix like nostr-tools
nostr_secp256k1_pubkey pubkey;
// Try with 0x02 prefix first (even y-coordinate)
compressed_pubkey[0] = 0x02;
memcpy(compressed_pubkey + 1, public_key_x, 32);
// Parse the public key
nostr_secp256k1_pubkey pubkey;
if (nostr_secp256k1_ec_pubkey_parse(&pubkey, compressed_pubkey, 33) != 1) {
return -1;
printf("[DEBUG] ecdh_shared_secret: Trying 0x02 prefix (even y)\n");
if (nostr_secp256k1_ec_pubkey_parse(&pubkey, compressed_pubkey, 33) == 1) {
printf("[DEBUG] ecdh_shared_secret: 0x02 prefix worked, public key parsed successfully\n");
// Perform ECDH with our custom hash function that copies the X coordinate
printf("[DEBUG] ecdh_shared_secret: Performing ECDH operation with 0x02 prefix\n");
if (nostr_secp256k1_ecdh(shared_secret, &pubkey, private_key, ecdh_hash_function_copy_x, NULL) == 1) {
printf("[DEBUG] ecdh_shared_secret: ECDH operation completed successfully\n");
return 0;
} else {
printf("[DEBUG] ecdh_shared_secret: ECDH operation failed with 0x02 prefix\n");
}
} else {
printf("[DEBUG] ecdh_shared_secret: 0x02 prefix failed, trying 0x03 prefix (odd y)\n");
}
// Perform ECDH with our custom hash function that copies the X coordinate
// This is the crucial fix: we pass ecdh_hash_function_copy_x instead of NULL
if (nostr_secp256k1_ecdh(shared_secret, &pubkey, private_key, ecdh_hash_function_copy_x, NULL) != 1) {
return -1;
// Try with 0x03 prefix (odd y-coordinate)
compressed_pubkey[0] = 0x03;
// public_key_x is already copied above
if (nostr_secp256k1_ec_pubkey_parse(&pubkey, compressed_pubkey, 33) == 1) {
printf("[DEBUG] ecdh_shared_secret: 0x03 prefix worked, public key parsed successfully\n");
// Perform ECDH with our custom hash function that copies the X coordinate
printf("[DEBUG] ecdh_shared_secret: Performing ECDH operation with 0x03 prefix\n");
if (nostr_secp256k1_ecdh(shared_secret, &pubkey, private_key, ecdh_hash_function_copy_x, NULL) == 1) {
printf("[DEBUG] ecdh_shared_secret: ECDH operation completed successfully\n");
return 0;
} else {
printf("[DEBUG] ecdh_shared_secret: ECDH operation failed with 0x03 prefix\n");
}
} else {
printf("[DEBUG] ecdh_shared_secret: Both 0x02 and 0x03 prefixes failed - invalid public key\n");
}
return 0;
printf("[DEBUG] ecdh_shared_secret: All attempts failed\n");
return -1;
}
// =============================================================================