111 lines
3.4 KiB
C
111 lines
3.4 KiB
C
/*
|
|
* get_pubkey_qrexec.c — connect to a running n_signer in another Qubes qube
|
|
* via qrexec, using the high-level nostr_signer API from nostr_core_lib.
|
|
*
|
|
* This demonstrates the new nostr_core_lib client features:
|
|
* - nostr_signer_nsigner_qrexec() — qrexec transport
|
|
* - nostr_signer_nsigner_set_nostr_index() — index-based key selection
|
|
*
|
|
* Usage:
|
|
* ./get_pubkey_qrexec <target_qube> [nostr_index]
|
|
* ./get_pubkey_qrexec nostr_signer 0
|
|
* ./get_pubkey_qrexec nostr_signer 1
|
|
*
|
|
* No auth envelope needed — qrexec identity comes from QREXEC_REMOTE_DOMAIN
|
|
* on the server side.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "nostr_common.h"
|
|
#include "nostr_signer.h"
|
|
#include "nip019.h"
|
|
|
|
int main(int argc, char **argv) {
|
|
const char *target_qube;
|
|
const char *service_name = "qubes.NsignerRpc";
|
|
int nostr_index = 0;
|
|
nostr_signer_t *signer = NULL;
|
|
char pubkey_hex[65];
|
|
unsigned char pubkey_bytes[32];
|
|
char npub[128];
|
|
int rc;
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr, "Usage: %s <target_qube> [nostr_index]\n", argv[0]);
|
|
return 1;
|
|
}
|
|
target_qube = argv[1];
|
|
if (argc > 2) {
|
|
nostr_index = atoi(argv[2]);
|
|
}
|
|
|
|
if (nostr_init() != NOSTR_SUCCESS) {
|
|
fprintf(stderr, "failed to initialize crypto subsystem\n");
|
|
return 1;
|
|
}
|
|
|
|
printf("Connecting to n_signer in qube \"%s\" via qrexec (index %d)...\n",
|
|
target_qube, nostr_index);
|
|
|
|
/* Create a high-level signer backed by qrexec transport */
|
|
signer = nostr_signer_nsigner_qrexec(target_qube, service_name, NULL, 30000);
|
|
if (signer == NULL) {
|
|
fprintf(stderr, "failed to create qrexec signer (is qrexec-client-vm available?)\n");
|
|
nostr_cleanup();
|
|
return 1;
|
|
}
|
|
|
|
/* Select key by nostr_index (NIP-06 m/44'/1237'/N'/0/0) */
|
|
if (nostr_signer_nsigner_set_nostr_index(signer, nostr_index) != NOSTR_SUCCESS) {
|
|
fprintf(stderr, "failed to set nostr_index\n");
|
|
nostr_signer_free(signer);
|
|
nostr_cleanup();
|
|
return 1;
|
|
}
|
|
|
|
/* Request the public key */
|
|
rc = nostr_signer_get_public_key(signer, pubkey_hex);
|
|
if (rc != NOSTR_SUCCESS) {
|
|
if (rc == NOSTR_ERROR_NSIGNER_INDEX_NOT_ALLOWED) {
|
|
fprintf(stderr, "DENIED: index %d is not in the signer's whitelist\n", nostr_index);
|
|
} else if (rc == NOSTR_ERROR_NSIGNER_POLICY_DENIED) {
|
|
fprintf(stderr, "DENIED: policy denied (caller not approved at signer terminal)\n");
|
|
} else {
|
|
fprintf(stderr, "get_public_key failed: error code %d\n", rc);
|
|
}
|
|
nostr_signer_free(signer);
|
|
nostr_cleanup();
|
|
return 1;
|
|
}
|
|
|
|
/* Convert hex pubkey to npub (bech32) */
|
|
{
|
|
int i;
|
|
for (i = 0; i < 32; i++) {
|
|
unsigned int byte;
|
|
if (sscanf(pubkey_hex + 2 * i, "%2x", &byte) != 1) {
|
|
fprintf(stderr, "failed to parse hex pubkey\n");
|
|
nostr_signer_free(signer);
|
|
nostr_cleanup();
|
|
return 1;
|
|
}
|
|
pubkey_bytes[i] = (unsigned char)byte;
|
|
}
|
|
}
|
|
if (nostr_key_to_bech32(pubkey_bytes, "npub", npub) != NOSTR_SUCCESS) {
|
|
fprintf(stderr, "failed to convert to npub\n");
|
|
nostr_signer_free(signer);
|
|
nostr_cleanup();
|
|
return 1;
|
|
}
|
|
|
|
printf("index %d: hex=%s npub=%s\n", nostr_index, pubkey_hex, npub);
|
|
|
|
nostr_signer_free(signer);
|
|
nostr_cleanup();
|
|
return 0;
|
|
}
|