No description
- Kotlin 48.9%
- C 28.9%
- Cuda 19.7%
- Shell 2.5%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| .idea | ||
| gradle/wrapper | ||
| native | ||
| src | ||
| .gitignore | ||
| build.gradle.kts | ||
| CHANGELOG.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| README.md | ||
| settings.gradle.kts | ||
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
- Generate a secp256k1 private key
- Derive the compressed public key →
did:key:z...(multicodec + base58btc) - Build a DID:PLC genesis operation (DAG-CBOR encoded)
- Sign it with ECDSA (SHA-256 hash → signature)
- DAG-CBOR encode the signed operation
- SHA-256 hash → base32 encode → first 24 chars = DID identifier
- 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