You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
4.2 KiB
145 lines
4.2 KiB
import 'package:nostr_tools/nostr_tools.dart';
|
|
|
|
/// Represents a Nostr keypair (private and public keys).
|
|
class NostrKeyPair {
|
|
/// Private key in hex format (32 bytes, 64 hex characters).
|
|
final String privateKey;
|
|
|
|
/// Public key in hex format (32 bytes, 64 hex characters).
|
|
final String publicKey;
|
|
|
|
/// Key API instance for key operations.
|
|
static final _keyApi = KeyApi();
|
|
|
|
/// NIP-19 API instance for bech32 encoding/decoding.
|
|
static final _nip19 = Nip19();
|
|
|
|
/// Creates a [NostrKeyPair] with the provided keys.
|
|
///
|
|
/// [privateKey] - Private key in hex format.
|
|
/// [publicKey] - Public key in hex format.
|
|
NostrKeyPair({
|
|
required this.privateKey,
|
|
required this.publicKey,
|
|
});
|
|
|
|
/// Generates a new Nostr keypair using nostr_tools.
|
|
///
|
|
/// Returns a new [NostrKeyPair] with random private and public keys.
|
|
factory NostrKeyPair.generate() {
|
|
final privateKey = _keyApi.generatePrivateKey();
|
|
final publicKey = _keyApi.getPublicKey(privateKey);
|
|
|
|
return NostrKeyPair(
|
|
privateKey: privateKey,
|
|
publicKey: publicKey,
|
|
);
|
|
}
|
|
|
|
/// Creates a [NostrKeyPair] from nsec (private key in bech32 format).
|
|
///
|
|
/// [nsec] - Private key in nsec format (e.g., 'nsec1...').
|
|
///
|
|
/// Returns a [NostrKeyPair] with the decoded private key and derived public key.
|
|
///
|
|
/// Throws [FormatException] if nsec is invalid.
|
|
factory NostrKeyPair.fromNsec(String nsec) {
|
|
try {
|
|
final decoded = _nip19.decode(nsec);
|
|
if (decoded['type'] != 'nsec') {
|
|
throw FormatException('Invalid nsec format: expected "nsec" type');
|
|
}
|
|
|
|
final privateKey = decoded['data'] as String;
|
|
final publicKey = _keyApi.getPublicKey(privateKey);
|
|
|
|
return NostrKeyPair(
|
|
privateKey: privateKey,
|
|
publicKey: publicKey,
|
|
);
|
|
} catch (e) {
|
|
throw FormatException('Failed to parse nsec: $e');
|
|
}
|
|
}
|
|
|
|
/// Creates a [NostrKeyPair] from npub (public key in bech32 format).
|
|
///
|
|
/// Note: This creates a keypair with only the public key. Private key operations won't work.
|
|
///
|
|
/// [npub] - Public key in npub format (e.g., 'npub1...').
|
|
///
|
|
/// Returns a [NostrKeyPair] with the decoded public key and empty private key.
|
|
///
|
|
/// Throws [FormatException] if npub is invalid.
|
|
factory NostrKeyPair.fromNpub(String npub) {
|
|
try {
|
|
final decoded = _nip19.decode(npub);
|
|
if (decoded['type'] != 'npub') {
|
|
throw FormatException('Invalid npub format: expected "npub" type');
|
|
}
|
|
|
|
final publicKey = decoded['data'] as String;
|
|
|
|
// No private key available when importing from npub
|
|
return NostrKeyPair(
|
|
privateKey: '', // Empty private key - can't sign events
|
|
publicKey: publicKey,
|
|
);
|
|
} catch (e) {
|
|
throw FormatException('Failed to parse npub: $e');
|
|
}
|
|
}
|
|
|
|
/// Creates a [NostrKeyPair] from a hex private key.
|
|
///
|
|
/// [hexPrivateKey] - Private key in hex format (64 hex characters).
|
|
///
|
|
/// Returns a [NostrKeyPair] with the provided private key and derived public key.
|
|
factory NostrKeyPair.fromHexPrivateKey(String hexPrivateKey) {
|
|
if (hexPrivateKey.length != 64) {
|
|
throw FormatException('Invalid hex private key: expected 64 hex characters');
|
|
}
|
|
|
|
final publicKey = _keyApi.getPublicKey(hexPrivateKey);
|
|
|
|
return NostrKeyPair(
|
|
privateKey: hexPrivateKey,
|
|
publicKey: publicKey,
|
|
);
|
|
}
|
|
|
|
/// Creates a [NostrKeyPair] from a JSON map.
|
|
factory NostrKeyPair.fromJson(Map<String, dynamic> json) {
|
|
return NostrKeyPair(
|
|
privateKey: json['privateKey'] as String,
|
|
publicKey: json['publicKey'] as String,
|
|
);
|
|
}
|
|
|
|
/// Converts the [NostrKeyPair] to a JSON map.
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'privateKey': privateKey,
|
|
'publicKey': publicKey,
|
|
};
|
|
}
|
|
|
|
/// Encodes the private key to nsec format.
|
|
String toNsec() {
|
|
if (privateKey.isEmpty) {
|
|
throw StateError('Cannot encode empty private key to nsec');
|
|
}
|
|
return _nip19.nsecEncode(privateKey);
|
|
}
|
|
|
|
/// Encodes the public key to npub format.
|
|
String toNpub() {
|
|
return _nip19.npubEncode(publicKey);
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return 'NostrKeyPair(publicKey: $publicKey)';
|
|
}
|
|
}
|