@humanjavaenterprises/nostr-nsec-seedphrase
Version:
A comprehensive TypeScript library designed to make Nostr keys human-readable and easier to manage. It supports seedphrase generation, key conversions between nsec/npub and hex formats, and provides secure key management utilities.
179 lines (178 loc) • 6.23 kB
JavaScript
import { getPublicKey, nip19 } from 'nostr-tools';
import * as secp256k1 from '@noble/secp256k1';
import * as bip39 from 'bip39';
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
export class NostrSeedPhrase {
/**
* Convert a Nostr nsec private key to a BIP39 seed phrase
* @param nsec - The nsec private key to convert
* @returns Object containing the seed phrase and original nsec
*/
static nsecToSeed(nsec) {
try {
const { type, data } = nip19.decode(nsec);
if (type !== 'nsec') {
throw new Error('Invalid nsec format');
}
// Convert the hex private key to bytes and back to hex for bip39
const privateKeyHex = bytesToHex(data);
// Generate mnemonic from the private key bytes
const seedPhrase = bip39.entropyToMnemonic(privateKeyHex);
return {
seedPhrase
};
}
catch (error) {
throw new Error(`Failed to convert nsec to seed phrase: ${error.message}`);
}
}
/**
* Convert a BIP39 seed phrase to a Nostr nsec private key
* @param seedPhrase - The BIP39 mnemonic seed phrase
* @returns Object containing the nsec private key and original seed phrase
*/
static seedToNsec(seedPhrase) {
try {
if (!NostrSeedPhrase.validateSeedPhrase(seedPhrase)) {
throw new Error('Invalid mnemonic phrase');
}
// Convert mnemonic to entropy (private key hex)
const privateKeyHex = bip39.mnemonicToEntropy(seedPhrase);
// Generate nsec
const nsec = nip19.nsecEncode(hexToBytes(privateKeyHex));
// Generate public key
const publicKeyHex = getPublicKey(hexToBytes(privateKeyHex));
const npub = nip19.npubEncode(publicKeyHex);
return {
nsec,
npub,
privateKeyHex,
publicKeyHex
};
}
catch (error) {
throw new Error(`Failed to convert seed phrase to nsec: ${error.message}`);
}
}
/**
* Validate a BIP39 seed phrase
* @param seedPhrase - The seed phrase to validate
* @returns boolean indicating if the seed phrase is valid
*/
static validateSeedPhrase(seedPhrase) {
return bip39.validateMnemonic(seedPhrase);
}
/**
* Generate a new Nostr key pair with corresponding seed phrase
* @returns Object containing the new nsec private key, npub public key, and seed phrase
*/
static generateNew() {
try {
// Generate a new private key
const privateKeyBytes = secp256k1.utils.randomPrivateKey();
const privateKeyHex = bytesToHex(privateKeyBytes);
// Convert to nsec
const nsec = nip19.nsecEncode(privateKeyBytes);
// Generate public key
const publicKeyHex = getPublicKey(privateKeyBytes);
const npub = nip19.npubEncode(publicKeyHex);
// Convert private key to seed phrase
const seedPhrase = bip39.entropyToMnemonic(privateKeyHex);
return {
nsec,
npub,
seedPhrase,
privateKeyHex,
publicKeyHex
};
}
catch (error) {
throw new Error(`Failed to generate new key pair: ${error.message}`);
}
}
/**
* Create a key pair from a hex private key
* @param privateKeyHex - The hex private key to convert
* @returns Object containing the nsec, npub, and hex versions of the keys
*/
static fromHex(privateKeyHex) {
try {
// Validate hex format
if (!/^[0-9a-fA-F]{64}$/.test(privateKeyHex)) {
throw new Error('Invalid hex private key format. Must be 64 characters of hex.');
}
const nsec = nip19.nsecEncode(hexToBytes(privateKeyHex));
const publicKeyHex = getPublicKey(hexToBytes(privateKeyHex));
const npub = nip19.npubEncode(publicKeyHex);
return {
nsec,
npub,
privateKeyHex,
publicKeyHex
};
}
catch (error) {
throw new Error(`Failed to create key pair from hex: ${error.message}`);
}
}
/**
* Convert an nsec to its hex representation
* @param nsec - The nsec to convert
* @returns The hex private key
*/
static nsecToHex(nsec) {
try {
const { type, data } = nip19.decode(nsec);
if (type !== 'nsec') {
throw new Error('Invalid nsec format');
}
return bytesToHex(data);
}
catch (error) {
throw new Error(`Failed to convert nsec to hex: ${error.message}`);
}
}
/**
* Convert an npub to its hex representation
* @param npub - The npub to convert
* @returns The hex public key
*/
static npubToHex(npub) {
try {
const { type, data } = nip19.decode(npub);
if (type !== 'npub') {
throw new Error('Invalid npub format');
}
return data;
}
catch (error) {
throw new Error(`Failed to convert npub to hex: ${error.message}`);
}
}
/**
* Convert a hex public key to npub format
* @param publicKeyHex - The hex public key to convert
* @returns The npub
*/
static hexToNpub(publicKeyHex) {
try {
return nip19.npubEncode(publicKeyHex);
}
catch (error) {
throw new Error(`Failed to convert hex to npub: ${error.message}`);
}
}
/**
* Convert a hex private key to nsec format
* @param privateKeyHex - The hex private key to convert
* @returns The nsec
*/
static hexToNsec(privateKeyHex) {
try {
return nip19.nsecEncode(hexToBytes(privateKeyHex));
}
catch (error) {
throw new Error(`Failed to convert hex to nsec: ${error.message}`);
}
}
}