This commit is contained in:
Logen
2025-09-08 19:37:12 -04:00
parent 56041b244d
commit 22589a5637
11 changed files with 440 additions and 29 deletions

View File

@@ -0,0 +1,118 @@
# nostr-keygen
A tiny commandline utility written in Python that generates an Nostr **npub** (public key) and **nsec** (private key) pair from a single file that you drop into the terminal.
> **NOTE:** The instructions below work on **macOS** and **Linux**. If youre on Windows youll need a compatible terminal (e.g. WSL, GitBash, or PowerShell with Python).
## How it works
1. **Entropy** The contents of the file you provide are read in binary mode.
2. **Hash** The data is hashed with SHA256 to produce a 32byte seed.
3. **Key generation** The seed is fed to the secp256k1 curve to create an ECDSA private key.
4. **Bech32 encoding** The private key is encoded as `nsec`; the compressed public key is encoded as `npub`.
The utility is intentionally lightweight; it has no external configuration and works on any platform with Python3.8+.
## 🛠️ Installation
### 1⃣ Install Python
- **macOS**: Use Homebrew
```bash
brew install python@3.12
```
(If you already have Python, skip this step.)
- **Linux (Ubuntu / Debianbased)**:
```bash
sudo apt-get update
sudo apt-get install python3 python3-venv
```
(Other distros may use `yum`, `dnf`, or your package manager of choice.)
- **Linux (Arch)**:
```bash
sudo pacman -S python
```
> **Tip** On macOS the `python3` binary is typically symlinked to `python`, but on many Linux systems youll need `python3` explicitly.
### 2⃣ Clone the repo
```bash
git clone https://github.com/yourgithubhandle/nostr-keygen.git
cd nostr-keygen
```
### 3⃣ Create a virtualenvironment (recommended)
```bash
python3 -m venv .venv # create a venv in the repo directory
source .venv/bin/activate # activate it (both on macOS and Linux)
```
> The virtualenvironment isolates the dependencies (`ecdsa`, `bech32`etc.) from the rest of your system.
### 4⃣ Install the tool in editable mode (development) or normally
- **Editable (work on the code as you edit it)**
```bash
pip install -e .
```
- **Normal installation**
```bash
pip install .
```
Both forms install the consolescript `nostrkeygen` into `./venv/bin`.
## 🚀 Run
```bash
# Drop any file onto the terminal prompt!
# macOS (most terminals) and many Linux terminals allow draganddrop.
nostr-keygen <filepath>
```
> Example: `nostr-keygen /tmp/randomfile.pdf`
---
### 📄 Quick test
```bash
# Create a tiny dummy file
printf "random entropy" > /tmp/dummy.bin
# Run the program
nostr-keygen /tmp/dummy.bin
```
You should see two lines outputted: an `nsec` string and an `npub` string.
## 📦 Packaging details
The project uses a `pyproject.toml` and the `[project.scripts]` entry to expose the `nostr-keygen` command. No additional packaging steps are needed for local use.
## 🔧 How the code works (quick dive)
```python
# main.py
import argparse, hashlib
from ecdsa import SigningKey, SECP256k1
from bech32 import bech32_encode, convertbits
NSEC_PREFIX, NPUB_PREFIX = "nsec", "npub"
def _to_bech32(data: bytes, hrp: str) -> str:
five_bits = convertbits(list(data), 8, 5, True)
return bech32_encode(hrp, five_bits)
# … (rest unchanged) …
```
## 📄 License
MIT.

122
README.md
View File

