NAME

Net::Nostr::Key - Secp256k1 keypair management for Nostr

SYNOPSIS

use Net::Nostr::Key;

# Generate a new keypair
my $key = Net::Nostr::Key->new;
say $key->pubkey_npub;   # npub1...
say $key->privkey_nsec;  # nsec1...
say $key->pubkey_hex;    # 64-char hex (x-only, BIP-340)
say $key->privkey_hex;   # 64-char hex

# Save and load from file
$key->save_privkey('my_key.pem');
my $key = Net::Nostr::Key->new(privkey => 'my_key.pem');

# Create and sign an event
my $event = $key->create_event(kind => 1, content => 'hello', tags => []);

# Load from DER data
my $key = Net::Nostr::Key->new(privkey => \$der_bytes);
my $key = Net::Nostr::Key->new(pubkey  => \$der_bytes);

DESCRIPTION

Manages secp256k1 keypairs for the Nostr protocol. Supports key generation, import/export in multiple formats (hex, raw, DER, PEM, NIP-19 bech32), file-based key storage, and BIP-340 Schnorr signatures.

CONSTRUCTOR

new

my $key = Net::Nostr::Key->new;
my $key = Net::Nostr::Key->new(privkey => \$der_bytes);
my $key = Net::Nostr::Key->new(pubkey  => \$der_bytes);
my $key = Net::Nostr::Key->new(privkey => 'my_key.pem');

Without arguments, generates a new secp256k1 keypair. Pass privkey or pubkey as a scalar reference to key data (DER or PEM), or as a filename string to load from a file (PEM or DER format). When only a public key is loaded, signing operations will fail.

# Save a key to a file and load it back
$key->save_privkey('my_key.pem');
my $key = Net::Nostr::Key->new(privkey => 'my_key.pem');

METHODS

schnorr_sign

my $sig = $key->schnorr_sign($message);  # 64 raw bytes

Signs the given message using BIP-340 Schnorr signatures. Returns the raw 64-byte signature. Requires a private key to be loaded.

my $key = Net::Nostr::Key->new;
my $sig = $key->schnorr_sign('hello');
say length($sig);  # 64

privkey_loaded

my $bool = $key->privkey_loaded;

Returns true if a private key is loaded (i.e. signing is possible).

pubkey_loaded

my $bool = $key->pubkey_loaded;

Returns true if any key material is loaded (public or private).

my $key = Net::Nostr::Key->new(pubkey => \$der);
say $key->pubkey_loaded;   # 1
say $key->privkey_loaded;  # 0

pubkey_hex

my $hex = $key->pubkey_hex;  # 64-char lowercase hex

Returns the x-only public key as a 64-character hex string, suitable for use as a Nostr pubkey (BIP-340 format).

privkey_hex

my $hex = $key->privkey_hex;  # 64-char lowercase hex

Returns the private key as a 64-character hex string.

pubkey_npub

my $npub = $key->pubkey_npub;  # 'npub1...'

Returns the public key as a NIP-19 bech32-encoded npub string.

my $key = Net::Nostr::Key->new;
say $key->pubkey_npub;  # npub1...

privkey_nsec

my $nsec = $key->privkey_nsec;  # 'nsec1...'

Returns the private key as a NIP-19 bech32-encoded nsec string.

my $key = Net::Nostr::Key->new;
say $key->privkey_nsec;  # nsec1...

pubkey_raw

my $raw = $key->pubkey_raw;  # 65 bytes (04 || x || y)

Returns the uncompressed public key as raw bytes (65 bytes with 04 prefix).

privkey_raw

my $raw = $key->privkey_raw;  # 32 bytes

Returns the private key as 32 raw bytes.

pubkey_der

my $der = $key->pubkey_der;

Returns the public key in DER-encoded format. Can be passed to a new Key constructor:

my $key2 = Net::Nostr::Key->new(pubkey => \$key->pubkey_der);

privkey_der

my $der = $key->privkey_der;

Returns the private key in DER-encoded format.

my $key2 = Net::Nostr::Key->new(privkey => \$key->privkey_der);

pubkey_pem

my $pem = $key->pubkey_pem;

Returns the public key in PEM-encoded format (Base64 with header/footer).

say $key->pubkey_pem;
# -----BEGIN PUBLIC KEY-----
# ...
# -----END PUBLIC KEY-----

privkey_pem

my $pem = $key->privkey_pem;

Returns the private key in PEM-encoded format.

save_privkey

$key->save_privkey('my_key.pem');

Saves the private key to the given file path in PEM format. Croaks if no private key is loaded.

my $key = Net::Nostr::Key->new;
$key->save_privkey('my_key.pem');

# Load it back later
my $same_key = Net::Nostr::Key->new(privkey => 'my_key.pem');

save_pubkey

$key->save_pubkey('my_pubkey.pem');

Saves the public key to the given file path in PEM format.

my $key = Net::Nostr::Key->new;
$key->save_pubkey('my_pubkey.pem');

my $pub_only = Net::Nostr::Key->new(pubkey => 'my_pubkey.pem');

sign_event

my $sig_hex = $key->sign_event($event);

Signs the event's ID with BIP-340 Schnorr and sets the event's sig field. Returns the signature as a 128-character hex string.

my $event = Net::Nostr::Event->new(
    pubkey => $key->pubkey_hex, kind => 1,
    content => 'hello', tags => [],
);
$key->sign_event($event);
say $event->sig;  # 128-char hex

create_event

my $event = $key->create_event(kind => 1, content => 'hello', tags => []);

Convenience method that creates a new Net::Nostr::Event with the key's public key, signs it, and returns the signed event.

my $event = $key->create_event(
    kind    => 1,
    content => 'hello world',
    tags    => [['t', 'nostr']],
);
say $event->id;   # set
say $event->sig;  # set

constructor_keys

my @keys = Net::Nostr::Key->constructor_keys;  # ('privkey', 'pubkey')

Returns the list of valid constructor argument names. Used internally by Net::Nostr to extract key-related arguments.

SEE ALSO

Net::Nostr, Net::Nostr::Event