v0.0.58 - Added derive verb: HMAC-SHA256(privkey, data) for secp256k1, enabling opaque d-tag derivation via nsigner remote backend without exposing the privkey
This commit is contained in:
@@ -74,6 +74,7 @@ role_curve_t role_curve_from_str(const char *s);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
#define VERB_GET_PUBLIC_KEY "get_public_key"
|
||||
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
|
||||
#define VERB_NOSTR_SIGN_EVENT "nostr_sign_event"
|
||||
@@ -363,6 +364,14 @@ int main(void) {
|
||||
enforce_verb_algorithm(VERB_DERIVE_SHARED, CRYPTO_ALG_X25519) == ENFORCE_OK);
|
||||
check("enforce derive_shared_secret + ed25519 -> ALGORITHM err",
|
||||
enforce_verb_algorithm(VERB_DERIVE_SHARED, CRYPTO_ALG_ED25519) == ENFORCE_ERR_ALGORITHM);
|
||||
check("enforce derive + secp256k1 -> OK",
|
||||
enforce_verb_algorithm(VERB_DERIVE, CRYPTO_ALG_SECP256K1) == ENFORCE_OK);
|
||||
check("enforce derive + ed25519 -> ALGORITHM err",
|
||||
enforce_verb_algorithm(VERB_DERIVE, CRYPTO_ALG_ED25519) == ENFORCE_ERR_ALGORITHM);
|
||||
check("enforce derive + x25519 -> ALGORITHM err",
|
||||
enforce_verb_algorithm(VERB_DERIVE, CRYPTO_ALG_X25519) == ENFORCE_ERR_ALGORITHM);
|
||||
check("enforce derive + ml-kem-768 -> ALGORITHM err",
|
||||
enforce_verb_algorithm(VERB_DERIVE, CRYPTO_ALG_ML_KEM_768) == ENFORCE_ERR_ALGORITHM);
|
||||
check("enforce get_public_key + any alg -> OK",
|
||||
enforce_verb_algorithm(VERB_GET_PUBLIC_KEY, CRYPTO_ALG_ED25519) == ENFORCE_OK);
|
||||
check("enforce nostr_sign_event + secp256k1 -> OK",
|
||||
@@ -678,6 +687,96 @@ int main(void) {
|
||||
check("policy_check_algorithm: wrong caller -> NO_MATCH", rc == POLICY_NO_MATCH);
|
||||
}
|
||||
|
||||
/* ---- derive: HMAC-SHA256(privkey, data) — secp256k1 ---- */
|
||||
/* Successful call returns a 64-hex digest. */
|
||||
resp = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv1\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
check("derive secp256k1 returns result", resp_has(resp, "\"result\""));
|
||||
check("derive secp256k1 has digest field", resp_has(resp, "digest"));
|
||||
check("derive secp256k1 has algorithm secp256k1", resp_has(resp, "secp256k1"));
|
||||
{
|
||||
char *digest_hex = extract_result_field(resp, "digest");
|
||||
check("derive secp256k1 digest is 64 hex chars",
|
||||
digest_hex != NULL && strlen(digest_hex) == 64);
|
||||
free(digest_hex);
|
||||
}
|
||||
free(resp);
|
||||
|
||||
/* Determinism: same input -> same digest. */
|
||||
resp = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv2\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
{
|
||||
char *digest2 = extract_result_field(resp, "digest");
|
||||
/* Re-run first call to compare (deterministic). */
|
||||
char *resp_a = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv1b\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
char *digest_a = extract_result_field(resp_a, "digest");
|
||||
check("derive determinism: same input -> same digest",
|
||||
digest2 != NULL && digest_a != NULL && strcmp(digest2, digest_a) == 0);
|
||||
free(digest2); free(digest_a); free(resp_a);
|
||||
}
|
||||
free(resp);
|
||||
|
||||
/* Opaqueness: different inputs -> different digests. */
|
||||
{
|
||||
char *resp_b = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv3\",\"method\":\"derive\",\"params\":[\"other-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
char *resp_c = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv1c\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
char *dig_b = extract_result_field(resp_b, "digest");
|
||||
char *dig_c = extract_result_field(resp_c, "digest");
|
||||
check("derive opaqueness: different inputs -> different digests",
|
||||
dig_b != NULL && dig_c != NULL && strcmp(dig_b, dig_c) != 0);
|
||||
free(dig_b); free(dig_c); free(resp_b); free(resp_c);
|
||||
}
|
||||
|
||||
/* Cross-check against nostr_hmac_sha256 with the derived private key. */
|
||||
{
|
||||
const unsigned char *priv = crypto_get_private_key(&g_key_store, 0);
|
||||
unsigned char ref_mac[32];
|
||||
char ref_hex[65];
|
||||
char *resp_ref = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dvref\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
char *got_hex = extract_result_field(resp_ref, "digest");
|
||||
if (priv != NULL && nostr_hmac_sha256(priv, 32,
|
||||
(const unsigned char *)"test-data", strlen("test-data"),
|
||||
ref_mac) == 0) {
|
||||
nostr_bytes_to_hex(ref_mac, 32, ref_hex);
|
||||
check("derive matches reference HMAC-SHA256(privkey, data)",
|
||||
got_hex != NULL && strcmp(got_hex, ref_hex) == 0);
|
||||
} else {
|
||||
check("derive reference HMAC computation available", 0);
|
||||
}
|
||||
free(got_hex); free(resp_ref);
|
||||
}
|
||||
|
||||
/* index is required: omitting it returns missing_index. */
|
||||
resp = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv4\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\"}]}");
|
||||
check("derive without index returns missing_index",
|
||||
resp_has(resp, "missing_index"));
|
||||
free(resp);
|
||||
|
||||
/* Non-secp256k1 algorithm is rejected. */
|
||||
resp = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dv5\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"ed25519\",\"index\":0}]}");
|
||||
check("derive ed25519 returns algorithm error",
|
||||
resp_has(resp, "algorithm_not_supported_for_verb") || resp_has(resp, "\"code\":1010"));
|
||||
free(resp);
|
||||
|
||||
/* Different index -> different digest (different privkey). */
|
||||
{
|
||||
char *r0 = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dvi0\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":0}]}");
|
||||
char *r1 = dispatcher_handle_request(&g_dispatcher,
|
||||
"{\"id\":\"dvi1\",\"method\":\"derive\",\"params\":[\"test-data\",{\"algorithm\":\"secp256k1\",\"index\":1}]}");
|
||||
char *d0 = extract_result_field(r0, "digest");
|
||||
char *d1 = extract_result_field(r1, "digest");
|
||||
check("derive different index -> different digest",
|
||||
d0 != NULL && d1 != NULL && strcmp(d0, d1) != 0);
|
||||
free(d0); free(d1); free(r0); free(r1);
|
||||
}
|
||||
|
||||
/* ---- Cleanup ---- */
|
||||
crypto_wipe(&g_key_store);
|
||||
alg_key_cache_wipe(&g_alg_key_cache);
|
||||
|
||||
@@ -211,6 +211,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -220,6 +221,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -158,6 +158,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
|
||||
#define VERB_NOSTR_SIGN_EVENT "nostr_sign_event"
|
||||
#define VERB_NOSTR_MINE_EVENT "nostr_mine_event"
|
||||
|
||||
@@ -208,6 +208,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -217,6 +218,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -210,6 +210,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -219,6 +220,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -150,6 +150,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
|
||||
#define VERB_NOSTR_SIGN_EVENT "nostr_sign_event"
|
||||
#define VERB_NOSTR_MINE_EVENT "nostr_mine_event"
|
||||
|
||||
@@ -120,6 +120,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
|
||||
#define VERB_NOSTR_SIGN_EVENT "nostr_sign_event"
|
||||
#define VERB_NOSTR_MINE_EVENT "nostr_mine_event"
|
||||
|
||||
@@ -208,6 +208,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -217,6 +218,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -208,6 +208,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -217,6 +218,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -211,6 +211,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -220,6 +221,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -208,6 +208,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -217,6 +218,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
@@ -150,6 +150,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
#define VERB_NOSTR_GET_PUBLIC_KEY "nostr_get_public_key"
|
||||
#define VERB_NOSTR_SIGN_EVENT "nostr_sign_event"
|
||||
#define VERB_NOSTR_MINE_EVENT "nostr_mine_event"
|
||||
|
||||
@@ -208,6 +208,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
#define ENFORCE_ERR_ALGORITHM -4 /* algorithm not valid for verb */
|
||||
|
||||
@@ -217,6 +218,7 @@ const char *selector_strerror(int err);
|
||||
#define VERB_ENCAPSULATE "encapsulate"
|
||||
#define VERB_DECAPSULATE "decapsulate"
|
||||
#define VERB_DERIVE_SHARED "derive_shared_secret"
|
||||
#define VERB_DERIVE "derive"
|
||||
|
||||
|
||||
/* Known verbs */
|
||||
|
||||
Reference in New Issue
Block a user