Keys and signers
Every event is attributed to a public key and authorized by a signature. The SDK separates the value that identifies an author from the mechanism that produces that signature:
PublicKeyidentifies an author and is safe to distribute.SecretKeyis private key material.Keyscontains a matching pair and signs directly.- a signer provides a public key and signatures without exposing its secret key.
The examples use Keys to keep signing visible. Use the signer interface when another component or device owns the
secret.
Generate and parse an identity
The following code creates a temporary identity, encodes its public key as bech32, and parses it again.
use nostr::prelude::*;
fn keys_example() -> Result<(), Box<dyn std::error::Error>> {
let keys = Keys::generate();
let public_key = keys.public_key();
let encoded = public_key.to_bech32()?;
let parsed = PublicKey::parse(&encoded)?;
assert_eq!(parsed, public_key);
println!("Public key: {encoded}");
Ok(())
}
from nostr_sdk import Event, EventBuilder, Filter, Kind, KindStandard, Keys, PublicKey, Timestamp
def keys_example() -> None:
keys = Keys.generate()
public_key = keys.public_key()
encoded = public_key.to_bech32()
parsed = PublicKey.parse(encoded)
assert parsed == public_key
print(f"Public key: {encoded}")
import {
Event,
EventBuilder,
Filter,
Kind,
KindStandard,
Keys,
PublicKey,
Timestamp,
} from "@nostrdevkit/nostr-sdk-node";
function keysExample() {
const keys = Keys.generate();
const publicKey = keys.publicKey();
const encoded = publicKey.toBech32();
const parsed = PublicKey.parse(encoded);
console.log("Public key:", parsed.toBech32());
}
import {
Event,
EventBuilder,
Filter,
Kind,
KindStandard,
Keys,
PublicKey,
Timestamp,
uniffiInitAsync,
} from "@nostrdevkit/nostr-sdk-web";
await uniffiInitAsync();
function keysExample() {
const keys = Keys.generate();
const publicKey = keys.publicKey();
const encoded = publicKey.toBech32();
const parsed = PublicKey.parse(encoded);
console.log("Public key:", parsed.toBech32());
}
import {
Event,
EventBuilder,
Filter,
Kind,
KindStandard,
Keys,
PublicKey,
Timestamp,
} from "@nostrdevkit/nostr-sdk-react-native";
export function keysExample() {
const keys = Keys.generate();
const publicKey = keys.publicKey();
const encoded = publicKey.toBech32();
const parsed = PublicKey.parse(encoded);
console.log("Public key:", parsed.toBech32());
}
import org.nostrdevkit.sdk.*
fun keysExample() {
val keys = Keys.generate()
val publicKey = keys.publicKey()
val encoded = publicKey.toBech32()
val parsed = PublicKey.parse(encoded)
check(parsed == publicKey)
println("Public key: $encoded")
}
import NostrSDK
func keysExample() throws {
let keys = Keys.generate()
let publicKey = keys.publicKey()
let encoded = try publicKey.toBech32()
let parsed = try PublicKey.parse(publicKey: encoded)
print("Public key: \(try parsed.toBech32())")
}
using Nostr.Sdk;
public static class CoreExample
{
public static void KeysExample()
{
var keys = Keys.Generate();
var publicKey = keys.PublicKey();
var encoded = publicKey.ToBech32();
var parsed = PublicKey.Parse(encoded);
Console.WriteLine($"Public key: {parsed.ToBech32()}");
}
}
Keys.generate creates a new identity every time. Use it for tests or account creation, not when an existing identity
is expected.
Public-key parsing accepts the supported hex and bech32 forms. Keep the parsed PublicKey as a typed value inside the
application and encode it only at input or output boundaries.
Keys or signer
Keys signs locally. The signer interface covers hardware, remote signers, browser extensions, and other external
implementations. In both cases the SDK flow is the same:
EventBuilder --> unsigned event --> signer --> Event --> Client
External signing can be asynchronous, rejected, or cancelled. Once signed, the resulting Event is independent of the
signer and can be passed to the client.
With an identity available, the next chapter constructs the value it signs: an event.