No description
  • Kotlin 48.9%
  • C 28.9%
  • Cuda 19.7%
  • Shell 2.5%
Find a file
2026-03-30 21:08:32 +02:00
.forgejo/workflows Add Base58 encoding/decoding tests and initial CHANGELOG detailing new features, fixes, and optimizations 2026-03-27 16:46:14 +01:00
.idea Add hybrid GPU-based vanity DID cracker with JNI bridging 2026-03-26 22:19:41 +01:00
gradle/wrapper init 2026-03-26 19:51:16 +01:00
native Replace PdsRegistrar with new GoatCli implementation. Migrate all related functionality and consolidate logic for PDS credential management and account registration. Improve modularity and enhance error handling. 2026-03-30 21:08:32 +02:00
src Replace PdsRegistrar with new GoatCli implementation. Migrate all related functionality and consolidate logic for PDS credential management and account registration. Improve modularity and enhance error handling. 2026-03-30 21:08:32 +02:00
.gitignore init 2026-03-26 19:51:16 +01:00
build.gradle.kts Add Base58 encoding/decoding tests and initial CHANGELOG detailing new features, fixes, and optimizations 2026-03-27 16:46:14 +01:00
CHANGELOG.md Add Base58 encoding/decoding tests and initial CHANGELOG detailing new features, fixes, and optimizations 2026-03-27 16:46:14 +01:00
gradle.properties init 2026-03-26 19:51:16 +01:00
gradlew init 2026-03-26 19:51:16 +01:00
gradlew.bat init 2026-03-26 19:51:16 +01:00
README.md Add Base58 encoding/decoding tests and initial CHANGELOG detailing new features, fixes, and optimizations 2026-03-27 16:46:14 +01:00
settings.gradle.kts init 2026-03-26 19:51:16 +01:00

vanity-didplc

Generate vanity DID:PLC identifiers for the AT Protocol (Bluesky).

A DID:PLC identifier looks like did:plc:abcdefghijklmnopqrstuvwx — the last 24 characters are base32-encoded. This tool brute-forces key pairs until the resulting DID matches your desired pattern.

Performance

Engine Speed Notes
CUDA (RTX 4060) ~1.5B attempts/sec Pre-computed ECDSA nonces, word-oriented SHA-256
OpenCL GPU ~220/sec Full secp256k1 on GPU
Native (libsecp256k1) ~50K/sec Multi-threaded C with OpenSSL
JVM (BouncyCastle) ~2K/sec Pure Kotlin fallback

The tool auto-detects the fastest available engine.

Quick Start

# Build the project
./gradlew shadowJar

# Search for a prefix (JVM fallback, no native libs needed)
java -jar build/libs/*-all.jar --prefix abc

# Build native libraries for better performance
./native/build.sh

# Run with native acceleration
java --enable-native-access=ALL-UNNAMED -jar build/libs/*-all.jar --prefix abc

Usage

vanity-didplc [--prefix|--suffix|--contains|--regex] <pattern> [options]

Match modes:
  --prefix <pattern>    match start of DID identifier (default)
  --suffix <pattern>    match end of DID identifier
  --contains <pattern>  match anywhere in DID identifier
  --regex <pattern>     match identifier against a regex

Options:
  -w, --workers <n>     number of worker threads (default: all cores)
  --json                output results as JSON
  --timeout <seconds>   stop after N seconds
  --dry-run             show expected difficulty without searching
  --pds <url>           PDS host for auto-registration
  --handle <handle>     desired handle (e.g. user.bsky.social)
  --email <email>       account email
  --password <pass>     account password
  --invite-code <code>  invite code (optional)

Subcommands:
  register              register a previously generated key against a PDS

Examples

# Find a DID starting with "cool"
vanity-didplc --prefix cool

# Find a DID ending with "xyz"
vanity-didplc --suffix xyz

# Regex match
vanity-didplc --regex "^abc.*xyz$"

# JSON output for scripting
vanity-didplc --json --prefix ab

# Estimate difficulty without searching
vanity-didplc --dry-run --prefix abcdef

# Search with a 60-second timeout
vanity-didplc --timeout 60 --prefix abcde

# Generate and register in one step
vanity-didplc --prefix ab \
  --pds https://your-pds.example.com \
  --handle you.example.com \
  --email you@example.com \
  --password yourpassword

Pattern Difficulty

DID identifiers use base32 (characters: a-z, 2-7). Each character adds 32x difficulty:

Pattern Length Expected Attempts ~Time (CUDA, 1.5B/s)
1 32 instant
2 1,024 instant
3 32,768 instant
4 ~1M instant
5 ~33M <1s
6 ~1B <1s
7 ~34B ~23s
8 ~1.1T ~12min

Building Native Libraries

Requirements

  • GCC (for native CPU cracker)
  • libsecp256k1 — built from source automatically if not installed
  • OpenSSL development headers (libssl-dev / openssl-devel)
  • OpenCL headers (optional, for GPU cracker)
  • CUDA Toolkit with nvcc (optional, for CUDA cracker)

Build

# Build all available native libraries
./native/build.sh

# Libraries are placed in native/:
#   libvanitycrack.so      - CPU cracker (libsecp256k1 + OpenSSL)
#   libvanitycrackgpu.so   - OpenCL GPU cracker
#   libvanitycrackcuda.so  - CUDA GPU cracker (fastest)

System-specific notes

Arch Linux:

sudo pacman -S openssl libsecp256k1 opencl-headers cuda

Ubuntu/Debian:

sudo apt install libssl-dev libsecp256k1-dev opencl-headers nvidia-cuda-toolkit

How It Works

  1. Generate a secp256k1 private key
  2. Derive the compressed public key → did:key:z... (multicodec + base58btc)
  3. Build a DID:PLC genesis operation (DAG-CBOR encoded)
  4. Sign it with ECDSA (SHA-256 hash → signature)
  5. DAG-CBOR encode the signed operation
  6. SHA-256 hash → base32 encode → first 24 chars = DID identifier
  7. Check if did:plc:<identifier> matches the pattern

The CUDA backend optimizes this by pre-computing 100K ECDSA nonces on the CPU (the expensive elliptic curve part), then running only a 256-bit modular multiply + add per attempt on the GPU, followed by signature encoding, SHA-256, and base32 matching.

License

MIT