├── .github └── workflows │ └── build.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── main.rs ├── shader.cl └── utils ├── args.rs ├── device.rs ├── mod.rs ├── pattern.rs └── vanity_key.rs /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - master 8 | pull_request: 9 | 10 | jobs: 11 | build: 12 | strategy: 13 | matrix: 14 | os: 15 | - windows-latest 16 | - ubuntu-latest 17 | - macos-latest 18 | 19 | runs-on: ${{ matrix.os }} 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: dtolnay/rust-toolchain@stable 24 | with: 25 | toolchain: stable 26 | 27 | - uses: Swatinem/rust-cache@v2 28 | - name: Prepare OpenCL SDK 29 | shell: bash 30 | id: prepare 31 | env: 32 | GH_TOKEN: ${{ github.token }} 33 | run: | 34 | if [[ "$RUNNER_OS" == "Windows" ]]; then 35 | VERSION=$(gh release view --repo KhronosGroup/OpenCL-SDK --json tagName --jq .tagName) 36 | gh release download --repo KhronosGroup/OpenCL-SDK --pattern "OpenCL-SDK-${VERSION}-Win-x64.zip" 37 | unzip "OpenCL-SDK-${VERSION}-Win-x64.zip" 38 | cp "OpenCL-SDK-${VERSION}-Win-x64/lib/OpenCL.lib" OpenCL.lib 39 | fi 40 | if [[ "$RUNNER_OS" == "Linux" ]]; then 41 | sudo apt install opencl-headers ocl-icd-opencl-dev 42 | fi 43 | echo "rust_arch=$(rustc -vV | grep 'host: ' | cut -d ' ' -f 2)" >> $GITHUB_OUTPUT 44 | 45 | - name: Build 46 | id: build 47 | shell: bash 48 | run: | 49 | if [[ "$RUNNER_OS" == "Windows" ]]; then 50 | export RUSTFLAGS="--remap-path-prefix C:\\Users\\runneradmin=~" 51 | else 52 | export RUSTFLAGS="--remap-path-prefix $HOME=~" 53 | fi 54 | cargo build --release 55 | if [[ "$RUNNER_OS" == "Windows" ]]; then 56 | echo "executable=target/release/opencl_vanity_gpg.exe" >> $GITHUB_OUTPUT 57 | else 58 | echo "executable=target/release/opencl_vanity_gpg" >> $GITHUB_OUTPUT 59 | fi 60 | 61 | - name: Upload result 62 | uses: actions/upload-artifact@v4 63 | with: 64 | name: opencl_vanity_gpg-${{ steps.prepare.outputs.rust_arch }} 65 | path: ${{ steps.build.outputs.executable }} 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | OpenCL.lib 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "adler2" 7 | version = "2.0.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 10 | 11 | [[package]] 12 | name = "aead" 13 | version = "0.5.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" 16 | dependencies = [ 17 | "crypto-common", 18 | "generic-array", 19 | ] 20 | 21 | [[package]] 22 | name = "aes" 23 | version = "0.8.4" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" 26 | dependencies = [ 27 | "cfg-if", 28 | "cipher", 29 | "cpufeatures", 30 | ] 31 | 32 | [[package]] 33 | name = "aes-gcm" 34 | version = "0.10.3" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" 37 | dependencies = [ 38 | "aead", 39 | "aes", 40 | "cipher", 41 | "ctr", 42 | "ghash", 43 | "subtle", 44 | ] 45 | 46 | [[package]] 47 | name = "aes-kw" 48 | version = "0.2.1" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "69fa2b352dcefb5f7f3a5fb840e02665d311d878955380515e4fd50095dd3d8c" 51 | dependencies = [ 52 | "aes", 53 | ] 54 | 55 | [[package]] 56 | name = "android-tzdata" 57 | version = "0.1.1" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 60 | 61 | [[package]] 62 | name = "android_system_properties" 63 | version = "0.1.5" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 66 | dependencies = [ 67 | "libc", 68 | ] 69 | 70 | [[package]] 71 | name = "anstream" 72 | version = "0.6.18" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 75 | dependencies = [ 76 | "anstyle", 77 | "anstyle-parse", 78 | "anstyle-query", 79 | "anstyle-wincon", 80 | "colorchoice", 81 | "is_terminal_polyfill", 82 | "utf8parse", 83 | ] 84 | 85 | [[package]] 86 | name = "anstyle" 87 | version = "1.0.10" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 90 | 91 | [[package]] 92 | name = "anstyle-parse" 93 | version = "0.2.6" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 96 | dependencies = [ 97 | "utf8parse", 98 | ] 99 | 100 | [[package]] 101 | name = "anstyle-query" 102 | version = "1.1.2" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 105 | dependencies = [ 106 | "windows-sys", 107 | ] 108 | 109 | [[package]] 110 | name = "anstyle-wincon" 111 | version = "3.0.6" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" 114 | dependencies = [ 115 | "anstyle", 116 | "windows-sys", 117 | ] 118 | 119 | [[package]] 120 | name = "anyhow" 121 | version = "1.0.95" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 124 | 125 | [[package]] 126 | name = "argon2" 127 | version = "0.5.3" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" 130 | dependencies = [ 131 | "base64ct", 132 | "blake2", 133 | "cpufeatures", 134 | "password-hash", 135 | "zeroize", 136 | ] 137 | 138 | [[package]] 139 | name = "autocfg" 140 | version = "1.4.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 143 | 144 | [[package]] 145 | name = "base16ct" 146 | version = "0.2.0" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" 149 | 150 | [[package]] 151 | name = "base64" 152 | version = "0.22.1" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 155 | 156 | [[package]] 157 | name = "base64ct" 158 | version = "1.6.0" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 161 | 162 | [[package]] 163 | name = "bitfield" 164 | version = "0.14.0" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" 167 | 168 | [[package]] 169 | name = "bitflags" 170 | version = "1.3.2" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 173 | 174 | [[package]] 175 | name = "blake2" 176 | version = "0.10.6" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" 179 | dependencies = [ 180 | "digest", 181 | ] 182 | 183 | [[package]] 184 | name = "block-buffer" 185 | version = "0.10.4" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 188 | dependencies = [ 189 | "generic-array", 190 | ] 191 | 192 | [[package]] 193 | name = "block-padding" 194 | version = "0.3.3" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" 197 | dependencies = [ 198 | "generic-array", 199 | ] 200 | 201 | [[package]] 202 | name = "blowfish" 203 | version = "0.9.1" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" 206 | dependencies = [ 207 | "byteorder", 208 | "cipher", 209 | ] 210 | 211 | [[package]] 212 | name = "bstr" 213 | version = "1.11.3" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" 216 | dependencies = [ 217 | "memchr", 218 | "serde", 219 | ] 220 | 221 | [[package]] 222 | name = "buffer-redux" 223 | version = "1.0.2" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "4e8acf87c5b9f5897cd3ebb9a327f420e0cae9dd4e5c1d2e36f2c84c571a58f1" 226 | dependencies = [ 227 | "memchr", 228 | ] 229 | 230 | [[package]] 231 | name = "bumpalo" 232 | version = "3.16.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 235 | 236 | [[package]] 237 | name = "byteorder" 238 | version = "1.5.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 241 | 242 | [[package]] 243 | name = "camellia" 244 | version = "0.1.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" 247 | dependencies = [ 248 | "byteorder", 249 | "cipher", 250 | ] 251 | 252 | [[package]] 253 | name = "cast5" 254 | version = "0.11.1" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" 257 | dependencies = [ 258 | "cipher", 259 | ] 260 | 261 | [[package]] 262 | name = "cc" 263 | version = "1.2.7" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" 266 | dependencies = [ 267 | "shlex", 268 | ] 269 | 270 | [[package]] 271 | name = "cfb-mode" 272 | version = "0.8.2" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" 275 | dependencies = [ 276 | "cipher", 277 | ] 278 | 279 | [[package]] 280 | name = "cfg-if" 281 | version = "1.0.0" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 284 | 285 | [[package]] 286 | name = "chrono" 287 | version = "0.4.39" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" 290 | dependencies = [ 291 | "android-tzdata", 292 | "iana-time-zone", 293 | "num-traits 0.2.19", 294 | "windows-targets", 295 | ] 296 | 297 | [[package]] 298 | name = "cipher" 299 | version = "0.4.4" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 302 | dependencies = [ 303 | "crypto-common", 304 | "inout", 305 | ] 306 | 307 | [[package]] 308 | name = "cl-sys" 309 | version = "0.4.3" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "4febd824a957638c066180fbf72b2bed5bcee33740773f3dc59fe91f0a3e6595" 312 | dependencies = [ 313 | "libc", 314 | ] 315 | 316 | [[package]] 317 | name = "clap" 318 | version = "4.5.24" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd" 321 | dependencies = [ 322 | "clap_builder", 323 | "clap_derive", 324 | ] 325 | 326 | [[package]] 327 | name = "clap_builder" 328 | version = "4.5.24" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd" 331 | dependencies = [ 332 | "anstream", 333 | "anstyle", 334 | "clap_lex", 335 | "strsim", 336 | ] 337 | 338 | [[package]] 339 | name = "clap_derive" 340 | version = "4.5.24" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" 343 | dependencies = [ 344 | "heck", 345 | "proc-macro2", 346 | "quote", 347 | "syn", 348 | ] 349 | 350 | [[package]] 351 | name = "clap_lex" 352 | version = "0.7.4" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 355 | 356 | [[package]] 357 | name = "cmac" 358 | version = "0.7.2" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" 361 | dependencies = [ 362 | "cipher", 363 | "dbl", 364 | "digest", 365 | ] 366 | 367 | [[package]] 368 | name = "colorchoice" 369 | version = "1.0.3" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 372 | 373 | [[package]] 374 | name = "console" 375 | version = "0.15.10" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" 378 | dependencies = [ 379 | "encode_unicode", 380 | "libc", 381 | "once_cell", 382 | "unicode-width", 383 | "windows-sys", 384 | ] 385 | 386 | [[package]] 387 | name = "const-oid" 388 | version = "0.9.6" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 391 | 392 | [[package]] 393 | name = "core-foundation-sys" 394 | version = "0.8.7" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 397 | 398 | [[package]] 399 | name = "cpufeatures" 400 | version = "0.2.16" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" 403 | dependencies = [ 404 | "libc", 405 | ] 406 | 407 | [[package]] 408 | name = "crc24" 409 | version = "0.1.6" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "fd121741cf3eb82c08dd3023eb55bf2665e5f60ec20f89760cf836ae4562e6a0" 412 | 413 | [[package]] 414 | name = "crc32fast" 415 | version = "1.4.2" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 418 | dependencies = [ 419 | "cfg-if", 420 | ] 421 | 422 | [[package]] 423 | name = "crossbeam" 424 | version = "0.8.4" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" 427 | dependencies = [ 428 | "crossbeam-channel", 429 | "crossbeam-deque", 430 | "crossbeam-epoch", 431 | "crossbeam-queue", 432 | "crossbeam-utils", 433 | ] 434 | 435 | [[package]] 436 | name = "crossbeam-channel" 437 | version = "0.5.14" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" 440 | dependencies = [ 441 | "crossbeam-utils", 442 | ] 443 | 444 | [[package]] 445 | name = "crossbeam-deque" 446 | version = "0.8.6" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 449 | dependencies = [ 450 | "crossbeam-epoch", 451 | "crossbeam-utils", 452 | ] 453 | 454 | [[package]] 455 | name = "crossbeam-epoch" 456 | version = "0.9.18" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 459 | dependencies = [ 460 | "crossbeam-utils", 461 | ] 462 | 463 | [[package]] 464 | name = "crossbeam-queue" 465 | version = "0.3.12" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" 468 | dependencies = [ 469 | "crossbeam-utils", 470 | ] 471 | 472 | [[package]] 473 | name = "crossbeam-utils" 474 | version = "0.8.21" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 477 | 478 | [[package]] 479 | name = "crypto-bigint" 480 | version = "0.5.5" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" 483 | dependencies = [ 484 | "generic-array", 485 | "rand_core 0.6.4", 486 | "subtle", 487 | "zeroize", 488 | ] 489 | 490 | [[package]] 491 | name = "crypto-common" 492 | version = "0.1.6" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 495 | dependencies = [ 496 | "generic-array", 497 | "rand_core 0.6.4", 498 | "typenum", 499 | ] 500 | 501 | [[package]] 502 | name = "ctr" 503 | version = "0.9.2" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" 506 | dependencies = [ 507 | "cipher", 508 | ] 509 | 510 | [[package]] 511 | name = "curve25519-dalek" 512 | version = "4.1.3" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" 515 | dependencies = [ 516 | "cfg-if", 517 | "cpufeatures", 518 | "curve25519-dalek-derive", 519 | "digest", 520 | "fiat-crypto 0.2.9", 521 | "rustc_version", 522 | "subtle", 523 | "zeroize", 524 | ] 525 | 526 | [[package]] 527 | name = "curve25519-dalek-derive" 528 | version = "0.1.1" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" 531 | dependencies = [ 532 | "proc-macro2", 533 | "quote", 534 | "syn", 535 | ] 536 | 537 | [[package]] 538 | name = "darling" 539 | version = "0.20.10" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 542 | dependencies = [ 543 | "darling_core", 544 | "darling_macro", 545 | ] 546 | 547 | [[package]] 548 | name = "darling_core" 549 | version = "0.20.10" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 552 | dependencies = [ 553 | "fnv", 554 | "ident_case", 555 | "proc-macro2", 556 | "quote", 557 | "strsim", 558 | "syn", 559 | ] 560 | 561 | [[package]] 562 | name = "darling_macro" 563 | version = "0.20.10" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 566 | dependencies = [ 567 | "darling_core", 568 | "quote", 569 | "syn", 570 | ] 571 | 572 | [[package]] 573 | name = "dbl" 574 | version = "0.3.2" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" 577 | dependencies = [ 578 | "generic-array", 579 | ] 580 | 581 | [[package]] 582 | name = "der" 583 | version = "0.7.9" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" 586 | dependencies = [ 587 | "const-oid", 588 | "pem-rfc7468", 589 | "zeroize", 590 | ] 591 | 592 | [[package]] 593 | name = "derive_builder" 594 | version = "0.20.2" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" 597 | dependencies = [ 598 | "derive_builder_macro", 599 | ] 600 | 601 | [[package]] 602 | name = "derive_builder_core" 603 | version = "0.20.2" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" 606 | dependencies = [ 607 | "darling", 608 | "proc-macro2", 609 | "quote", 610 | "syn", 611 | ] 612 | 613 | [[package]] 614 | name = "derive_builder_macro" 615 | version = "0.20.2" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" 618 | dependencies = [ 619 | "derive_builder_core", 620 | "syn", 621 | ] 622 | 623 | [[package]] 624 | name = "derive_more" 625 | version = "1.0.0" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" 628 | dependencies = [ 629 | "derive_more-impl", 630 | ] 631 | 632 | [[package]] 633 | name = "derive_more-impl" 634 | version = "1.0.0" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" 637 | dependencies = [ 638 | "proc-macro2", 639 | "quote", 640 | "syn", 641 | "unicode-xid", 642 | ] 643 | 644 | [[package]] 645 | name = "des" 646 | version = "0.8.1" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" 649 | dependencies = [ 650 | "cipher", 651 | ] 652 | 653 | [[package]] 654 | name = "digest" 655 | version = "0.10.7" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 658 | dependencies = [ 659 | "block-buffer", 660 | "const-oid", 661 | "crypto-common", 662 | "subtle", 663 | ] 664 | 665 | [[package]] 666 | name = "dsa" 667 | version = "0.6.3" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "48bc224a9084ad760195584ce5abb3c2c34a225fa312a128ad245a6b412b7689" 670 | dependencies = [ 671 | "digest", 672 | "num-bigint-dig", 673 | "num-traits 0.2.19", 674 | "pkcs8", 675 | "rfc6979", 676 | "sha2", 677 | "signature", 678 | "zeroize", 679 | ] 680 | 681 | [[package]] 682 | name = "eax" 683 | version = "0.5.0" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "9954fabd903b82b9d7a68f65f97dc96dd9ad368e40ccc907a7c19d53e6bfac28" 686 | dependencies = [ 687 | "aead", 688 | "cipher", 689 | "cmac", 690 | "ctr", 691 | "subtle", 692 | ] 693 | 694 | [[package]] 695 | name = "ecdsa" 696 | version = "0.16.9" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" 699 | dependencies = [ 700 | "der", 701 | "digest", 702 | "elliptic-curve", 703 | "rfc6979", 704 | "signature", 705 | "spki", 706 | ] 707 | 708 | [[package]] 709 | name = "ed25519" 710 | version = "2.2.3" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" 713 | dependencies = [ 714 | "pkcs8", 715 | "signature", 716 | ] 717 | 718 | [[package]] 719 | name = "ed25519-dalek" 720 | version = "2.1.1" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" 723 | dependencies = [ 724 | "curve25519-dalek", 725 | "ed25519", 726 | "serde", 727 | "sha2", 728 | "subtle", 729 | "zeroize", 730 | ] 731 | 732 | [[package]] 733 | name = "ed448-goldilocks" 734 | version = "0.7.2" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "87b5fa9e9e3dd5fe1369f380acd3dcdfa766dbd0a1cd5b048fb40e38a6a78e79" 737 | dependencies = [ 738 | "fiat-crypto 0.1.20", 739 | "hex", 740 | "subtle", 741 | ] 742 | 743 | [[package]] 744 | name = "elliptic-curve" 745 | version = "0.13.8" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" 748 | dependencies = [ 749 | "base16ct", 750 | "crypto-bigint", 751 | "digest", 752 | "ff", 753 | "generic-array", 754 | "group", 755 | "hkdf", 756 | "pem-rfc7468", 757 | "pkcs8", 758 | "rand_core 0.6.4", 759 | "sec1", 760 | "subtle", 761 | "zeroize", 762 | ] 763 | 764 | [[package]] 765 | name = "encode_unicode" 766 | version = "1.0.0" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" 769 | 770 | [[package]] 771 | name = "enum_primitive" 772 | version = "0.1.1" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" 775 | dependencies = [ 776 | "num-traits 0.1.43", 777 | ] 778 | 779 | [[package]] 780 | name = "env_filter" 781 | version = "0.1.3" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" 784 | dependencies = [ 785 | "log", 786 | ] 787 | 788 | [[package]] 789 | name = "env_logger" 790 | version = "0.11.6" 791 | source = "registry+https://github.com/rust-lang/crates.io-index" 792 | checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" 793 | dependencies = [ 794 | "anstream", 795 | "anstyle", 796 | "env_filter", 797 | "humantime", 798 | "log", 799 | ] 800 | 801 | [[package]] 802 | name = "equivalent" 803 | version = "1.0.1" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 806 | 807 | [[package]] 808 | name = "ff" 809 | version = "0.13.0" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" 812 | dependencies = [ 813 | "rand_core 0.6.4", 814 | "subtle", 815 | ] 816 | 817 | [[package]] 818 | name = "fiat-crypto" 819 | version = "0.1.20" 820 | source = "registry+https://github.com/rust-lang/crates.io-index" 821 | checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" 822 | 823 | [[package]] 824 | name = "fiat-crypto" 825 | version = "0.2.9" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" 828 | 829 | [[package]] 830 | name = "flate2" 831 | version = "1.0.35" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" 834 | dependencies = [ 835 | "crc32fast", 836 | "miniz_oxide", 837 | ] 838 | 839 | [[package]] 840 | name = "fnv" 841 | version = "1.0.7" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 844 | 845 | [[package]] 846 | name = "futures" 847 | version = "0.1.31" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" 850 | 851 | [[package]] 852 | name = "generic-array" 853 | version = "0.14.7" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 856 | dependencies = [ 857 | "typenum", 858 | "version_check", 859 | "zeroize", 860 | ] 861 | 862 | [[package]] 863 | name = "getrandom" 864 | version = "0.2.15" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 867 | dependencies = [ 868 | "cfg-if", 869 | "libc", 870 | "wasi", 871 | ] 872 | 873 | [[package]] 874 | name = "ghash" 875 | version = "0.5.1" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" 878 | dependencies = [ 879 | "opaque-debug", 880 | "polyval", 881 | ] 882 | 883 | [[package]] 884 | name = "group" 885 | version = "0.13.0" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" 888 | dependencies = [ 889 | "ff", 890 | "rand_core 0.6.4", 891 | "subtle", 892 | ] 893 | 894 | [[package]] 895 | name = "hashbrown" 896 | version = "0.15.2" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 899 | 900 | [[package]] 901 | name = "heck" 902 | version = "0.5.0" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 905 | 906 | [[package]] 907 | name = "hex" 908 | version = "0.4.3" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 911 | 912 | [[package]] 913 | name = "hkdf" 914 | version = "0.12.4" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 917 | dependencies = [ 918 | "hmac", 919 | ] 920 | 921 | [[package]] 922 | name = "hmac" 923 | version = "0.12.1" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 926 | dependencies = [ 927 | "digest", 928 | ] 929 | 930 | [[package]] 931 | name = "humantime" 932 | version = "2.1.0" 933 | source = "registry+https://github.com/rust-lang/crates.io-index" 934 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 935 | 936 | [[package]] 937 | name = "iana-time-zone" 938 | version = "0.1.61" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 941 | dependencies = [ 942 | "android_system_properties", 943 | "core-foundation-sys", 944 | "iana-time-zone-haiku", 945 | "js-sys", 946 | "wasm-bindgen", 947 | "windows-core", 948 | ] 949 | 950 | [[package]] 951 | name = "iana-time-zone-haiku" 952 | version = "0.1.2" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 955 | dependencies = [ 956 | "cc", 957 | ] 958 | 959 | [[package]] 960 | name = "idea" 961 | version = "0.5.1" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" 964 | dependencies = [ 965 | "cipher", 966 | ] 967 | 968 | [[package]] 969 | name = "ident_case" 970 | version = "1.0.1" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 973 | 974 | [[package]] 975 | name = "indexmap" 976 | version = "2.7.0" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" 979 | dependencies = [ 980 | "equivalent", 981 | "hashbrown", 982 | ] 983 | 984 | [[package]] 985 | name = "indicatif" 986 | version = "0.17.9" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" 989 | dependencies = [ 990 | "console", 991 | "number_prefix", 992 | "portable-atomic", 993 | "unicode-width", 994 | "web-time", 995 | ] 996 | 997 | [[package]] 998 | name = "indicatif-log-bridge" 999 | version = "0.2.3" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "63703cf9069b85dbe6fe26e1c5230d013dee99d3559cd3d02ba39e099ef7ab02" 1002 | dependencies = [ 1003 | "indicatif", 1004 | "log", 1005 | ] 1006 | 1007 | [[package]] 1008 | name = "inout" 1009 | version = "0.1.3" 1010 | source = "registry+https://github.com/rust-lang/crates.io-index" 1011 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 1012 | dependencies = [ 1013 | "generic-array", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "is_terminal_polyfill" 1018 | version = "1.70.1" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1021 | 1022 | [[package]] 1023 | name = "iter-read" 1024 | version = "1.1.0" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "071ed4cc1afd86650602c7b11aa2e1ce30762a1c27193201cb5cee9c6ebb1294" 1027 | 1028 | [[package]] 1029 | name = "js-sys" 1030 | version = "0.3.76" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" 1033 | dependencies = [ 1034 | "once_cell", 1035 | "wasm-bindgen", 1036 | ] 1037 | 1038 | [[package]] 1039 | name = "k256" 1040 | version = "0.13.4" 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" 1042 | checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" 1043 | dependencies = [ 1044 | "cfg-if", 1045 | "ecdsa", 1046 | "elliptic-curve", 1047 | "once_cell", 1048 | "sha2", 1049 | "signature", 1050 | ] 1051 | 1052 | [[package]] 1053 | name = "keccak" 1054 | version = "0.1.5" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" 1057 | dependencies = [ 1058 | "cpufeatures", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "lazy_static" 1063 | version = "1.5.0" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1066 | dependencies = [ 1067 | "spin", 1068 | ] 1069 | 1070 | [[package]] 1071 | name = "libc" 1072 | version = "0.2.169" 1073 | source = "registry+https://github.com/rust-lang/crates.io-index" 1074 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 1075 | 1076 | [[package]] 1077 | name = "libm" 1078 | version = "0.2.11" 1079 | source = "registry+https://github.com/rust-lang/crates.io-index" 1080 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 1081 | 1082 | [[package]] 1083 | name = "log" 1084 | version = "0.4.22" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 1087 | 1088 | [[package]] 1089 | name = "md-5" 1090 | version = "0.10.6" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1093 | dependencies = [ 1094 | "cfg-if", 1095 | "digest", 1096 | ] 1097 | 1098 | [[package]] 1099 | name = "memchr" 1100 | version = "2.7.4" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1103 | 1104 | [[package]] 1105 | name = "minimal-lexical" 1106 | version = "0.2.1" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1109 | 1110 | [[package]] 1111 | name = "miniz_oxide" 1112 | version = "0.8.2" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" 1115 | dependencies = [ 1116 | "adler2", 1117 | ] 1118 | 1119 | [[package]] 1120 | name = "nodrop" 1121 | version = "0.1.14" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" 1124 | 1125 | [[package]] 1126 | name = "nom" 1127 | version = "7.1.3" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1130 | dependencies = [ 1131 | "memchr", 1132 | "minimal-lexical", 1133 | ] 1134 | 1135 | [[package]] 1136 | name = "num-bigint-dig" 1137 | version = "0.8.4" 1138 | source = "registry+https://github.com/rust-lang/crates.io-index" 1139 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 1140 | dependencies = [ 1141 | "byteorder", 1142 | "lazy_static", 1143 | "libm", 1144 | "num-integer", 1145 | "num-iter", 1146 | "num-traits 0.2.19", 1147 | "rand", 1148 | "serde", 1149 | "smallvec", 1150 | "zeroize", 1151 | ] 1152 | 1153 | [[package]] 1154 | name = "num-complex" 1155 | version = "0.4.6" 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" 1157 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" 1158 | dependencies = [ 1159 | "num-traits 0.2.19", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "num-integer" 1164 | version = "0.1.46" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 1167 | dependencies = [ 1168 | "num-traits 0.2.19", 1169 | ] 1170 | 1171 | [[package]] 1172 | name = "num-iter" 1173 | version = "0.1.45" 1174 | source = "registry+https://github.com/rust-lang/crates.io-index" 1175 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 1176 | dependencies = [ 1177 | "autocfg", 1178 | "num-integer", 1179 | "num-traits 0.2.19", 1180 | ] 1181 | 1182 | [[package]] 1183 | name = "num-traits" 1184 | version = "0.1.43" 1185 | source = "registry+https://github.com/rust-lang/crates.io-index" 1186 | checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" 1187 | dependencies = [ 1188 | "num-traits 0.2.19", 1189 | ] 1190 | 1191 | [[package]] 1192 | name = "num-traits" 1193 | version = "0.2.19" 1194 | source = "registry+https://github.com/rust-lang/crates.io-index" 1195 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1196 | dependencies = [ 1197 | "autocfg", 1198 | "libm", 1199 | ] 1200 | 1201 | [[package]] 1202 | name = "num_enum" 1203 | version = "0.7.3" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" 1206 | dependencies = [ 1207 | "num_enum_derive", 1208 | ] 1209 | 1210 | [[package]] 1211 | name = "num_enum_derive" 1212 | version = "0.7.3" 1213 | source = "registry+https://github.com/rust-lang/crates.io-index" 1214 | checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" 1215 | dependencies = [ 1216 | "proc-macro-crate", 1217 | "proc-macro2", 1218 | "quote", 1219 | "syn", 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "number_prefix" 1224 | version = "0.4.0" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 1227 | 1228 | [[package]] 1229 | name = "ocb3" 1230 | version = "0.1.0" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | checksum = "c196e0276c471c843dd5777e7543a36a298a4be942a2a688d8111cd43390dedb" 1233 | dependencies = [ 1234 | "aead", 1235 | "cipher", 1236 | "ctr", 1237 | "subtle", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "ocl" 1242 | version = "0.19.7" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "4297afb442d411793e4e24ee5a2977d15b6c95c743418f1c0ce0a2397d7ec8a3" 1245 | dependencies = [ 1246 | "futures", 1247 | "nodrop", 1248 | "num-traits 0.2.19", 1249 | "ocl-core", 1250 | "qutex", 1251 | "thiserror", 1252 | ] 1253 | 1254 | [[package]] 1255 | name = "ocl-core" 1256 | version = "0.11.5" 1257 | source = "registry+https://github.com/rust-lang/crates.io-index" 1258 | checksum = "c145dd9f205b86611a5df15eb89517417b03005441cf6cec245c65a4b9248c52" 1259 | dependencies = [ 1260 | "bitflags", 1261 | "cl-sys", 1262 | "enum_primitive", 1263 | "num-complex", 1264 | "num-traits 0.2.19", 1265 | "ocl-core-vector", 1266 | "rustc_version", 1267 | "thiserror", 1268 | ] 1269 | 1270 | [[package]] 1271 | name = "ocl-core-vector" 1272 | version = "0.1.1" 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" 1274 | checksum = "f562279e046ca160aeed5eaf6f7c4eb9fa56cb8fd9d038dbdbf56225caeb8074" 1275 | dependencies = [ 1276 | "num-traits 0.2.19", 1277 | ] 1278 | 1279 | [[package]] 1280 | name = "once_cell" 1281 | version = "1.20.2" 1282 | source = "registry+https://github.com/rust-lang/crates.io-index" 1283 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 1284 | 1285 | [[package]] 1286 | name = "opaque-debug" 1287 | version = "0.3.1" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" 1290 | 1291 | [[package]] 1292 | name = "opencl_vanity_gpg" 1293 | version = "0.1.0" 1294 | dependencies = [ 1295 | "anyhow", 1296 | "byteorder", 1297 | "chrono", 1298 | "clap", 1299 | "env_logger", 1300 | "hex", 1301 | "indicatif", 1302 | "indicatif-log-bridge", 1303 | "log", 1304 | "ocl", 1305 | "pgp", 1306 | "rand", 1307 | "smallvec", 1308 | ] 1309 | 1310 | [[package]] 1311 | name = "p256" 1312 | version = "0.13.2" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" 1315 | dependencies = [ 1316 | "ecdsa", 1317 | "elliptic-curve", 1318 | "primeorder", 1319 | "sha2", 1320 | ] 1321 | 1322 | [[package]] 1323 | name = "p384" 1324 | version = "0.13.0" 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" 1326 | checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" 1327 | dependencies = [ 1328 | "ecdsa", 1329 | "elliptic-curve", 1330 | "primeorder", 1331 | "sha2", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "p521" 1336 | version = "0.13.3" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" 1339 | dependencies = [ 1340 | "base16ct", 1341 | "ecdsa", 1342 | "elliptic-curve", 1343 | "primeorder", 1344 | "rand_core 0.6.4", 1345 | "sha2", 1346 | ] 1347 | 1348 | [[package]] 1349 | name = "password-hash" 1350 | version = "0.5.0" 1351 | source = "registry+https://github.com/rust-lang/crates.io-index" 1352 | checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" 1353 | dependencies = [ 1354 | "base64ct", 1355 | "rand_core 0.6.4", 1356 | "subtle", 1357 | ] 1358 | 1359 | [[package]] 1360 | name = "pem-rfc7468" 1361 | version = "0.7.0" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 1364 | dependencies = [ 1365 | "base64ct", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "pgp" 1370 | version = "0.14.2" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "1877a97fd422433220ad272eb008ec55691944b1200e9eb204e3cb2cb69d34e9" 1373 | dependencies = [ 1374 | "aes", 1375 | "aes-gcm", 1376 | "aes-kw", 1377 | "argon2", 1378 | "base64", 1379 | "bitfield", 1380 | "block-padding", 1381 | "blowfish", 1382 | "bstr", 1383 | "buffer-redux", 1384 | "byteorder", 1385 | "camellia", 1386 | "cast5", 1387 | "cfb-mode", 1388 | "chrono", 1389 | "cipher", 1390 | "const-oid", 1391 | "crc24", 1392 | "curve25519-dalek", 1393 | "derive_builder", 1394 | "derive_more", 1395 | "des", 1396 | "digest", 1397 | "dsa", 1398 | "eax", 1399 | "ecdsa", 1400 | "ed25519-dalek", 1401 | "elliptic-curve", 1402 | "flate2", 1403 | "generic-array", 1404 | "hex", 1405 | "hkdf", 1406 | "idea", 1407 | "iter-read", 1408 | "k256", 1409 | "log", 1410 | "md-5", 1411 | "nom", 1412 | "num-bigint-dig", 1413 | "num-traits 0.2.19", 1414 | "num_enum", 1415 | "ocb3", 1416 | "p256", 1417 | "p384", 1418 | "p521", 1419 | "rand", 1420 | "ripemd", 1421 | "rsa", 1422 | "sha1", 1423 | "sha1-checked", 1424 | "sha2", 1425 | "sha3", 1426 | "signature", 1427 | "smallvec", 1428 | "thiserror", 1429 | "twofish", 1430 | "x25519-dalek", 1431 | "x448", 1432 | "zeroize", 1433 | ] 1434 | 1435 | [[package]] 1436 | name = "pkcs1" 1437 | version = "0.7.5" 1438 | source = "registry+https://github.com/rust-lang/crates.io-index" 1439 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 1440 | dependencies = [ 1441 | "der", 1442 | "pkcs8", 1443 | "spki", 1444 | ] 1445 | 1446 | [[package]] 1447 | name = "pkcs8" 1448 | version = "0.10.2" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1451 | dependencies = [ 1452 | "der", 1453 | "spki", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "polyval" 1458 | version = "0.6.2" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" 1461 | dependencies = [ 1462 | "cfg-if", 1463 | "cpufeatures", 1464 | "opaque-debug", 1465 | "universal-hash", 1466 | ] 1467 | 1468 | [[package]] 1469 | name = "portable-atomic" 1470 | version = "1.10.0" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" 1473 | 1474 | [[package]] 1475 | name = "ppv-lite86" 1476 | version = "0.2.20" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 1479 | dependencies = [ 1480 | "zerocopy", 1481 | ] 1482 | 1483 | [[package]] 1484 | name = "primeorder" 1485 | version = "0.13.6" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" 1488 | dependencies = [ 1489 | "elliptic-curve", 1490 | ] 1491 | 1492 | [[package]] 1493 | name = "proc-macro-crate" 1494 | version = "3.2.0" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" 1497 | dependencies = [ 1498 | "toml_edit", 1499 | ] 1500 | 1501 | [[package]] 1502 | name = "proc-macro2" 1503 | version = "1.0.92" 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" 1505 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 1506 | dependencies = [ 1507 | "unicode-ident", 1508 | ] 1509 | 1510 | [[package]] 1511 | name = "quote" 1512 | version = "1.0.38" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 1515 | dependencies = [ 1516 | "proc-macro2", 1517 | ] 1518 | 1519 | [[package]] 1520 | name = "qutex" 1521 | version = "0.2.6" 1522 | source = "registry+https://github.com/rust-lang/crates.io-index" 1523 | checksum = "11778238e7d8b0e3ca62033fdc69e01ef5cdb08809cdc2398b2ce5ec873a1757" 1524 | dependencies = [ 1525 | "crossbeam", 1526 | "futures", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "rand" 1531 | version = "0.8.5" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1534 | dependencies = [ 1535 | "libc", 1536 | "rand_chacha", 1537 | "rand_core 0.6.4", 1538 | ] 1539 | 1540 | [[package]] 1541 | name = "rand_chacha" 1542 | version = "0.3.1" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1545 | dependencies = [ 1546 | "ppv-lite86", 1547 | "rand_core 0.6.4", 1548 | ] 1549 | 1550 | [[package]] 1551 | name = "rand_core" 1552 | version = "0.5.1" 1553 | source = "registry+https://github.com/rust-lang/crates.io-index" 1554 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1555 | 1556 | [[package]] 1557 | name = "rand_core" 1558 | version = "0.6.4" 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" 1560 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1561 | dependencies = [ 1562 | "getrandom", 1563 | ] 1564 | 1565 | [[package]] 1566 | name = "rfc6979" 1567 | version = "0.4.0" 1568 | source = "registry+https://github.com/rust-lang/crates.io-index" 1569 | checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" 1570 | dependencies = [ 1571 | "hmac", 1572 | "subtle", 1573 | ] 1574 | 1575 | [[package]] 1576 | name = "ripemd" 1577 | version = "0.1.3" 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" 1579 | checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" 1580 | dependencies = [ 1581 | "digest", 1582 | ] 1583 | 1584 | [[package]] 1585 | name = "rsa" 1586 | version = "0.9.7" 1587 | source = "registry+https://github.com/rust-lang/crates.io-index" 1588 | checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" 1589 | dependencies = [ 1590 | "const-oid", 1591 | "digest", 1592 | "num-bigint-dig", 1593 | "num-integer", 1594 | "num-traits 0.2.19", 1595 | "pkcs1", 1596 | "pkcs8", 1597 | "rand_core 0.6.4", 1598 | "signature", 1599 | "spki", 1600 | "subtle", 1601 | "zeroize", 1602 | ] 1603 | 1604 | [[package]] 1605 | name = "rustc_version" 1606 | version = "0.4.1" 1607 | source = "registry+https://github.com/rust-lang/crates.io-index" 1608 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 1609 | dependencies = [ 1610 | "semver", 1611 | ] 1612 | 1613 | [[package]] 1614 | name = "sec1" 1615 | version = "0.7.3" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" 1618 | dependencies = [ 1619 | "base16ct", 1620 | "der", 1621 | "generic-array", 1622 | "pkcs8", 1623 | "subtle", 1624 | "zeroize", 1625 | ] 1626 | 1627 | [[package]] 1628 | name = "semver" 1629 | version = "1.0.24" 1630 | source = "registry+https://github.com/rust-lang/crates.io-index" 1631 | checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" 1632 | 1633 | [[package]] 1634 | name = "serde" 1635 | version = "1.0.217" 1636 | source = "registry+https://github.com/rust-lang/crates.io-index" 1637 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 1638 | dependencies = [ 1639 | "serde_derive", 1640 | ] 1641 | 1642 | [[package]] 1643 | name = "serde_derive" 1644 | version = "1.0.217" 1645 | source = "registry+https://github.com/rust-lang/crates.io-index" 1646 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 1647 | dependencies = [ 1648 | "proc-macro2", 1649 | "quote", 1650 | "syn", 1651 | ] 1652 | 1653 | [[package]] 1654 | name = "sha1" 1655 | version = "0.10.6" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 1658 | dependencies = [ 1659 | "cfg-if", 1660 | "cpufeatures", 1661 | "digest", 1662 | ] 1663 | 1664 | [[package]] 1665 | name = "sha1-checked" 1666 | version = "0.10.0" 1667 | source = "registry+https://github.com/rust-lang/crates.io-index" 1668 | checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" 1669 | dependencies = [ 1670 | "digest", 1671 | "sha1", 1672 | "zeroize", 1673 | ] 1674 | 1675 | [[package]] 1676 | name = "sha2" 1677 | version = "0.10.8" 1678 | source = "registry+https://github.com/rust-lang/crates.io-index" 1679 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 1680 | dependencies = [ 1681 | "cfg-if", 1682 | "cpufeatures", 1683 | "digest", 1684 | ] 1685 | 1686 | [[package]] 1687 | name = "sha3" 1688 | version = "0.10.8" 1689 | source = "registry+https://github.com/rust-lang/crates.io-index" 1690 | checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" 1691 | dependencies = [ 1692 | "digest", 1693 | "keccak", 1694 | ] 1695 | 1696 | [[package]] 1697 | name = "shlex" 1698 | version = "1.3.0" 1699 | source = "registry+https://github.com/rust-lang/crates.io-index" 1700 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1701 | 1702 | [[package]] 1703 | name = "signature" 1704 | version = "2.2.0" 1705 | source = "registry+https://github.com/rust-lang/crates.io-index" 1706 | checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 1707 | dependencies = [ 1708 | "digest", 1709 | "rand_core 0.6.4", 1710 | ] 1711 | 1712 | [[package]] 1713 | name = "smallvec" 1714 | version = "1.13.2" 1715 | source = "registry+https://github.com/rust-lang/crates.io-index" 1716 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 1717 | 1718 | [[package]] 1719 | name = "spin" 1720 | version = "0.9.8" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1723 | 1724 | [[package]] 1725 | name = "spki" 1726 | version = "0.7.3" 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" 1728 | checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 1729 | dependencies = [ 1730 | "base64ct", 1731 | "der", 1732 | ] 1733 | 1734 | [[package]] 1735 | name = "strsim" 1736 | version = "0.11.1" 1737 | source = "registry+https://github.com/rust-lang/crates.io-index" 1738 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1739 | 1740 | [[package]] 1741 | name = "subtle" 1742 | version = "2.6.1" 1743 | source = "registry+https://github.com/rust-lang/crates.io-index" 1744 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1745 | 1746 | [[package]] 1747 | name = "syn" 1748 | version = "2.0.95" 1749 | source = "registry+https://github.com/rust-lang/crates.io-index" 1750 | checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" 1751 | dependencies = [ 1752 | "proc-macro2", 1753 | "quote", 1754 | "unicode-ident", 1755 | ] 1756 | 1757 | [[package]] 1758 | name = "thiserror" 1759 | version = "1.0.69" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1762 | dependencies = [ 1763 | "thiserror-impl", 1764 | ] 1765 | 1766 | [[package]] 1767 | name = "thiserror-impl" 1768 | version = "1.0.69" 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" 1770 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1771 | dependencies = [ 1772 | "proc-macro2", 1773 | "quote", 1774 | "syn", 1775 | ] 1776 | 1777 | [[package]] 1778 | name = "toml_datetime" 1779 | version = "0.6.8" 1780 | source = "registry+https://github.com/rust-lang/crates.io-index" 1781 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 1782 | 1783 | [[package]] 1784 | name = "toml_edit" 1785 | version = "0.22.22" 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" 1787 | checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" 1788 | dependencies = [ 1789 | "indexmap", 1790 | "toml_datetime", 1791 | "winnow", 1792 | ] 1793 | 1794 | [[package]] 1795 | name = "twofish" 1796 | version = "0.7.1" 1797 | source = "registry+https://github.com/rust-lang/crates.io-index" 1798 | checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" 1799 | dependencies = [ 1800 | "cipher", 1801 | ] 1802 | 1803 | [[package]] 1804 | name = "typenum" 1805 | version = "1.17.0" 1806 | source = "registry+https://github.com/rust-lang/crates.io-index" 1807 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 1808 | 1809 | [[package]] 1810 | name = "unicode-ident" 1811 | version = "1.0.14" 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" 1813 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 1814 | 1815 | [[package]] 1816 | name = "unicode-width" 1817 | version = "0.2.0" 1818 | source = "registry+https://github.com/rust-lang/crates.io-index" 1819 | checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" 1820 | 1821 | [[package]] 1822 | name = "unicode-xid" 1823 | version = "0.2.6" 1824 | source = "registry+https://github.com/rust-lang/crates.io-index" 1825 | checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 1826 | 1827 | [[package]] 1828 | name = "universal-hash" 1829 | version = "0.5.1" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" 1832 | dependencies = [ 1833 | "crypto-common", 1834 | "subtle", 1835 | ] 1836 | 1837 | [[package]] 1838 | name = "utf8parse" 1839 | version = "0.2.2" 1840 | source = "registry+https://github.com/rust-lang/crates.io-index" 1841 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1842 | 1843 | [[package]] 1844 | name = "version_check" 1845 | version = "0.9.5" 1846 | source = "registry+https://github.com/rust-lang/crates.io-index" 1847 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1848 | 1849 | [[package]] 1850 | name = "wasi" 1851 | version = "0.11.0+wasi-snapshot-preview1" 1852 | source = "registry+https://github.com/rust-lang/crates.io-index" 1853 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1854 | 1855 | [[package]] 1856 | name = "wasm-bindgen" 1857 | version = "0.2.99" 1858 | source = "registry+https://github.com/rust-lang/crates.io-index" 1859 | checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" 1860 | dependencies = [ 1861 | "cfg-if", 1862 | "once_cell", 1863 | "wasm-bindgen-macro", 1864 | ] 1865 | 1866 | [[package]] 1867 | name = "wasm-bindgen-backend" 1868 | version = "0.2.99" 1869 | source = "registry+https://github.com/rust-lang/crates.io-index" 1870 | checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" 1871 | dependencies = [ 1872 | "bumpalo", 1873 | "log", 1874 | "proc-macro2", 1875 | "quote", 1876 | "syn", 1877 | "wasm-bindgen-shared", 1878 | ] 1879 | 1880 | [[package]] 1881 | name = "wasm-bindgen-macro" 1882 | version = "0.2.99" 1883 | source = "registry+https://github.com/rust-lang/crates.io-index" 1884 | checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" 1885 | dependencies = [ 1886 | "quote", 1887 | "wasm-bindgen-macro-support", 1888 | ] 1889 | 1890 | [[package]] 1891 | name = "wasm-bindgen-macro-support" 1892 | version = "0.2.99" 1893 | source = "registry+https://github.com/rust-lang/crates.io-index" 1894 | checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" 1895 | dependencies = [ 1896 | "proc-macro2", 1897 | "quote", 1898 | "syn", 1899 | "wasm-bindgen-backend", 1900 | "wasm-bindgen-shared", 1901 | ] 1902 | 1903 | [[package]] 1904 | name = "wasm-bindgen-shared" 1905 | version = "0.2.99" 1906 | source = "registry+https://github.com/rust-lang/crates.io-index" 1907 | checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" 1908 | 1909 | [[package]] 1910 | name = "web-time" 1911 | version = "1.1.0" 1912 | source = "registry+https://github.com/rust-lang/crates.io-index" 1913 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1914 | dependencies = [ 1915 | "js-sys", 1916 | "wasm-bindgen", 1917 | ] 1918 | 1919 | [[package]] 1920 | name = "windows-core" 1921 | version = "0.52.0" 1922 | source = "registry+https://github.com/rust-lang/crates.io-index" 1923 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 1924 | dependencies = [ 1925 | "windows-targets", 1926 | ] 1927 | 1928 | [[package]] 1929 | name = "windows-sys" 1930 | version = "0.59.0" 1931 | source = "registry+https://github.com/rust-lang/crates.io-index" 1932 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1933 | dependencies = [ 1934 | "windows-targets", 1935 | ] 1936 | 1937 | [[package]] 1938 | name = "windows-targets" 1939 | version = "0.52.6" 1940 | source = "registry+https://github.com/rust-lang/crates.io-index" 1941 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1942 | dependencies = [ 1943 | "windows_aarch64_gnullvm", 1944 | "windows_aarch64_msvc", 1945 | "windows_i686_gnu", 1946 | "windows_i686_gnullvm", 1947 | "windows_i686_msvc", 1948 | "windows_x86_64_gnu", 1949 | "windows_x86_64_gnullvm", 1950 | "windows_x86_64_msvc", 1951 | ] 1952 | 1953 | [[package]] 1954 | name = "windows_aarch64_gnullvm" 1955 | version = "0.52.6" 1956 | source = "registry+https://github.com/rust-lang/crates.io-index" 1957 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1958 | 1959 | [[package]] 1960 | name = "windows_aarch64_msvc" 1961 | version = "0.52.6" 1962 | source = "registry+https://github.com/rust-lang/crates.io-index" 1963 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1964 | 1965 | [[package]] 1966 | name = "windows_i686_gnu" 1967 | version = "0.52.6" 1968 | source = "registry+https://github.com/rust-lang/crates.io-index" 1969 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1970 | 1971 | [[package]] 1972 | name = "windows_i686_gnullvm" 1973 | version = "0.52.6" 1974 | source = "registry+https://github.com/rust-lang/crates.io-index" 1975 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1976 | 1977 | [[package]] 1978 | name = "windows_i686_msvc" 1979 | version = "0.52.6" 1980 | source = "registry+https://github.com/rust-lang/crates.io-index" 1981 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1982 | 1983 | [[package]] 1984 | name = "windows_x86_64_gnu" 1985 | version = "0.52.6" 1986 | source = "registry+https://github.com/rust-lang/crates.io-index" 1987 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1988 | 1989 | [[package]] 1990 | name = "windows_x86_64_gnullvm" 1991 | version = "0.52.6" 1992 | source = "registry+https://github.com/rust-lang/crates.io-index" 1993 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1994 | 1995 | [[package]] 1996 | name = "windows_x86_64_msvc" 1997 | version = "0.52.6" 1998 | source = "registry+https://github.com/rust-lang/crates.io-index" 1999 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2000 | 2001 | [[package]] 2002 | name = "winnow" 2003 | version = "0.6.22" 2004 | source = "registry+https://github.com/rust-lang/crates.io-index" 2005 | checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" 2006 | dependencies = [ 2007 | "memchr", 2008 | ] 2009 | 2010 | [[package]] 2011 | name = "x25519-dalek" 2012 | version = "2.0.1" 2013 | source = "registry+https://github.com/rust-lang/crates.io-index" 2014 | checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" 2015 | dependencies = [ 2016 | "curve25519-dalek", 2017 | "rand_core 0.6.4", 2018 | "serde", 2019 | "zeroize", 2020 | ] 2021 | 2022 | [[package]] 2023 | name = "x448" 2024 | version = "0.6.0" 2025 | source = "registry+https://github.com/rust-lang/crates.io-index" 2026 | checksum = "c4cd07d4fae29e07089dbcacf7077cd52dce7760125ca9a4dd5a35ca603ffebb" 2027 | dependencies = [ 2028 | "ed448-goldilocks", 2029 | "hex", 2030 | "rand_core 0.5.1", 2031 | ] 2032 | 2033 | [[package]] 2034 | name = "zerocopy" 2035 | version = "0.7.35" 2036 | source = "registry+https://github.com/rust-lang/crates.io-index" 2037 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 2038 | dependencies = [ 2039 | "byteorder", 2040 | "zerocopy-derive", 2041 | ] 2042 | 2043 | [[package]] 2044 | name = "zerocopy-derive" 2045 | version = "0.7.35" 2046 | source = "registry+https://github.com/rust-lang/crates.io-index" 2047 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 2048 | dependencies = [ 2049 | "proc-macro2", 2050 | "quote", 2051 | "syn", 2052 | ] 2053 | 2054 | [[package]] 2055 | name = "zeroize" 2056 | version = "1.8.1" 2057 | source = "registry+https://github.com/rust-lang/crates.io-index" 2058 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2059 | dependencies = [ 2060 | "zeroize_derive", 2061 | ] 2062 | 2063 | [[package]] 2064 | name = "zeroize_derive" 2065 | version = "1.4.2" 2066 | source = "registry+https://github.com/rust-lang/crates.io-index" 2067 | checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" 2068 | dependencies = [ 2069 | "proc-macro2", 2070 | "quote", 2071 | "syn", 2072 | ] 2073 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "opencl_vanity_gpg" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [profile.release] 7 | codegen-units = 1 8 | lto = "thin" 9 | opt-level = 3 10 | panic = "abort" 11 | strip = true 12 | 13 | [dependencies] 14 | byteorder = "1.5" 15 | chrono = { version = "0.4", default-features = false, features = ["now"] } 16 | clap = { version = "4.5", features = ["derive"] } 17 | env_logger = { version = "0.11", default-features = false, features = ["auto-color", "humantime"] } 18 | hex = "0.4" 19 | log = "0.4" 20 | ocl = "0.19" 21 | pgp = "0.14" 22 | rand = "0.8" 23 | smallvec = "1.13" 24 | anyhow = "1.0" 25 | indicatif = "0.17" 26 | indicatif-log-bridge = "0.2" 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opencl_vanity_gpg 2 | 3 | 使用 GPU(OpenCL)快速生成带有“靓号”的 PGP 密钥! 4 | 5 | “靓号”指的是带有连号等特定格式的密钥指纹或 ID(例如以 `77777777` 结尾),具体介绍和生成原理请参见: 6 | 7 | - [一位 PGP 进步青年的科学算号实践](https://www.douban.com/note/763978955/) 8 | - [某科学的 PGP 算号指南](https://blog.dejavu.moe/posts/the-scientific-vanity-pgp-counting-guide/) 9 | 10 | ![](https://github.com/user-attachments/assets/e6364d93-fffe-4fcd-9857-b70155e6f476) 11 | 12 | 简单来说,密钥指纹是密钥生效时间和公钥内容的 SHA-1,通过不断生成密钥和修改时间(成本更低)的暴力遍历方式找到“靓号”。 13 | 14 | > [!TIP] 15 | > 16 | > 姊妹项目:使用 WebGL 实现的网页版 [TransparentLC/webgl-vanity-gpg](https://github.com/TransparentLC/webgl-vanity-gpg) 17 | > 18 | > 实际上这个项目也可以当成是它的“锈化”版…\_φ(・ω・` ) 19 | 20 | 目前最好的同类工具是使用 CPU 的 [RedL0tus/VanityGPG](https://github.com/RedL0tus/VanityGPG) 和使用 GPU(CUDA)的 [cuihaoleo/gpg-fingerprint-filter-gpu](https://github.com/cuihaoleo/gpg-fingerprint-filter-gpu)。这个项目是使用 GPU(OpenCL)实现的,优点当然是开箱即用了。 21 | 22 | GitHub Actions 有自动编译好的二进制文件。 23 | 24 | # 使用方法 25 | 26 | ```console 27 | $ opencl_vanity_gpg -h 28 | Usage: opencl_vanity_gpg [OPTIONS] 29 | 30 | Options: 31 | -c, --cipher-suite Cipher suite of the vanity key 32 | ed25519, ecdsa-****, rsa**** => Primary key 33 | cv25519, ecdh-**** => Subkey 34 | Use gpg CLI for further editing of the key. [default: ed25519] [possible values: ed25519, cv25519, rsa2048, rsa3072, rsa4096, ecdh-p256, ecdh-p384, ecdh-p521, ecdsa-p256, ecdsa-p384, ecdsa-p521] 35 | -u, --user-id OpenPGP compatible user ID [default: "Dummy "] 36 | -p, --pattern A pattern less than 40 chars for matching fingerprints 37 | > Format: 38 | * 0-9A-F are fixed, G-Z are wildcards 39 | * Other chars will be ignored 40 | * Case insensitive 41 | > Example: 42 | * 11XXXX** may output a fingerprint ends with 11222234 or 11AAAABF 43 | * 11XXYYZZ may output a fingerprint ends with 11223344 or 11AABBCC 44 | -f, --filter OpenCL kernel function for uint h[5] for matching fingerprints 45 | Ignore the pattern and no estimate is given if this has been set 46 | > Example: 47 | * (h[4] & 0xFFFF) == 0x1234 outputs a fingerprint ends with 1234 48 | * (h[0] & 0xFFFF0000) == 0xABCD0000 outputs a fingerprint starts with ABCD 49 | -o, --output The dir where the vanity keys are saved 50 | -d, --device Device ID to use 51 | -t, --thread Adjust it to maximum your device's usage 52 | -i, --iteration Adjust it to maximum your device's usage [default: 512] 53 | --timeout Exit after a specified time in seconds 54 | --oneshot Exit after getting a vanity key 55 | --no-progress Don't print progress 56 | --no-secret-key-logging Don't print armored secret key 57 | --list-device Show available OpenCL devices then exit 58 | -h, --help Print help 59 | -V, --version Print version 60 | 61 | $ opencl_vanity_gpg -p 11XXYYZZ --oneshot 62 | [2025-01-08T19:00:25Z INFO opencl_vanity_gpg] Using device: Apple M1 Pro 63 | [2025-01-08T19:00:25Z INFO opencl_vanity_gpg] Auto set thread: 1048576 64 | [2025-01-08T19:00:25Z INFO opencl_vanity_gpg] You will get vanity keys created after 2008-01-05T00:11:53.021Z 65 | [2025-01-08T19:00:25Z WARN opencl_vanity_gpg] No output dir given. Generated vanity keys will not be saved. 66 | [2025-01-08T19:00:26Z INFO opencl_vanity_gpg::utils::vanity_key] Get a vanity key: 67 | -----BEGIN PGP PRIVATE KEY BLOCK----- 68 | 69 | xVgER4EupBYJKwYBBAHaRw8BAQdAI4vIy0CaErtwj1iAQInMQYwIz4BMo30MfS1s 70 | Kg0FYMUAAP4oOaeAXKE3fHhq1H28qYI+j7awA2iYQW7+fgTODpyXWxAfzRlEdW1t 71 | eSA8ZHVtbXlAZXhhbXBsZS5jb20+wo4EEBYIADYCGQEFAmd+y0oCGwMECwkIBwUV 72 | CgkICwUWAgMBAAEnFiEEucj6sO6iKUnbGDpx5F4DcRHMZiIACgkQ5F4DcRHMZiJ0 73 | iQD/cUPO7lBsDbg5wyFwXalTvzcac8865OakjsdmA+bJPc8A/insYTxgzA/boh7i 74 | ieogUSu64E0VyYGnfjcnIMX33mQPx10ER4EupBIKKwYBBAGXVQEFAQEHQPHXTpFg 75 | T6dZ/eudJ0W+JzzfuzK8cCWlDcaWD/DEogVRAwEIBwAA/2I4tvG84tjPcZGxClnJ 76 | nUpTRDrLvKtelZ5QBZLJbNJoEjXCeAQYFggAIAUCZ37LSgIbDBYhBLnI+rDuoilJ 77 | 2xg6ceReA3ERzGYiAAoJEOReA3ERzGYi8QwBAPr0n0eGhbNt5PMUfDccx4ttthFm 78 | xsCkD3wdoVaA7t/BAQCvPyuVmtJN4M8gsYNRZYEfLwb1BIckohZv+svENGSqAw== 79 | =ZeYm 80 | -----END PGP PRIVATE KEY BLOCK----- 81 | 82 | [2025-01-08T19:00:26Z INFO opencl_vanity_gpg::utils::vanity_key] Created at: 2008-01-06T19:40:20.000Z (1199648420) 83 | [2025-01-08T19:00:26Z INFO opencl_vanity_gpg::utils::vanity_key] Fingerprint #0: B9C8FAB0EEA22949DB183A71E45E037111CC6622 84 | [2025-01-08T19:00:26Z INFO opencl_vanity_gpg::utils::vanity_key] Fingerprint #1: 7FBC6D063D9C4CF4C281E8A14876C8831552E9B4 85 | [2025-01-08T19:00:26Z INFO opencl_vanity_gpg] Hashed: 536.87M (512.00x) Time: 1.53s Speed: 351.76M hash/s 86 | ``` 87 | 88 | 一个 Curve25519 的密钥由用来签名和认证的 Ed25519 主密钥和用来加密的 Cv25519 子密钥组成。VanityGPG [只能生成主密钥为“靓号”的密钥](https://github.com/RedL0tus/VanityGPG/issues/5),而这个项目也可以生成子密钥为“靓号”的密钥(只需要添加参数 `-c cv25519` 即可)。对于其他 NISP P-\*\*\* 的椭圆曲线的密钥也是类似的。 89 | 90 | # 性能对比 91 | 92 | | Repo | 计算方式 | 速度(hash/s) | 注释 | 93 | | - | - | - | - | 94 | | [RedL0tus/VanityGPG](https://github.com/RedL0tus/VanityGPG) | CPU | 165m | Xeon w5-2465X ×16 cores
Arch Linux | 95 | | 这个项目 | CPU | 120m | Xeon w5-2465X ×16 cores
Arch Linux
CPU 也可以是 OpenCL 的计算设备,虽然性能损耗比较严重…… | 96 | | [cuihaoleo/gpg-fingerprint-filter-gpu](https://github.com/cuihaoleo/gpg-fingerprint-filter-gpu) | GPU | 1b | A16 1/8
Ubuntu 24.04 | 97 | | 这个项目 | GPU | 1.5b | A16 1/8
Ubuntu 24.04 | 98 | | [TransparentLC/webgl-vanity-gpg](https://github.com/TransparentLC/webgl-vanity-gpg) | GPU | 2b | GTX 1070
Windows 11 | 99 | | 这个项目 | GPU | 3b | GTX 1070
Windows 11 | 100 | | [TransparentLC/webgl-vanity-gpg](https://github.com/TransparentLC/webgl-vanity-gpg) | GPU | 7b | RTX A5500
Windows 11 | 101 | | 这个项目 | GPU | 12b | RTX A5500
Windows 11 | 102 | | 这个项目 | GPU | 32b | RTX 4090
Ubuntu 22.04 | 103 | | 这个项目 | GPU | 240m | RTX 4090
Ubuntu 22.04 rsa4096 | 104 | | 这个项目 | GPU | 380m | Apple M1 Pro | 105 | | 这个项目 | GPU | 1.6b | Apple M4 Pro | 106 | 107 | 除另有标注外,以上的速度均为生成 cv25519 类型的密钥的速度。 108 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::bail; 2 | use log::*; 3 | use ocl::{Buffer, Device, Platform, ProQue}; 4 | use pgp::types::PublicKeyTrait; 5 | use rand::thread_rng; 6 | use std::{ 7 | fs, 8 | path::Path, 9 | str::FromStr, 10 | sync::{mpsc::*, LazyLock}, 11 | thread, 12 | time::Instant, 13 | }; 14 | use utils::ARGS; 15 | use utils::*; 16 | 17 | mod utils; 18 | 19 | fn main() -> anyhow::Result<()> { 20 | let bars = init_logger(); 21 | 22 | debug!("{:#?}", LazyLock::force(&ARGS)); 23 | 24 | let device_list = utils::DeviceList::new()?; 25 | 26 | if ARGS.list_device { 27 | info!("Available OpenCL devices: \n"); 28 | for (i, device) in device_list.iter().enumerate() { 29 | println!("Device #{} - {:?}", i, device); 30 | } 31 | return Ok(()); 32 | } 33 | 34 | let device = match ARGS.device { 35 | Some(i) => device_list[i].device, 36 | None => Device::first(Platform::default())?, 37 | }; 38 | 39 | info!("Using device: {}", device.name()?); 40 | 41 | let dimension = match ARGS.thread { 42 | Some(v) => v, 43 | None => match device.info(ocl::core::DeviceInfo::MaxWorkItemSizes)? { 44 | ocl::core::DeviceInfoResult::MaxWorkItemSizes(wgs) => { 45 | let dimension = usize::max(wgs[0] * wgs[1], 1048576); 46 | info!("Auto set thread: {dimension}"); 47 | dimension 48 | } 49 | _ => unreachable!(), 50 | }, 51 | }; 52 | 53 | let iteration = ARGS.iteration; 54 | info!( 55 | "You will get vanity keys created after {}", 56 | chrono::Utc::now() 57 | .checked_sub_signed(chrono::TimeDelta::seconds((dimension * iteration) as i64)) 58 | .unwrap() 59 | .to_rfc3339_opts(chrono::SecondsFormat::Millis, true), 60 | ); 61 | 62 | if ARGS.output.is_none() { 63 | if ARGS.no_secret_key_logging { 64 | warn!("No output dir given and you disabled secret key logging. You have no chance to save generated vanity keys."); 65 | } else { 66 | warn!("No output dir given. Generated vanity keys will not be saved."); 67 | } 68 | } 69 | 70 | let pattern = match &ARGS.pattern { 71 | Some(pattern) => Some(HashPattern::from_str(pattern)?), 72 | None => None, 73 | }; 74 | 75 | let (filter, estimate) = match &ARGS.filter { 76 | Some(filter) => (filter.clone(), None), 77 | None => match &pattern { 78 | Some(p) => (p.filter.clone(), Some(p.possibliity)), 79 | None => bail!("No filter or pattern given"), 80 | }, 81 | }; 82 | debug!("Filter: {filter}"); 83 | 84 | let mut rng = thread_rng(); 85 | 86 | match ARGS.cipher_suite { 87 | CipherSuite::RSA2048 | CipherSuite::RSA3072 | CipherSuite::RSA4096 => { 88 | warn!("Generating RSA vanity keys is not recommended. Too slow!") 89 | } 90 | _ => (), 91 | }; 92 | 93 | let mut vanity_key = VanitySecretKey::new(ARGS.cipher_suite, ARGS.user_id.clone(), &mut rng); 94 | let mut hashdata = manually_prepare_sha1(vanity_key.hashdata()); 95 | 96 | let (tx_hashdata, rx_hashdata) = channel::>(); 97 | let (tx_result, rx_result) = channel::>(); 98 | 99 | let mut hashed = 0; 100 | let mut start = Instant::now(); 101 | 102 | let pro_que = ProQue::builder() 103 | .src( 104 | std::include_str!("shader.cl").replace( 105 | "#define __INJECTS__", 106 | &[ 107 | format!("#define FILTER(h) ({filter})"), 108 | format!("#define CHUNK ({})", hashdata.len() / 16), 109 | ] 110 | .join("\n"), 111 | ), 112 | ) 113 | .device(device) 114 | .dims(dimension) 115 | .build()?; 116 | 117 | let buffer_result = Buffer::::builder() 118 | .queue(pro_que.queue().clone()) 119 | .len(1) 120 | .fill_val(0) 121 | .build()?; 122 | 123 | thread::spawn(move || opencl_thread(buffer_result, pro_que, rx_hashdata, tx_result)); 124 | 125 | let bench_size = (dimension * iteration) as u64; 126 | let bar = bars.add(init_progress_bar(estimate)); 127 | 128 | loop { 129 | debug!("Send key to OpenCL thread"); 130 | tx_hashdata.send(hashdata)?; 131 | let vanity_key_next = 132 | VanitySecretKey::new(ARGS.cipher_suite, ARGS.user_id.clone(), &mut rng); 133 | let hashdata_next = manually_prepare_sha1(vanity_key_next.hashdata()); 134 | 135 | debug!("Receive result from OpenCL thread"); 136 | let vanity_timestamp = rx_result.recv()?; 137 | hashed += bench_size; 138 | 139 | let elapsed = start.elapsed().as_secs_f64(); 140 | bar.inc(bench_size); 141 | 142 | if let Some(vanity_timestamp) = vanity_timestamp { 143 | vanity_key.edit_timestamp(vanity_timestamp, &mut rng); 144 | 145 | if match &pattern { 146 | Some(pattern) => vanity_key.check_pattern(pattern), 147 | None => true, 148 | } { 149 | vanity_key.log_state(); 150 | 151 | match estimate { 152 | Some(estimate) => info!( 153 | "Hashed: {} ({:.02}x) Time: {:.02}s Speed: {} hash/s", 154 | format_number(hashed as f64), 155 | (hashed as f64) / estimate, 156 | elapsed, 157 | format_number((hashed as f64) / elapsed), 158 | ), 159 | None => info!( 160 | "Hashed: {} Time: {:.02}s Speed: {} hash/s", 161 | format_number(hashed as f64), 162 | elapsed, 163 | format_number((hashed as f64) / elapsed), 164 | ), 165 | } 166 | 167 | if let Some(ref output_dir) = ARGS.output { 168 | fs::write( 169 | Path::new(output_dir).join(format!( 170 | "{}-sec.asc", 171 | hex::encode_upper(vanity_key.secret_key.fingerprint().as_bytes()) 172 | )), 173 | vanity_key.to_armored_string()?, 174 | ) 175 | .unwrap(); 176 | } 177 | 178 | if ARGS.oneshot { 179 | bar.finish(); 180 | bars.clear()?; 181 | break; 182 | } 183 | 184 | hashed = 0; 185 | bar.reset(); 186 | start = Instant::now(); 187 | } 188 | } 189 | 190 | if let Some(timeout) = ARGS.timeout { 191 | if elapsed > timeout { 192 | info!("Timeout!"); 193 | break; 194 | } 195 | } 196 | 197 | vanity_key = vanity_key_next; 198 | hashdata = hashdata_next; 199 | } 200 | 201 | Ok(()) 202 | } 203 | 204 | fn opencl_thread( 205 | buffer_result: Buffer, 206 | pro_que: ProQue, 207 | rx_hashdata: Receiver>, 208 | tx_result: Sender>, 209 | ) { 210 | let mut vec = vec![0; buffer_result.len()]; 211 | debug!("OpenCL thread ready"); 212 | while let Ok(hashdata) = rx_hashdata.recv() { 213 | buffer_result.cmd().fill(0, None).enq().unwrap(); 214 | 215 | let buffer_hashdata = Buffer::::builder() 216 | .queue(pro_que.queue().clone()) 217 | .len(hashdata.len()) 218 | .copy_host_slice(&hashdata) 219 | .build() 220 | .unwrap(); 221 | 222 | let kernel = pro_que 223 | .kernel_builder("vanity_sha1") 224 | .arg(&buffer_hashdata) 225 | .arg(&buffer_result) 226 | .arg(ARGS.iteration as u64) 227 | .build() 228 | .unwrap(); 229 | 230 | unsafe { 231 | kernel.enq().unwrap(); 232 | } 233 | 234 | buffer_result.read(&mut vec).enq().unwrap(); 235 | 236 | tx_result 237 | .send(match vec[0] { 238 | 0 => None, 239 | x => Some(x), 240 | }) 241 | .unwrap(); 242 | } 243 | debug!("OpenCL thread quit"); 244 | } 245 | -------------------------------------------------------------------------------- /src/shader.cl: -------------------------------------------------------------------------------- 1 | #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) 2 | 3 | #define __INJECTS__ 4 | #ifdef __INJECTS__ 5 | #define CHUNK (0) 6 | #define FILTER(h) (false) 7 | #endif 8 | 9 | __kernel void vanity_sha1(__constant uint *hashdata, __global uint *result, const ulong iter) { 10 | uint data[CHUNK * 16]; 11 | for (uint i = 0; i < CHUNK * 16; i++) data[i] = hashdata[i]; 12 | uint nonce = data[1]; 13 | for (uint i = 0; i < iter; i++) { 14 | data[1] = nonce - get_global_id(0) * iter - i; 15 | if (data[1] > nonce) break; 16 | 17 | uint h[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; 18 | 19 | #pragma unroll 20 | for (uint chunk = 0; chunk < CHUNK; chunk++) { 21 | uint w[80]; 22 | for (int i = 0; i < 16; i++) w[i] = data[chunk * 16 + i]; 23 | for (int i = 16; i < 80; i++) w[i] = ROTL(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1); 24 | 25 | uint a = h[0]; 26 | uint b = h[1]; 27 | uint c = h[2]; 28 | uint d = h[3]; 29 | uint e = h[4]; 30 | uint f; 31 | uint k; 32 | uint t; 33 | 34 | #pragma unroll 35 | for (int i = 0; i < 80; i++) { 36 | if (i < 20) { 37 | f = d ^ (b & (c ^ d)); 38 | k = 0x5A827999; 39 | } else if (i < 40) { 40 | f = b ^ c ^ d; 41 | k = 0x6ED9EBA1; 42 | } else if (i < 60) { 43 | f = (b & c) | (b & d) | (c & d); 44 | k = 0x8F1BBCDC; 45 | } else { 46 | f = b ^ c ^ d; 47 | k = 0xCA62C1D6; 48 | } 49 | t = ROTL(a, 5) + f + e + k + w[i]; 50 | e = d; 51 | d = c; 52 | c = ROTL(b, 30); 53 | b = a; 54 | a = t; 55 | } 56 | 57 | h[0] += a; 58 | h[1] += b; 59 | h[2] += c; 60 | h[3] += d; 61 | h[4] += e; 62 | } 63 | 64 | if (FILTER(h)) { 65 | *result = data[1]; 66 | break; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/utils/args.rs: -------------------------------------------------------------------------------- 1 | use clap::{Parser, ValueEnum}; 2 | use std::sync::LazyLock; 3 | 4 | pub static ARGS: LazyLock = LazyLock::new(if cfg!(debug_assertions) { 5 | Args::default 6 | } else { 7 | Args::parse 8 | }); 9 | 10 | #[derive(Parser, Debug)] 11 | #[command(version, about, long_about = None)] 12 | pub struct Args { 13 | /// Cipher suite of the vanity key 14 | /// ed25519, ecdsa-****, rsa**** => Primary key 15 | /// cv25519, ecdh-**** => Subkey 16 | /// Use gpg CLI for further editing of the key. 17 | #[arg(short, long, default_value_t, value_enum, verbatim_doc_comment)] 18 | pub cipher_suite: CipherSuite, 19 | 20 | /// OpenPGP compatible user ID 21 | #[arg(short, long, default_value_t = String::from("Dummy "))] 22 | pub user_id: String, 23 | 24 | /// A pattern less than 40 chars for matching fingerprints 25 | /// > Format: 26 | /// * 0-9A-F are fixed, G-Z are wildcards 27 | /// * Other chars will be ignored 28 | /// * Case insensitive 29 | /// > Example: 30 | /// * 11XXXX** may output a fingerprint ends with 11222234 or 11AAAABF 31 | /// * 11XXYYZZ may output a fingerprint ends with 11223344 or 11AABBCC 32 | #[arg(short, long, verbatim_doc_comment)] 33 | pub pattern: Option, 34 | 35 | /// OpenCL kernel function for uint h[5] for matching fingerprints 36 | /// Ignore the pattern and no estimate is given if this has been set 37 | /// > Example: 38 | /// * (h[4] & 0xFFFF) == 0x1234 outputs a fingerprint ends with 1234 39 | /// * (h[0] & 0xFFFF0000) == 0xABCD0000 outputs a fingerprint starts with ABCD 40 | #[arg(short, long, verbatim_doc_comment)] 41 | pub filter: Option, 42 | 43 | /// The dir where the vanity keys are saved 44 | #[arg(short, long)] 45 | pub output: Option, 46 | 47 | /// Device ID to use 48 | #[arg(short, long)] 49 | pub device: Option, 50 | 51 | /// Adjust it to maximum your device's usage 52 | #[arg(short, long)] 53 | pub thread: Option, 54 | 55 | /// Adjust it to maximum your device's usage 56 | #[arg(short, long, default_value_t = 1 << 9)] 57 | pub iteration: usize, 58 | 59 | /// Exit after a specified time in seconds 60 | #[arg(long)] 61 | pub timeout: Option, 62 | 63 | /// Exit after getting a vanity key 64 | #[arg(long, default_value_t = false)] 65 | pub oneshot: bool, 66 | 67 | /// Don't print progress 68 | #[arg(long, default_value_t = false)] 69 | pub no_progress: bool, 70 | 71 | /// Don't print armored secret key 72 | #[arg(long, default_value_t = false)] 73 | pub no_secret_key_logging: bool, 74 | 75 | /// Show available OpenCL devices then exit 76 | #[arg(long, default_value_t = false)] 77 | pub list_device: bool, 78 | } 79 | 80 | impl Default for Args { 81 | fn default() -> Self { 82 | Self { 83 | cipher_suite: CipherSuite::Ed25519, 84 | user_id: String::from("Dummy "), 85 | pattern: Some(String::from("XXXYYYZZZWWW")), 86 | filter: None, 87 | output: None, 88 | device: None, 89 | thread: None, 90 | iteration: 512, 91 | timeout: None, 92 | oneshot: true, 93 | no_progress: true, 94 | no_secret_key_logging: false, 95 | list_device: false, 96 | } 97 | } 98 | } 99 | 100 | /// Cipher Suites 101 | #[derive(ValueEnum, Default, Clone, Copy, Debug)] 102 | #[clap(rename_all = "kebab_case")] 103 | pub enum CipherSuite { 104 | #[default] 105 | Ed25519, 106 | Cv25519, 107 | RSA2048, 108 | RSA3072, 109 | RSA4096, 110 | EcdhP256, 111 | EcdhP384, 112 | EcdhP521, 113 | EcdsaP256, 114 | EcdsaP384, 115 | EcdsaP521, 116 | } 117 | -------------------------------------------------------------------------------- /src/utils/device.rs: -------------------------------------------------------------------------------- 1 | use ocl::core::{DeviceInfo as OclInfo, DeviceInfoResult}; 2 | use ocl::{Device, Platform}; 3 | 4 | pub struct DeviceInfo { 5 | pub name: String, 6 | pub platform_name: String, 7 | pub max_work_group_size: usize, 8 | pub max_work_item_sizes: Vec, 9 | pub max_work_item_dimensions: u32, 10 | 11 | // hold the actual device 12 | pub device: Device, 13 | } 14 | 15 | pub struct DeviceList(pub Vec); 16 | 17 | impl DeviceInfo { 18 | pub fn new(device: Device, platform: Platform) -> anyhow::Result { 19 | Ok(Self { 20 | name: device.name()?, 21 | platform_name: platform.name()?, 22 | max_work_group_size: match device.info(OclInfo::MaxWorkGroupSize)? { 23 | DeviceInfoResult::MaxWorkGroupSize(size) => size, 24 | _ => unreachable!(), 25 | }, 26 | max_work_item_sizes: match device.info(OclInfo::MaxWorkItemSizes)? { 27 | DeviceInfoResult::MaxWorkItemSizes(wgs) => wgs, 28 | _ => unreachable!(), 29 | }, 30 | max_work_item_dimensions: match device.info(OclInfo::MaxWorkItemDimensions)? { 31 | DeviceInfoResult::MaxWorkItemDimensions(dim) => dim, 32 | _ => unreachable!(), 33 | }, 34 | device, 35 | }) 36 | } 37 | } 38 | 39 | impl DeviceList { 40 | pub fn new() -> anyhow::Result { 41 | let platforms = Platform::list(); 42 | let mut list = Vec::with_capacity(platforms.len()); 43 | for platform in platforms { 44 | if let Ok(devices) = Device::list_all(platform) { 45 | for device in devices { 46 | list.push(DeviceInfo::new(device, platform)?); 47 | } 48 | } 49 | } 50 | Ok(Self(list)) 51 | } 52 | } 53 | 54 | impl std::fmt::Debug for DeviceInfo { 55 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 56 | write!( 57 | f, 58 | "{} ({}, MaxWorkGroupSize={}, MaxWorkItemSizes={}, MaxWorkItemDimensions={})", 59 | self.name, 60 | self.platform_name, 61 | self.max_work_group_size, 62 | self.max_work_item_sizes 63 | .iter() 64 | .map(|x| x.to_string()) 65 | .collect::>() 66 | .join(", "), 67 | self.max_work_item_dimensions 68 | ) 69 | } 70 | } 71 | 72 | impl std::ops::Deref for DeviceList { 73 | type Target = Vec; 74 | 75 | fn deref(&self) -> &Self::Target { 76 | &self.0 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | mod args; 2 | mod device; 3 | mod pattern; 4 | mod vanity_key; 5 | 6 | use std::{fmt::Write, mem}; 7 | 8 | pub use args::*; 9 | pub use device::DeviceList; 10 | pub use pattern::HashPattern; 11 | use indicatif::*; 12 | use indicatif_log_bridge::LogWrapper; 13 | pub use vanity_key::VanitySecretKey; 14 | 15 | /// Do SHA-1 padding manually 16 | /// A SHA-1 block is 512 bit, so the output Vec length is a multiple of 16 17 | pub fn manually_prepare_sha1(hashdata: Vec) -> Vec { 18 | // Length after padding 19 | // Fill with 0x80 0x00 ... to 448 mod 512 bit, which is 56 mod 64 bytes 20 | // plus u64's 8 bytes, the length is a multiple of 64 21 | let padded_length = hashdata.len() + (64 - ((hashdata.len() + 8) % 64)) + 8; 22 | let mut result_u8 = Vec::with_capacity(padded_length); 23 | result_u8.extend_from_slice(&hashdata); 24 | result_u8.push(0x80); 25 | result_u8.resize(padded_length, 0); 26 | 27 | // convert Vec to Vec 28 | // https://stackoverflow.com/questions/49690459/converting-a-vecu32-to-vecu8-in-place-and-with-minimal-overhead 29 | let mut result_u32 = unsafe { 30 | let ptr = result_u8.as_mut_ptr() as *mut u32; 31 | let length = result_u8.len() / 4; 32 | let capacity = result_u8.capacity() / 4; 33 | mem::forget(result_u8); 34 | Vec::from_raw_parts(ptr, length, capacity) 35 | }; 36 | 37 | // assert_eq!(result_u32.len() % 16, 0); 38 | // SHA-1 uses big-endian words and length 39 | for pos in &mut result_u32 { 40 | *pos = pos.to_be(); 41 | } 42 | 43 | let bit_length = hashdata.len() * 8; 44 | result_u32[padded_length / 4 - 1] = (bit_length) as u32; 45 | result_u32[padded_length / 4 - 2] = (bit_length >> 32) as u32; 46 | result_u32 47 | } 48 | 49 | pub fn init_logger() -> MultiProgress { 50 | let logger = env_logger::Builder::from_env( 51 | env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), 52 | ) 53 | .format_indent(None) 54 | .build(); 55 | 56 | let level = logger.filter(); 57 | let multi = MultiProgress::new(); 58 | 59 | LogWrapper::new(multi.clone(), logger).try_init().unwrap(); 60 | log::set_max_level(level); 61 | 62 | multi 63 | } 64 | 65 | pub fn init_progress_bar(estimate: Option) -> ProgressBar { 66 | let bar = match estimate { 67 | Some(estimate) => ProgressBar::new(estimate as u64), 68 | None => ProgressBar::new_spinner(), 69 | }; 70 | 71 | bar.set_style( 72 | ProgressStyle::default_spinner() 73 | .template("[{elapsed_precise}] {bar:50.cyan/blue} {progress} {rate} > {eta_precise}") 74 | .unwrap() 75 | .progress_chars("##-") 76 | .with_key("progress", |state: &ProgressState, w: &mut dyn Write| { 77 | write!( 78 | w, 79 | "{}/{}", 80 | format_number(state.pos() as f64), 81 | match state.len() { 82 | None => "???".to_string(), 83 | Some(x) => format_number(x as f64), 84 | } 85 | ) 86 | .unwrap() 87 | }) 88 | .with_key("rate", |state: &ProgressState, w: &mut dyn Write| { 89 | write!( 90 | w, 91 | "{} hash/s", 92 | format_number((state.pos() as f64) / state.elapsed().as_secs_f64()), 93 | ) 94 | .unwrap() 95 | }), 96 | ); 97 | 98 | bar 99 | } 100 | 101 | 102 | pub fn format_number(v: impl Into) -> String { 103 | match Into::::into(v) { 104 | v if v >= 1e12f64 => { 105 | format!("{:.02}T", v / 1e12f64) 106 | } 107 | v if v >= 1e9f64 => { 108 | format!("{:.02}B", v / 1e9f64) 109 | } 110 | v if v >= 1e6f64 => { 111 | format!("{:.02}M", v / 1e6f64) 112 | } 113 | v if v >= 1e3f64 => { 114 | format!("{:.02}K", v / 1e3f64) 115 | } 116 | v => { 117 | format!("{v:.02}") 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/utils/pattern.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, str::FromStr}; 2 | 3 | use anyhow::bail; 4 | 5 | #[derive(Debug, Clone)] 6 | pub struct HashPattern { 7 | pub pattern: String, 8 | pub filter: String, 9 | pub possibliity: f64, 10 | } 11 | 12 | impl HashPattern { 13 | pub fn is_match(&self, hash: &[u8]) -> bool { 14 | if hash.len() != 20 { 15 | return false; 16 | } 17 | 18 | let hash_str = hex::encode_upper(hash); 19 | 20 | for (i, c) in self.pattern.chars().enumerate() { 21 | if c.is_ascii_hexdigit() && c != hash_str.chars().nth(i).unwrap() { 22 | return false; 23 | } 24 | } 25 | 26 | let mut map = HashMap::new(); 27 | for (pos, c) in self.pattern.chars().enumerate() { 28 | if ('G'..='Z').contains(&c) { 29 | let hash_char = hash_str.chars().nth(pos).unwrap(); 30 | let expect = map.entry(c).or_insert(hash_char); 31 | if *expect != hash_char { 32 | return false; 33 | } 34 | } 35 | } 36 | 37 | true 38 | } 39 | } 40 | 41 | impl FromStr for HashPattern { 42 | type Err = anyhow::Error; 43 | 44 | fn from_str(s: &str) -> Result { 45 | let pattern = match s.trim().replace(' ', "").to_ascii_uppercase() { 46 | x if x.len() <= 40 => "*".repeat(40 - x.len()) + &x, 47 | _ => bail!("Invalid pattern: {}", s), 48 | }; 49 | 50 | let mut parts: Vec = vec![]; 51 | 52 | // Handle fixed 0-9A-F 53 | let mut fixed_pos_count: usize = 0; 54 | for i in 0..=4 { 55 | let mut mask = String::new(); 56 | let mut value = String::new(); 57 | let mut activated = false; 58 | for j in 0..8 { 59 | let char = *pattern.chars().nth(i * 8 + j).get_or_insert(' '); 60 | if char.is_ascii_hexdigit() { 61 | fixed_pos_count += 1; 62 | mask += "F"; 63 | value += &String::from(char); 64 | activated = true; 65 | } else { 66 | mask += "0"; 67 | value += "0"; 68 | } 69 | } 70 | if activated { 71 | parts.push(format!("(h[{i}] & 0x{mask}) == 0x{value}")); 72 | } 73 | } 74 | 75 | // Handle wildcard G-Z 76 | let mut wildcard_pos_all: [Vec; (b'Z' - b'G' + 1) as usize] = 77 | std::default::Default::default(); 78 | for (i, wildcard) in pattern.chars().enumerate() { 79 | if ('G'..='Z').contains(&wildcard) { 80 | wildcard_pos_all[((wildcard as u8) - b'G') as usize].push(i); 81 | } 82 | } 83 | let mut wildcard_pos_count = 0; 84 | 85 | for wildcard in 'G'..='Z' { 86 | let wildcard_pos = &wildcard_pos_all[((wildcard as u8) - b'G') as usize]; 87 | if wildcard_pos.len() >= 2 { 88 | for i in 1..wildcard_pos.len() { 89 | let left_index = wildcard_pos[i - 1] / 8; 90 | let right_index = wildcard_pos[i] / 8; 91 | let left_digit = 7 - wildcard_pos[i - 1] % 8; 92 | let right_digit = 7 - wildcard_pos[i] % 8; 93 | parts.push(format!( 94 | "(/* {}: h[{}][{}] == h[{}][{}] */ (h[{}] {} {}) & 0xF{}) == (h[{}] & 0xF{})", 95 | wildcard, 96 | left_index, 97 | left_digit, 98 | right_index, 99 | right_digit, 100 | left_index, 101 | if right_digit > left_digit { "<<" } else { ">>" }, 102 | right_digit.abs_diff(left_digit) * 4, 103 | "0".repeat(right_digit), 104 | right_index, 105 | "0".repeat(right_digit), 106 | )); 107 | } 108 | wildcard_pos_count += wildcard_pos.len() - 1; 109 | } 110 | } 111 | 112 | let filter = if !parts.is_empty() { 113 | parts.join(" && ") 114 | } else { 115 | String::from("true") 116 | }; 117 | 118 | Ok(HashPattern { 119 | pattern, 120 | filter, 121 | possibliity: (16f64).powi((fixed_pos_count + wildcard_pos_count) as i32), 122 | }) 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/utils/vanity_key.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use byteorder::{BigEndian, ByteOrder}; 3 | use log::{debug, info}; 4 | use pgp::{ 5 | composed::{key::SecretKeyParamsBuilder, KeyType}, 6 | crypto::{ecc_curve::ECCCurve, hash::HashAlgorithm, sym::SymmetricKeyAlgorithm}, 7 | packet::KeyFlags, 8 | ser::Serialize, 9 | types::{CompressionAlgorithm, KeyVersion, PublicKeyTrait, SecretKeyTrait}, 10 | Deserializable, SecretKey, SecretSubkey, SignedSecretKey, SubkeyParamsBuilder, 11 | }; 12 | use rand::{CryptoRng, Rng}; 13 | use smallvec::smallvec; 14 | 15 | use crate::ARGS; 16 | 17 | use super::{CipherSuite, HashPattern}; 18 | 19 | /// Get the data used to calculate the fingerprint of a private key 20 | fn build_secret_key_hashdata(secret_key: impl SecretKeyTrait) -> Vec { 21 | let mut hashdata = vec![0x99, 0, 0, 0x04, 0, 0, 0, 0]; 22 | BigEndian::write_u32( 23 | &mut hashdata[4..8], 24 | secret_key.created_at().timestamp() as u32, 25 | ); 26 | hashdata.push(secret_key.algorithm().into()); 27 | secret_key.public_params().to_writer(&mut hashdata).unwrap(); 28 | let packet_len = (hashdata.len() - 3) as u16; 29 | BigEndian::write_u16(&mut hashdata[1..3], packet_len); 30 | hashdata 31 | } 32 | 33 | pub struct VanitySecretKey { 34 | pub cipher_suite: CipherSuite, 35 | pub secret_key: SignedSecretKey, 36 | } 37 | 38 | impl VanitySecretKey { 39 | pub fn new(cipher_suite: CipherSuite, user_id: String, mut rng: impl Rng + CryptoRng) -> Self { 40 | let mut secret_key_params_builder = SecretKeyParamsBuilder::default(); 41 | secret_key_params_builder 42 | .preferred_symmetric_algorithms(smallvec![ 43 | SymmetricKeyAlgorithm::AES256, 44 | SymmetricKeyAlgorithm::AES192, 45 | SymmetricKeyAlgorithm::AES128, 46 | ]) 47 | .preferred_hash_algorithms(smallvec![ 48 | HashAlgorithm::SHA2_512, 49 | HashAlgorithm::SHA2_384, 50 | HashAlgorithm::SHA2_256, 51 | HashAlgorithm::SHA2_224, 52 | ]) 53 | .preferred_compression_algorithms(smallvec![ 54 | CompressionAlgorithm::ZLIB, 55 | CompressionAlgorithm::BZip2, 56 | CompressionAlgorithm::ZIP, 57 | CompressionAlgorithm::Uncompressed, 58 | ]) 59 | .can_certify(true) 60 | .can_sign(true) 61 | .primary_user_id(user_id); 62 | 63 | match cipher_suite { 64 | CipherSuite::Cv25519 | CipherSuite::Ed25519 => { 65 | let mut subkey_params_builder = SubkeyParamsBuilder::default(); 66 | subkey_params_builder 67 | .key_type(KeyType::ECDH(ECCCurve::Curve25519)) 68 | .can_encrypt(true); 69 | secret_key_params_builder 70 | .key_type(KeyType::EdDSALegacy) 71 | .subkey(subkey_params_builder.build().unwrap()); 72 | } 73 | CipherSuite::EcdhP256 74 | | CipherSuite::EcdsaP256 75 | | CipherSuite::EcdhP384 76 | | CipherSuite::EcdsaP384 77 | | CipherSuite::EcdhP521 78 | | CipherSuite::EcdsaP521 => { 79 | let curve = match cipher_suite { 80 | CipherSuite::EcdhP256 | CipherSuite::EcdsaP256 => ECCCurve::P256, 81 | CipherSuite::EcdhP384 | CipherSuite::EcdsaP384 => ECCCurve::P384, 82 | CipherSuite::EcdhP521 | CipherSuite::EcdsaP521 => ECCCurve::P521, 83 | _ => unreachable!(), 84 | }; 85 | let mut subkey_params_builder = SubkeyParamsBuilder::default(); 86 | subkey_params_builder 87 | .key_type(KeyType::ECDH(curve.clone())) 88 | .can_encrypt(true); 89 | secret_key_params_builder 90 | .key_type(KeyType::ECDSA(curve.clone())) 91 | .subkey(subkey_params_builder.build().unwrap()); 92 | } 93 | CipherSuite::RSA2048 | CipherSuite::RSA3072 | CipherSuite::RSA4096 => { 94 | let bits = match cipher_suite { 95 | CipherSuite::RSA2048 => 2048, 96 | CipherSuite::RSA3072 => 3072, 97 | CipherSuite::RSA4096 => 4096, 98 | _ => unreachable!(), 99 | }; 100 | secret_key_params_builder 101 | .key_type(KeyType::Rsa(bits)) 102 | .can_encrypt(true); 103 | } 104 | } 105 | 106 | let secret_key_params = secret_key_params_builder.build().unwrap(); 107 | let secret_key = secret_key_params 108 | .generate(&mut rng) 109 | .unwrap() 110 | .sign(&mut rng, String::new) 111 | .unwrap(); 112 | assert_eq!(secret_key.version(), KeyVersion::V4); 113 | 114 | Self { 115 | cipher_suite, 116 | secret_key, 117 | } 118 | } 119 | 120 | pub fn edit_timestamp(&mut self, timestamp: u32, mut rng: impl Rng + CryptoRng) { 121 | // RFC 9580 - OpenPGP 122 | // 4. Packet Syntax 123 | // https://datatracker.ietf.org/doc/html/rfc9580#name-packet-syntax 124 | let mut secret_key_bytes = self.secret_key.to_bytes().unwrap(); 125 | let mut packet_read_pos: usize = 0; 126 | while packet_read_pos < secret_key_bytes.len() { 127 | let cipher_type_byte = secret_key_bytes[packet_read_pos]; 128 | debug!("cipher_type_byte = {:#04X}", cipher_type_byte); 129 | packet_read_pos += 1; 130 | let (size, size_length) = match cipher_type_byte >> 6 { 131 | 0b10 => match cipher_type_byte & 0b00000011 { 132 | 0 => (secret_key_bytes[packet_read_pos] as usize, 1), 133 | 1 => ( 134 | BigEndian::read_u16(&secret_key_bytes[packet_read_pos..packet_read_pos + 2]) 135 | as usize, 136 | 2, 137 | ), 138 | 2 => ( 139 | BigEndian::read_u32(&secret_key_bytes[packet_read_pos..packet_read_pos + 4]) 140 | as usize, 141 | 4, 142 | ), 143 | 3 => unimplemented!("Indeterminate length"), 144 | _ => unreachable!(), 145 | }, 146 | 0b11 => match secret_key_bytes[packet_read_pos] { 147 | x if x < 192 => (secret_key_bytes[packet_read_pos] as usize, 1), 148 | x if x < 224 => ( 149 | (((secret_key_bytes[packet_read_pos] - 192) as usize) << 8) 150 | + (secret_key_bytes[packet_read_pos + 1] as usize) 151 | + 192, 152 | 2, 153 | ), 154 | 255 => ( 155 | BigEndian::read_u32( 156 | &secret_key_bytes[packet_read_pos + 1..packet_read_pos + 5], 157 | ) as usize, 158 | 5, 159 | ), 160 | _ => unimplemented!("Partial body length"), 161 | }, 162 | _ => unreachable!(), 163 | }; 164 | debug!("size = {size}, size_length = {size_length}"); 165 | packet_read_pos += size_length; 166 | let packet_type = match cipher_type_byte >> 6 { 167 | 0b10 => (cipher_type_byte & 0b00111100) >> 2, 168 | 0b11 => cipher_type_byte & 0b00111111, 169 | _ => unreachable!(), 170 | }; 171 | debug!("packet_type = {packet_type:#04X}"); 172 | // 0x05 => Secret-Key Packet 173 | // 0x07 => Secret-Subkey Packet 174 | if [0x05, 0x07].contains(&packet_type) { 175 | BigEndian::write_u32( 176 | &mut secret_key_bytes[packet_read_pos + 1..packet_read_pos + 5], 177 | timestamp, 178 | ); 179 | } 180 | packet_read_pos += size; 181 | } 182 | 183 | // The signature of this key is invalid because only the timestamp is modified 184 | let edited_key = SignedSecretKey::from_bytes(&secret_key_bytes[..]).unwrap(); 185 | 186 | // Re-sign the key 187 | let mut subkey_flags = KeyFlags::default(); 188 | subkey_flags.set_encrypt_storage(true); 189 | subkey_flags.set_encrypt_comms(true); 190 | self.secret_key = SecretKey::new( 191 | edited_key.primary_key, 192 | edited_key.details.as_unsigned(), 193 | edited_key 194 | .public_subkeys 195 | .iter() 196 | .map(|e| e.as_unsigned()) 197 | .collect(), 198 | edited_key 199 | .secret_subkeys 200 | .iter() 201 | .map(|e| SecretSubkey::new(e.key.clone(), subkey_flags)) 202 | .collect(), 203 | ) 204 | .sign(&mut rng, String::new) 205 | .unwrap(); 206 | } 207 | 208 | pub fn hashdata(&self) -> Vec { 209 | match self.cipher_suite { 210 | CipherSuite::Ed25519 211 | | CipherSuite::EcdsaP256 212 | | CipherSuite::EcdsaP384 213 | | CipherSuite::EcdsaP521 214 | | CipherSuite::RSA2048 215 | | CipherSuite::RSA3072 216 | | CipherSuite::RSA4096 => build_secret_key_hashdata(&self.secret_key), 217 | CipherSuite::Cv25519 218 | | CipherSuite::EcdhP256 219 | | CipherSuite::EcdhP384 220 | | CipherSuite::EcdhP521 => { 221 | build_secret_key_hashdata(&self.secret_key.secret_subkeys[0]) 222 | } 223 | } 224 | } 225 | 226 | pub fn to_armored_string(&self) -> Result { 227 | Ok(self 228 | .secret_key 229 | .to_armored_string(pgp::ArmorOptions::default())?) 230 | } 231 | 232 | pub fn check_pattern(&self, pattern: &HashPattern) -> bool { 233 | if pattern.is_match(self.secret_key.fingerprint().as_bytes()) { 234 | return true; 235 | } 236 | 237 | for subkey in &self.secret_key.secret_subkeys { 238 | if pattern.is_match(subkey.fingerprint().as_bytes()) { 239 | return true; 240 | } 241 | } 242 | 243 | false 244 | } 245 | 246 | pub fn log_state(&self) { 247 | if ARGS.no_secret_key_logging { 248 | info!("Get a vanity key!"); 249 | } else { 250 | info!( 251 | "Get a vanity key: \n{}", 252 | self.to_armored_string().unwrap_or_default() 253 | ); 254 | } 255 | info!( 256 | "Created at: {} ({})", 257 | self.secret_key 258 | .created_at() 259 | .to_rfc3339_opts(chrono::SecondsFormat::Millis, true), 260 | self.secret_key.created_at().timestamp(), 261 | ); 262 | info!( 263 | "Fingerprint #0: {}", 264 | hex::encode_upper(self.secret_key.fingerprint().as_bytes()) 265 | ); 266 | for (i, subkey) in self.secret_key.secret_subkeys.iter().enumerate() { 267 | info!( 268 | "Fingerprint #{}: {}", 269 | i + 1, 270 | hex::encode_upper(subkey.fingerprint().as_bytes()) 271 | ); 272 | } 273 | } 274 | } 275 | --------------------------------------------------------------------------------