Why Nostr? What is Njump?
2024-07-03 00:53:04

npub1xh…uz80w on Nostr: commit ecd1ef6c1d55df8e02cda76dd3420e55514f73da Author: @RandyMcMillan ...

commit ecd1ef6c1d55df8e02cda76dd3420e55514f73da
Author: @RandyMcMillan <[email protected]>
Date: Wed Jan 31 17:11:39 2024 -0500

template/gnostr-npub:requirements.txt

diff --git a/requirements.txt b/requirements.txt
index 4d0c76a3a..ad546be9c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
virtualenv
git-archive-all
+./py/nostr
diff --git a/template/gnostr-npub b/template/gnostr-npub
new file mode 100755
index 000000000..b9cdf7180
--- /dev/null
+++ b/template/gnostr-npub
@@ -0,0 +1,162 @@
+#!/usr/bin/env python3
+"""
+ Nostr vanity pubkey generator
+
+ adapted from:
+ https://github.com/kdmukai/nostr_vanity_npub
+"""
+import datetime
+from threading import Event, Lock, Thread
+from typing import List
+from nostr.key import PrivateKey
+from importlib.metadata import version
+
+class ThreadsafeCounter:
+ """
+ Copied from SeedSigner
+ """
+ def __init__(self, initial_value: int = 0):
+ self.count = initial_value
+ self._lock = Lock()
+
+ @property
+ def cur_count(self):
+ # Reads don't require the lock
+ return self.count
+
+ def increment(self, step: int = 1):
+ # Updates must be locked
+ with self._lock:
+ self.count += step
+
+ def set_value(self, value: int):
+ with self._lock:
+ self.count = value
+
+
+
+class BruteForceThread(Thread):
+ def __init__(self, targets: List[str], bonus_targets: List[str], threadsafe_counter: ThreadsafeCounter, event: Event, include_end: bool = False):
+ super().__init__(daemon=True)
+ self.targets = targets
+ self.bonus_targets = bonus_targets
+ self.threadsafe_counter = threadsafe_counter
+ self.event = event
+ self.include_end = include_end
+
+
+ def run(self):
+ i = 0
+ while not self.event.is_set():
+ i += 1
+ pk = PrivateKey()
+ npub = pk.public_key.bech32()[5:] # Trim the "npub1" prefix
+
+ # First check the bonus targets
+ for target in self.bonus_targets:
+ if npub[:len(target)] == target or (self.include_end and npub[-1*len(target):] == target):
+ # Found one of our bonus targets!
+ print(f"BONUS TARGET: {target}:\n\t{pk.public_key.bech32()}\n\t{pk.bech32()}", flush=True)
+
+ # Now check our main targets
+ for target in self.targets:
+ if npub[:len(target)] == target or (self.include_end and npub[-1*len(target):] == target):
+ # Found our match!
+ print(f"\n{int(self.threadsafe_counter.cur_count):,} | {(time.time() - start):0.1f}s | {target} | npub1{npub}")
+ print(f"""\n\t{"*"*76}\n\tPrivate key: {pk.bech32()}\n\t{"*"*76}\n""", flush=True)
+
+ # Set the shared Event to signal to the other threads to exit
+ self.event.set()
+ break
+
+ # Nothing matched
+ if i % 1e4 == 0:
+ # Accumulate every 1e4...
+ self.threadsafe_counter.increment(1e4)
+ if self.threadsafe_counter.cur_count % 1e6 == 0:
+ # ...but update to stdout every 1e6
+ print(f"{str(datetime.datetime.now())}: Tried {int(self.threadsafe_counter.cur_count):,} npubs so far", flush=True)
+ continue
+
+
+
+
+if __name__ == "__main__":
+ import argparse
+ import time
+ from threading import Event
+ from nostr import bech32
+ __version__="v0.0.0"
+
+
+ parser = argparse.ArgumentParser(
+ description="gnostr-npub " + __version__ + \
+ "\n\nSearch for `target` in an npub such that:\n\n" + \
+ "\tnpub1[target]023456789acdefghjklmnpqrstuvwxyz",
+ formatter_class=argparse.RawTextHelpFormatter,
+ )
+
+ # Required positional arguments
+ parser.add_argument('targets', type=str,
+ help="The string(s) you're looking for (comma-separated, no spaces)")
+
+ # Optional arguments
+ parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + __version__)
+
+ # Optional arguments
+ parser.add_argument('-b', '--bonus_targets',
+ default="gn0str",
+ dest="bonus_targets",
+ help="Additional targets to search for, \nbut does not end execution when \nfound (comma-separated, no spaces)")
+
+ parser.add_argument('-e', '--include-end',
+ action="store_true",
+ default=False,
+ dest="include_end",
+ help="Also search the end of the npub")
+
+ parser.add_argument('-j', '--jobs',
+ default=2,
+ type=int,
+ dest="num_jobs",
+ help="Number of threads (default: 2)")
+
+ args = parser.parse_args()
+ targets = args.targets.lower().split(",")
+ bonus_targets = args.bonus_targets.lower().split(",") if args.bonus_targets else []
+ include_end = args.include_end
+ num_jobs = args.num_jobs
+
+ print(targets)
+ print(bonus_targets)
+
+ for target in targets + bonus_targets:
+ for i in range(0, len(target)):
+ if target[i] not in bech32.CHARSET:
+ print(f"""ERROR: "{target[i]}" is not a valid character (not in the bech32 charset)""")
+ print(f"""\tbech32 chars: {"".join(sorted(bech32.CHARSET))}""")
+ exit()
+
+ if max([len(t) for t in targets]) >= 6:
+ print(
+ "This will probably take a LONG time!\n\n" + \
+ "\tTip: CTRL-C to abort.\n\n"
+ )
+
+ start = time.time()
+ threadsafe_counter = ThreadsafeCounter()
+ event = Event()
+
+ threads = []
+ for i in range(0, num_jobs):
+ brute_force_thread = BruteForceThread(targets, bonus_targets, threadsafe_counter=threadsafe_counter, event=event, include_end=include_end)
+ brute_force_thread.start()
+ threads.append(brute_force_thread)
+
+ print(f"Initialized {num_jobs} threads")
+
+ print(f"{str(datetime.datetime.now())}: Starting")
+
+ # Block until the first thread exits; after one thread finds a match, it will set the
+ # Event and all threads will exit.
+ threads[0].join()
Author Public Key
npub1xhwtar2p9jscucsdql7ekjcxrh5quhpm8c9q3pvk725gcszye8js8uz80w