@@ -1,47 +1,115 @@
# README.md
# nostr-keygen
A tiny commandline utility written in Python that generates an Nostr **npub** (public key) and **nsec** (private key) pair from a single file that you drop into the terminal.
## How it works
> **NOTE:** The instructions below work on **macOS** and **Linux**. If youre on Windows youll need a compatible terminal (e.g. WSL, GitBash, or PowerShell with Python).
1. **Entropy** The contents of the file you provide are read in binary mode.
2. **Hash** The data is hashed with SHA256 to produce a 32byte seed.
3. **Key generation** The seed is fed to the secp256k1 curve to create an ECDSA private key.
4. **Bech32 encoding** The private key is encoded as `nsec`; the compressed public key is encoded as `npub`.
---
The utility is intentionally lightweight; it has no external configuration and works on any platform with Python3.8+.
## Installation
## 🚀 Run
```bash
# Clone the repo
git clone https://github.com/yourname/nostr-keygen.git
# Drop any file into the terminal prompt!
# macOS (most terminals) and many Linux terminals allow draganddrop.
nostr-keygen <filepath>
```
> The terminal prompt you see (``$`` on macOS, ``username@host:~$`` on Linux) accepts draganddrop of any file. The script will read that file path and produce key strings.
---
### 📄 Quick test
```bash
# Create a tiny dummy file
printf "random entropy" > /tmp/dummy.bin
# Run the program
nostr-keygen /tmp/dummy.bin
```
You should see two lines outputted: an `nsec` string and an `npub` string.
## 🛠️ Installation
### 1⃣ Install Python
- **macOS**: Use Homebrew
```bash
brew install python@3.12
```
(If you already have Python, skip this step.)
- **Linux (Ubuntu / Debianbased)**:
```bash
sudo apt-get update
sudo apt-get install python3 python3-venv
```
(Other distros may use `yum`, `dnf`, or your package manager of choice.)
- **Linux (Arch)**:
```bash
sudo pacman -S python
```
> **Tip** On macOS the `python3` binary is typically symlinked to `python`, but on many Linux systems youll need `python3` explicitly.
### 2⃣ Clone the repo
```bash
git clone https://github.com/yourgithubhandle/nostr-keygen.git
cd nostr-keygen
# Create a virtualenv and install deps
python3 -m venv venv
source venv/bin/activate
pip install -e . # installs the program and its deps
```
After that you can run it with:
### 3⃣ Create a virtualenvironment (recommended)
```bash
# Replace file.txt with the path to any file you want to use as entropy
nostr-keygen file.txt
python3 -m venv .venv # create a venv in the repo directory
source .venv/bin/activate # activate it (both on macOS and Linux)
```
## Using draganddrop in the terminal
> The virtualenvironment isolates thirdparty libraries (`ecdsa`, `bech32`, etc.) from the systemwide Python installation, ensuring that installing or updating them wont accidentally break other projects. It also guarantees that anyone who checks out the repo can recreate the exact same runtime environment.
On macOS (and most X11 terminals) you can simply drag a file into the terminal prompt. The terminal translates that to the files full path. For example:
### 4⃣ Install the tool in editable mode (development) or normally
```
$ nostr-keygen <dragged file>
- **Editable (work on the code as you edit it)**
```bash
pip install -e .
```
- **Normal installation**
```bash
pip install .
```
Both forms install the consolescript `nostrkeygen` into `./.venv/bin`.
## 🚫 Keystring safety
> Keep your `nsec` secret in a secure, offline location. Anyone with that string can sign Nostr events or spend Nostrbased funds.
## 🔧 How the code works (quick dive)
```python
# main.py
import argparse, hashlib
from ecdsa import SigningKey, SECP256k1
from bech32 import bech32_encode, convertbits
NSEC_PREFIX, NPUB_PREFIX = "nsec", "npub"
def _to_bech32(data: bytes, hrp: str) -> str:
five_bits = convertbits(list(data), 8, 5, True)
return bech32_encode(hrp, five_bits)
# … (rest unchanged) …
```
This will invoke the program using the path of the dropped file.
### Why the keygen algorithm matters
## License
MIT
1. **Read file in binary** We need raw entropy; reading as text would truncate or encode the file in an unexpected way. Binary mode is the most faithful representation of the files content.
2. **SHA256 hash** Provides a *deterministic* 32byte seed from any file. Different inputs yield different seeds, and the same input always yields the same seed.
3. **Create a secp256k1 signing key** The curve used by Nostr (and Bitcoin) for ECDSA. The secret key is derived directly from the seed bytes.
4. **Bech32 encoding** Nostr keys are humanreadable Bech32 strings prefixed with `nsec` or `npub`. `_to_bech32` converts 8bit byte streams to 5bit groups and encodes them.

79
build/lib/main.py Normal file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""Generate a fresh Nostr key (npub/nsec) using a file as entropy source.
Usage:
nostr-keygen <path-to-file>
The file is read in binary mode and its bytes are hashed with SHA256 to
produce the 32byte seed which is then used to generate a secp256k1
private key. The private key is hexencoded as an nsec, and the
corresponding public key is converted to a Bech32 npub. The example
uses the official Nostr prefix "nsec"/
"""
import argparse
import hashlib
import os
import sys
from ecdsa import SigningKey, SECP256k1
from bech32 import bech32_encode, convertbits
# Constants for Nostr bech32 encoding
NSEC_PREFIX = "nsec"
NPUB_PREFIX = "npub"
# convertbits helper adapted from bech32 library; using provided function for clarity
def _to_bech32(data: bytes, hrp: str) -> str:
"""Encode raw bytes into a Bech32 string with the given humanreadable part."""
# Convert 8bit bytes to 5bit groups
five_bits = convertbits(list(data), 8, 5, True)
if five_bits is None:
raise ValueError("Error converting data to 5bit groups")
return bech32_encode(hrp, five_bits)
def _entropy_to_pri_key(entropy: bytes) -> SigningKey:
"""Return an ECDSA SECP256k1 private key derived from entropy."""
# Use SHA256 of the provided entropy for deterministic key generation
seed = hashlib.sha256(entropy).digest()
return SigningKey.from_string(seed, curve=SECP256k1)
def generate_key_from_file(file_path: str) -> (str, str):
"""Return (nsec, npub) for the key derived from the file content."""
if not os.path.isfile(file_path):
raise FileNotFoundError(f"File not found: {file_path}")
with open(file_path, "rb") as f:
data = f.read()
sk = _entropy_to_pri_key(data)
vk = sk.get_verifying_key()
# Private key bytes
private_bytes = sk.to_string()
# Public key bytes, compressed (33 bytes)
public_bytes = vk.to_string("compressed")
nsec = _to_bech32(private_bytes, NSEC_PREFIX)
npub = _to_bech32(public_bytes, NPUB_PREFIX)
return nsec, npub
def main():
parser = argparse.ArgumentParser(description="Generate Nostr key pair from file entropy")
parser.add_argument("file", help="Path to file used as entropy source")
args = parser.parse_args()
try:
nsec, npub = generate_key_from_file(args.file)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
print("NSEc:", nsec)
print("NPop:", npub)
if __name__ == "__main__":
main()

View File

@@ -71,8 +71,8 @@ def main():
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
print("NSEc:", nsec)
print("NPop:", npub)
print("NSec:", nsec)
print("NPub:", npub)
if __name__ == "__main__":

View File

@@ -0,0 +1,128 @@
Metadata-Version: 2.4
Name: nostr-keygen
Version: 0.1.0
Summary: Terminal tool to generate nostr npub/nsec from file entropy
Author-email: Your Name <you@example.com>
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: ecdsa
Requires-Dist: bech32
# nostr-keygen
A tiny commandline utility written in Python that generates an Nostr **npub** (public key) and **nsec** (private key) pair from a single file that you drop into the terminal.
> **NOTE:** The instructions below work on **macOS** and **Linux**. If youre on Windows youll need a compatible terminal (e.g. WSL, GitBash, or PowerShell with Python).
## How it works
1. **Entropy** The contents of the file you provide are read in binary mode.
2. **Hash** The data is hashed with SHA256 to produce a 32byte seed.
3. **Key generation** The seed is fed to the secp256k1 curve to create an ECDSA private key.
4. **Bech32 encoding** The private key is encoded as `nsec`; the compressed public key is encoded as `npub`.
The utility is intentionally lightweight; it has no external configuration and works on any platform with Python3.8+.
## 🛠️ Installation
### 1⃣ Install Python
- **macOS**: Use Homebrew
```bash
brew install python@3.12
```
(If you already have Python, skip this step.)
- **Linux (Ubuntu / Debianbased)**:
```bash
sudo apt-get update
sudo apt-get install python3 python3-venv
```
(Other distros may use `yum`, `dnf`, or your package manager of choice.)
- **Linux (Arch)**:
```bash
sudo pacman -S python
```
> **Tip** On macOS the `python3` binary is typically symlinked to `python`, but on many Linux systems youll need `python3` explicitly.
### 2⃣ Clone the repo
```bash
git clone https://github.com/yourgithubhandle/nostr-keygen.git
cd nostr-keygen
```
### 3⃣ Create a virtualenvironment (recommended)
```bash
python3 -m venv .venv # create a venv in the repo directory
source .venv/bin/activate # activate it (both on macOS and Linux)
```
> The virtualenvironment isolates the dependencies (`ecdsa`, `bech32`etc.) from the rest of your system.
### 4⃣ Install the tool in editable mode (development) or normally
- **Editable (work on the code as you edit it)**
```bash
pip install -e .
```
- **Normal installation**
```bash
pip install .
```
Both forms install the consolescript `nostrkeygen` into `./venv/bin`.
## 🚀 Run
```bash
# Drop any file onto the terminal prompt!
# macOS (most terminals) and many Linux terminals allow draganddrop.
nostr-keygen <filepath>
```
> Example: `nostr-keygen /tmp/randomfile.pdf`
---
### 📄 Quick test
```bash
# Create a tiny dummy file
printf "random entropy" > /tmp/dummy.bin
# Run the program
nostr-keygen /tmp/dummy.bin
```
You should see two lines outputted: an `nsec` string and an `npub` string.
## 📦 Packaging details
The project uses a `pyproject.toml` and the `[project.scripts]` entry to expose the `nostr-keygen` command. No additional packaging steps are needed for local use.
## 🔧 How the code works (quick dive)
```python
# main.py
import argparse, hashlib
from ecdsa import SigningKey, SECP256k1
from bech32 import bech32_encode, convertbits
NSEC_PREFIX, NPUB_PREFIX = "nsec", "npub"
def _to_bech32(data: bytes, hrp: str) -> str:
five_bits = convertbits(list(data), 8, 5, True)
return bech32_encode(hrp, five_bits)
# … (rest unchanged) …
```
## 📄 License
MIT.

View File

@@ -0,0 +1,9 @@
README.md
main.py
pyproject.toml
nostr_keygen.egg-info/PKG-INFO
nostr_keygen.egg-info/SOURCES.txt
nostr_keygen.egg-info/dependency_links.txt
nostr_keygen.egg-info/entry_points.txt
nostr_keygen.egg-info/requires.txt
nostr_keygen.egg-info/top_level.txt

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,2 @@
[console_scripts]
nostr-keygen = main:main

View File

@@ -0,0 +1,2 @@
ecdsa
bech32

View File

@@ -0,0 +1 @@
main

View File

@@ -10,3 +10,6 @@ authors = [{name = "Your Name", email = "you@example.com"}]
readme = "README.md"
requires-python = ">=3.8"
dependencies = ["ecdsa", "bech32"]
[project.scripts]
nostr-keygen = "main:main"