├── .envrc ├── .github └── workflows │ └── test.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── build.rs ├── shell.nix └── src ├── hex_lsx.c ├── hex_neon.c ├── lib.rs ├── logger ├── indicatif_backend.rs └── mod.rs ├── main.rs └── pgp_backends ├── hex.rs ├── mod.rs ├── rpgp_backend.rs └── sequoia_backend.rs /.envrc: -------------------------------------------------------------------------------- 1 | # Derived from https://github.com/nix-community/nix-direnv/blob/master/direnvrc 2 | # shellcheck shell=bash 3 | 4 | _nix_export_or_unset() { 5 | local key=$1 value=$2 6 | if [[ "$value" == __UNSET__ ]]; then 7 | unset "$key" 8 | else 9 | export "$key=$value" 10 | fi 11 | } 12 | 13 | _nix_import_env() { 14 | local env=$1 15 | 16 | local old_path=${PATH:-} 17 | local old_term=${TERM:-__UNSET__} 18 | local old_shell=${SHELL:-__UNSET__} 19 | local old_tmpdir=${TMPDIR:-__UNSET__} 20 | local old_ssl_cert_file=${SSL_CERT_FILE:-__UNSET__} 21 | local old_nix_ssl_cert_file=${NIX_SSL_CERT_FILE:-__UNSET__} 22 | 23 | eval "$env" 24 | 25 | # `nix-shell --pure` sets invalid ssl certificate paths 26 | if [[ "${SSL_CERT_FILE:-}" = /no-cert-file.crt ]]; then 27 | _nix_export_or_unset SSL_CERT_FILE "$old_ssl_cert_file" 28 | fi 29 | 30 | if [[ "${NIX_SSL_CERT_FILE:-}" = /no-cert-file.crt ]]; then 31 | _nix_export_or_unset NIX_SSL_CERT_FILE "$old_nix_ssl_cert_file" 32 | fi 33 | 34 | export PATH=$PATH${old_path:+":"}$old_path 35 | _nix_export_or_unset TERM "$old_term" 36 | _nix_export_or_unset SHELL "$old_shell" 37 | _nix_export_or_unset TEMPDIR "$old_tmpdir" 38 | 39 | # misleading since we are in an impure shell now 40 | export IN_NIX_SHELL=impure 41 | } 42 | 43 | _nix_add_gcroot() { 44 | local storepath=$1 45 | local symlink=$2 46 | 47 | local stripped_pwd=${PWD/\//} 48 | local escaped_pwd=${stripped_pwd//-/--} 49 | local escaped_pwd=${escaped_pwd//\//-} 50 | ln -fs "$storepath" "$symlink" 51 | ln -fs "$symlink" "/nix/var/nix/gcroots/per-user/$USER/$escaped_pwd" 52 | } 53 | 54 | use_flake() { 55 | watch_file flake.nix 56 | watch_file flake.lock 57 | 58 | local profile="$(direnv_layout_dir)/flake-profile" 59 | local profile_rc="${profile}.rc" 60 | 61 | if [[ ! -e "$profile" 62 | || ! -e "$profile_rc" 63 | || "$HOME/.direnvrc" -nt "$profile_rc" 64 | || .envrc -nt "$profile_rc" 65 | || flake.nix -nt "$profile_rc" 66 | || flake.lock -nt "$profile_rc" 67 | ]]; 68 | then 69 | local tmp_profile="$(direnv_layout_dir)/flake-profile.$$" 70 | [[ -d "$(direnv_layout_dir)" ]] || mkdir "$(direnv_layout_dir)" 71 | local tmp_profile_rc=$(nix print-dev-env --profile "$tmp_profile") 72 | drv=$(realpath "$tmp_profile") 73 | echo "$tmp_profile_rc" > "$profile_rc" 74 | rm -f "$tmp_profile" "$tmp_profile"* 75 | _nix_add_gcroot "$drv" "$profile" 76 | log_status renewed cache 77 | else 78 | log_status using cached dev shell 79 | fi 80 | 81 | local old_nix_build_top=${NIX_BUILD_TOP:-__UNSET__} 82 | local old_tmp=${TMP:-__UNSET__} 83 | local old_tmpdir=${TMPDIR:-__UNSET__} 84 | local old_temp=${TEMP:-__UNSET__} 85 | local old_tempdir=${TEMPDIR:-__UNSET__} 86 | eval "$(< "$profile_rc")" 87 | # nix print-env-dev will create a temporary directory and use it a TMPDIR, 88 | # we cannot rely on this directory beeing not deleted at some point, 89 | # hence we are just removing it right away. 90 | if [[ "$NIX_BUILD_TOP" == */nix-shell.* && -d "$NIX_BUILD_TOP" ]]; then 91 | rmdir "$NIX_BUILD_TOP" 92 | fi 93 | 94 | _nix_export_or_unset NIX_BUILD_TOP "$old_nix_build_top" 95 | _nix_export_or_unset TMP "$old_tmp" 96 | _nix_export_or_unset TMPDIR "$old_tmpdir" 97 | _nix_export_or_unset TEMP "$old_temp" 98 | _nix_export_or_unset TEMPDIR "$old_tempdir" 99 | } 100 | 101 | use_nix() { 102 | local path direnv_dir 103 | path=$(nix-instantiate --find-file nixpkgs) 104 | direnv_dir=$(direnv_layout_dir) 105 | 106 | if [[ "${direnv:-}" == "" ]]; then 107 | log_status "\$direnv environment variable was not defined. Was this script run inside direnv?" 108 | fi 109 | 110 | local version 111 | if [[ -f "${path}/.version-suffix" ]]; then 112 | version=$(< "${path}/.version-suffix") 113 | elif [[ -f "${path}/.git/HEAD" ]]; then 114 | local head 115 | read -r head < "${path}/.git/HEAD" 116 | local regex="ref: (.*)" 117 | if [[ "$head" =~ $regex ]]; then 118 | read -r version < ".git/${BASH_REMATCH[1]}" 119 | else 120 | version="$head" 121 | fi 122 | fi 123 | 124 | local cache="$direnv_dir/cache-${version:-unknown}" 125 | 126 | local update_drv=0 127 | if [[ ! -e "$cache" 128 | || "$HOME/.direnvrc" -nt "$cache" 129 | || .envrc -nt "$cache" 130 | || default.nix -nt "$cache" 131 | || shell.nix -nt "$cache" 132 | ]]; 133 | then 134 | [[ -d "$direnv_dir" ]] || mkdir "$direnv_dir" 135 | local dump_cmd tmp 136 | dump_cmd="echo -n _____direnv_____; \"$direnv\" dump bash" 137 | tmp=$(nix-shell --show-trace --pure "$@" --run "$dump_cmd") 138 | # show original shell hook output 139 | echo "$tmp" | perl -nle 'print if m{(?<=_____direnv_____).*}' 140 | echo "$tmp" | perl -nle 'print $& while m{(?<=_____direnv_____).*}g' > "$cache" 141 | update_drv=1 142 | else 143 | log_status using cached derivation 144 | fi 145 | 146 | log_status eval "$cache" 147 | read -r cache_content < "$cache" 148 | _nix_import_env "$cache_content" 149 | 150 | # This part is based on https://discourse.nixos.org/t/what-is-the-best-dev-workflow-around-nix-shell/418/4 151 | if [[ "${out:-}" != "" ]] && (( update_drv )); then 152 | local drv_link="${direnv_dir}/drv" drv 153 | drv=$(nix show-derivation "$out" | grep -E -o -m1 '/nix/store/.*.drv') 154 | _nix_add_gcroot "$drv" "$drv_link" 155 | log_status renewed cache and derivation link 156 | fi 157 | 158 | if [[ "$#" == 0 ]]; then 159 | watch_file default.nix 160 | watch_file shell.nix 161 | fi 162 | } 163 | 164 | use_nix 165 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-20.04 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - uses: actions-rs/toolchain@v1 20 | with: 21 | toolchain: stable 22 | - name: Install dependencies 23 | run: sudo apt-get install nettle-dev libssl-dev capnproto make clang pkg-config libsqlite3-dev llvm libclang-dev 24 | - uses: actions-rs/cargo@v1 25 | with: 26 | command: build 27 | args: --all-features --release --verbose 28 | - uses: actions-rs/cargo@v1 29 | with: 30 | command: test 31 | args: --all-features --release --verbose 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .env 3 | .out 4 | .direnv 5 | *.asc 6 | .DS_Store 7 | **/.DS_Store 8 | /.idea 9 | 10 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.20.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aes" 22 | version = "0.8.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" 25 | dependencies = [ 26 | "cfg-if", 27 | "cipher", 28 | "cpufeatures", 29 | ] 30 | 31 | [[package]] 32 | name = "aho-corasick" 33 | version = "1.0.4" 34 | source = "registry+https://github.com/rust-lang/crates.io-index" 35 | checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" 36 | dependencies = [ 37 | "memchr", 38 | ] 39 | 40 | [[package]] 41 | name = "android-tzdata" 42 | version = "0.1.1" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 45 | 46 | [[package]] 47 | name = "android_system_properties" 48 | version = "0.1.5" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 51 | dependencies = [ 52 | "libc", 53 | ] 54 | 55 | [[package]] 56 | name = "anstream" 57 | version = "0.3.2" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" 60 | dependencies = [ 61 | "anstyle", 62 | "anstyle-parse", 63 | "anstyle-query", 64 | "anstyle-wincon", 65 | "colorchoice", 66 | "is-terminal", 67 | "utf8parse", 68 | ] 69 | 70 | [[package]] 71 | name = "anstyle" 72 | version = "1.0.1" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" 75 | 76 | [[package]] 77 | name = "anstyle-parse" 78 | version = "0.2.1" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" 81 | dependencies = [ 82 | "utf8parse", 83 | ] 84 | 85 | [[package]] 86 | name = "anstyle-query" 87 | version = "1.0.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 90 | dependencies = [ 91 | "windows-sys 0.48.0", 92 | ] 93 | 94 | [[package]] 95 | name = "anstyle-wincon" 96 | version = "1.0.2" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" 99 | dependencies = [ 100 | "anstyle", 101 | "windows-sys 0.48.0", 102 | ] 103 | 104 | [[package]] 105 | name = "anyhow" 106 | version = "1.0.75" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" 109 | 110 | [[package]] 111 | name = "ascii-canvas" 112 | version = "3.0.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" 115 | dependencies = [ 116 | "term", 117 | ] 118 | 119 | [[package]] 120 | name = "autocfg" 121 | version = "1.1.0" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 124 | 125 | [[package]] 126 | name = "backtrace" 127 | version = "0.3.68" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" 130 | dependencies = [ 131 | "addr2line", 132 | "cc", 133 | "cfg-if", 134 | "libc", 135 | "miniz_oxide", 136 | "object", 137 | "rustc-demangle", 138 | ] 139 | 140 | [[package]] 141 | name = "base16ct" 142 | version = "0.2.0" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" 145 | 146 | [[package]] 147 | name = "base64" 148 | version = "0.21.2" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" 151 | 152 | [[package]] 153 | name = "base64ct" 154 | version = "1.6.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 157 | 158 | [[package]] 159 | name = "bindgen" 160 | version = "0.63.0" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" 163 | dependencies = [ 164 | "bitflags 1.3.2", 165 | "cexpr", 166 | "clang-sys", 167 | "lazy_static", 168 | "lazycell", 169 | "peeking_take_while", 170 | "proc-macro2", 171 | "quote", 172 | "regex", 173 | "rustc-hash", 174 | "shlex", 175 | "syn 1.0.109", 176 | ] 177 | 178 | [[package]] 179 | name = "bit-set" 180 | version = "0.5.3" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" 183 | dependencies = [ 184 | "bit-vec", 185 | ] 186 | 187 | [[package]] 188 | name = "bit-vec" 189 | version = "0.6.3" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" 192 | 193 | [[package]] 194 | name = "bitfield" 195 | version = "0.14.0" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" 198 | 199 | [[package]] 200 | name = "bitflags" 201 | version = "1.3.2" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 204 | 205 | [[package]] 206 | name = "bitflags" 207 | version = "2.4.0" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" 210 | 211 | [[package]] 212 | name = "block-buffer" 213 | version = "0.10.4" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 216 | dependencies = [ 217 | "generic-array", 218 | ] 219 | 220 | [[package]] 221 | name = "block-padding" 222 | version = "0.3.3" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" 225 | dependencies = [ 226 | "generic-array", 227 | ] 228 | 229 | [[package]] 230 | name = "blowfish" 231 | version = "0.9.1" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" 234 | dependencies = [ 235 | "byteorder", 236 | "cipher", 237 | ] 238 | 239 | [[package]] 240 | name = "bstr" 241 | version = "1.6.0" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" 244 | dependencies = [ 245 | "memchr", 246 | "serde", 247 | ] 248 | 249 | [[package]] 250 | name = "buffer-redux" 251 | version = "1.0.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "d2886ea01509598caac116942abd33ab5a88fa32acdf7e4abfa0fc489ca520c9" 254 | dependencies = [ 255 | "memchr", 256 | "safemem", 257 | ] 258 | 259 | [[package]] 260 | name = "buffered-reader" 261 | version = "1.2.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "66d3bea5bcc3ecc38fe5388e6bc35e6fe7bd665eb3ae9a44283e15b91ad3867d" 264 | dependencies = [ 265 | "bzip2", 266 | "flate2", 267 | "lazy_static", 268 | "libc", 269 | ] 270 | 271 | [[package]] 272 | name = "bumpalo" 273 | version = "3.13.0" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 276 | 277 | [[package]] 278 | name = "byteorder" 279 | version = "1.4.3" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 282 | 283 | [[package]] 284 | name = "bzip2" 285 | version = "0.4.4" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" 288 | dependencies = [ 289 | "bzip2-sys", 290 | "libc", 291 | ] 292 | 293 | [[package]] 294 | name = "bzip2-sys" 295 | version = "0.1.11+1.0.8" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" 298 | dependencies = [ 299 | "cc", 300 | "libc", 301 | "pkg-config", 302 | ] 303 | 304 | [[package]] 305 | name = "camellia" 306 | version = "0.1.0" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" 309 | dependencies = [ 310 | "byteorder", 311 | "cipher", 312 | ] 313 | 314 | [[package]] 315 | name = "cast5" 316 | version = "0.11.1" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" 319 | dependencies = [ 320 | "cipher", 321 | ] 322 | 323 | [[package]] 324 | name = "cc" 325 | version = "1.0.83" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 328 | dependencies = [ 329 | "libc", 330 | ] 331 | 332 | [[package]] 333 | name = "cexpr" 334 | version = "0.6.0" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 337 | dependencies = [ 338 | "nom", 339 | ] 340 | 341 | [[package]] 342 | name = "cfb-mode" 343 | version = "0.8.2" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" 346 | dependencies = [ 347 | "cipher", 348 | ] 349 | 350 | [[package]] 351 | name = "cfg-if" 352 | version = "1.0.0" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 355 | 356 | [[package]] 357 | name = "chrono" 358 | version = "0.4.26" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" 361 | dependencies = [ 362 | "android-tzdata", 363 | "iana-time-zone", 364 | "js-sys", 365 | "num-traits", 366 | "time", 367 | "wasm-bindgen", 368 | "winapi", 369 | ] 370 | 371 | [[package]] 372 | name = "cipher" 373 | version = "0.4.4" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 376 | dependencies = [ 377 | "crypto-common", 378 | "inout", 379 | ] 380 | 381 | [[package]] 382 | name = "clang-sys" 383 | version = "1.6.1" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" 386 | dependencies = [ 387 | "glob", 388 | "libc", 389 | "libloading", 390 | ] 391 | 392 | [[package]] 393 | name = "clap" 394 | version = "4.3.23" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "03aef18ddf7d879c15ce20f04826ef8418101c7e528014c3eeea13321047dca3" 397 | dependencies = [ 398 | "clap_builder", 399 | "clap_derive", 400 | "once_cell", 401 | ] 402 | 403 | [[package]] 404 | name = "clap_builder" 405 | version = "4.3.23" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "f8ce6fffb678c9b80a70b6b6de0aad31df727623a70fd9a842c30cd573e2fa98" 408 | dependencies = [ 409 | "anstream", 410 | "anstyle", 411 | "clap_lex", 412 | "strsim", 413 | ] 414 | 415 | [[package]] 416 | name = "clap_derive" 417 | version = "4.3.12" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" 420 | dependencies = [ 421 | "heck", 422 | "proc-macro2", 423 | "quote", 424 | "syn 2.0.29", 425 | ] 426 | 427 | [[package]] 428 | name = "clap_lex" 429 | version = "0.5.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" 432 | 433 | [[package]] 434 | name = "colorchoice" 435 | version = "1.0.0" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 438 | 439 | [[package]] 440 | name = "colored" 441 | version = "2.0.4" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" 444 | dependencies = [ 445 | "is-terminal", 446 | "lazy_static", 447 | "windows-sys 0.48.0", 448 | ] 449 | 450 | [[package]] 451 | name = "console" 452 | version = "0.15.7" 453 | source = "registry+https://github.com/rust-lang/crates.io-index" 454 | checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" 455 | dependencies = [ 456 | "encode_unicode", 457 | "lazy_static", 458 | "libc", 459 | "unicode-width", 460 | "windows-sys 0.45.0", 461 | ] 462 | 463 | [[package]] 464 | name = "const-oid" 465 | version = "0.9.5" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" 468 | 469 | [[package]] 470 | name = "core-foundation-sys" 471 | version = "0.8.4" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 474 | 475 | [[package]] 476 | name = "cpufeatures" 477 | version = "0.2.9" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" 480 | dependencies = [ 481 | "libc", 482 | ] 483 | 484 | [[package]] 485 | name = "crc24" 486 | version = "0.1.6" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "fd121741cf3eb82c08dd3023eb55bf2665e5f60ec20f89760cf836ae4562e6a0" 489 | 490 | [[package]] 491 | name = "crc32fast" 492 | version = "1.3.2" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 495 | dependencies = [ 496 | "cfg-if", 497 | ] 498 | 499 | [[package]] 500 | name = "crossbeam-channel" 501 | version = "0.5.8" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" 504 | dependencies = [ 505 | "cfg-if", 506 | "crossbeam-utils", 507 | ] 508 | 509 | [[package]] 510 | name = "crossbeam-deque" 511 | version = "0.8.3" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" 514 | dependencies = [ 515 | "cfg-if", 516 | "crossbeam-epoch", 517 | "crossbeam-utils", 518 | ] 519 | 520 | [[package]] 521 | name = "crossbeam-epoch" 522 | version = "0.9.15" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" 525 | dependencies = [ 526 | "autocfg", 527 | "cfg-if", 528 | "crossbeam-utils", 529 | "memoffset", 530 | "scopeguard", 531 | ] 532 | 533 | [[package]] 534 | name = "crossbeam-utils" 535 | version = "0.8.16" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 538 | dependencies = [ 539 | "cfg-if", 540 | ] 541 | 542 | [[package]] 543 | name = "crunchy" 544 | version = "0.2.2" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 547 | 548 | [[package]] 549 | name = "crypto-bigint" 550 | version = "0.5.2" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" 553 | dependencies = [ 554 | "generic-array", 555 | "rand_core 0.6.4", 556 | "subtle", 557 | "zeroize", 558 | ] 559 | 560 | [[package]] 561 | name = "crypto-common" 562 | version = "0.1.6" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 565 | dependencies = [ 566 | "generic-array", 567 | "typenum", 568 | ] 569 | 570 | [[package]] 571 | name = "curve25519-dalek" 572 | version = "4.0.0" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "f711ade317dd348950a9910f81c5947e3d8907ebd2b83f76203ff1807e6a2bc2" 575 | dependencies = [ 576 | "cfg-if", 577 | "cpufeatures", 578 | "curve25519-dalek-derive", 579 | "digest 0.10.7", 580 | "fiat-crypto", 581 | "platforms", 582 | "rustc_version", 583 | "subtle", 584 | "zeroize", 585 | ] 586 | 587 | [[package]] 588 | name = "curve25519-dalek-derive" 589 | version = "0.1.0" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" 592 | dependencies = [ 593 | "proc-macro2", 594 | "quote", 595 | "syn 2.0.29", 596 | ] 597 | 598 | [[package]] 599 | name = "darling" 600 | version = "0.14.4" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" 603 | dependencies = [ 604 | "darling_core", 605 | "darling_macro", 606 | ] 607 | 608 | [[package]] 609 | name = "darling_core" 610 | version = "0.14.4" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" 613 | dependencies = [ 614 | "fnv", 615 | "ident_case", 616 | "proc-macro2", 617 | "quote", 618 | "strsim", 619 | "syn 1.0.109", 620 | ] 621 | 622 | [[package]] 623 | name = "darling_macro" 624 | version = "0.14.4" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" 627 | dependencies = [ 628 | "darling_core", 629 | "quote", 630 | "syn 1.0.109", 631 | ] 632 | 633 | [[package]] 634 | name = "der" 635 | version = "0.7.8" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" 638 | dependencies = [ 639 | "const-oid", 640 | "pem-rfc7468", 641 | "zeroize", 642 | ] 643 | 644 | [[package]] 645 | name = "derive_builder" 646 | version = "0.12.0" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" 649 | dependencies = [ 650 | "derive_builder_macro", 651 | ] 652 | 653 | [[package]] 654 | name = "derive_builder_core" 655 | version = "0.12.0" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" 658 | dependencies = [ 659 | "darling", 660 | "proc-macro2", 661 | "quote", 662 | "syn 1.0.109", 663 | ] 664 | 665 | [[package]] 666 | name = "derive_builder_macro" 667 | version = "0.12.0" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" 670 | dependencies = [ 671 | "derive_builder_core", 672 | "syn 1.0.109", 673 | ] 674 | 675 | [[package]] 676 | name = "des" 677 | version = "0.8.1" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" 680 | dependencies = [ 681 | "cipher", 682 | ] 683 | 684 | [[package]] 685 | name = "diff" 686 | version = "0.1.13" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" 689 | 690 | [[package]] 691 | name = "digest" 692 | version = "0.9.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 695 | dependencies = [ 696 | "generic-array", 697 | ] 698 | 699 | [[package]] 700 | name = "digest" 701 | version = "0.10.7" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 704 | dependencies = [ 705 | "block-buffer", 706 | "const-oid", 707 | "crypto-common", 708 | "subtle", 709 | ] 710 | 711 | [[package]] 712 | name = "dirs-next" 713 | version = "2.0.0" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 716 | dependencies = [ 717 | "cfg-if", 718 | "dirs-sys-next", 719 | ] 720 | 721 | [[package]] 722 | name = "dirs-sys-next" 723 | version = "0.1.2" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 726 | dependencies = [ 727 | "libc", 728 | "redox_users", 729 | "winapi", 730 | ] 731 | 732 | [[package]] 733 | name = "dyn-clone" 734 | version = "1.0.13" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" 737 | 738 | [[package]] 739 | name = "ecdsa" 740 | version = "0.16.8" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" 743 | dependencies = [ 744 | "der", 745 | "digest 0.10.7", 746 | "elliptic-curve", 747 | "rfc6979", 748 | "signature", 749 | "spki", 750 | ] 751 | 752 | [[package]] 753 | name = "ed25519" 754 | version = "2.2.2" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" 757 | dependencies = [ 758 | "pkcs8", 759 | "signature", 760 | ] 761 | 762 | [[package]] 763 | name = "ed25519-dalek" 764 | version = "2.0.0" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" 767 | dependencies = [ 768 | "curve25519-dalek", 769 | "ed25519", 770 | "serde", 771 | "sha2", 772 | "zeroize", 773 | ] 774 | 775 | [[package]] 776 | name = "either" 777 | version = "1.9.0" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" 780 | 781 | [[package]] 782 | name = "elliptic-curve" 783 | version = "0.13.5" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" 786 | dependencies = [ 787 | "base16ct", 788 | "crypto-bigint", 789 | "digest 0.10.7", 790 | "ff", 791 | "generic-array", 792 | "group", 793 | "hkdf", 794 | "pem-rfc7468", 795 | "pkcs8", 796 | "rand_core 0.6.4", 797 | "sec1", 798 | "subtle", 799 | "zeroize", 800 | ] 801 | 802 | [[package]] 803 | name = "ena" 804 | version = "0.14.2" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" 807 | dependencies = [ 808 | "log", 809 | ] 810 | 811 | [[package]] 812 | name = "encode_unicode" 813 | version = "0.3.6" 814 | source = "registry+https://github.com/rust-lang/crates.io-index" 815 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 816 | 817 | [[package]] 818 | name = "errno" 819 | version = "0.3.2" 820 | source = "registry+https://github.com/rust-lang/crates.io-index" 821 | checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" 822 | dependencies = [ 823 | "errno-dragonfly", 824 | "libc", 825 | "windows-sys 0.48.0", 826 | ] 827 | 828 | [[package]] 829 | name = "errno-dragonfly" 830 | version = "0.1.2" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 833 | dependencies = [ 834 | "cc", 835 | "libc", 836 | ] 837 | 838 | [[package]] 839 | name = "fastrand" 840 | version = "2.0.0" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" 843 | 844 | [[package]] 845 | name = "ff" 846 | version = "0.13.0" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" 849 | dependencies = [ 850 | "rand_core 0.6.4", 851 | "subtle", 852 | ] 853 | 854 | [[package]] 855 | name = "fiat-crypto" 856 | version = "0.1.20" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" 859 | 860 | [[package]] 861 | name = "fixedbitset" 862 | version = "0.4.2" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 865 | 866 | [[package]] 867 | name = "flate2" 868 | version = "1.0.27" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" 871 | dependencies = [ 872 | "crc32fast", 873 | "miniz_oxide", 874 | ] 875 | 876 | [[package]] 877 | name = "fnv" 878 | version = "1.0.7" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 881 | 882 | [[package]] 883 | name = "generic-array" 884 | version = "0.14.7" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 887 | dependencies = [ 888 | "typenum", 889 | "version_check", 890 | "zeroize", 891 | ] 892 | 893 | [[package]] 894 | name = "getrandom" 895 | version = "0.1.16" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 898 | dependencies = [ 899 | "cfg-if", 900 | "js-sys", 901 | "libc", 902 | "wasi 0.9.0+wasi-snapshot-preview1", 903 | "wasm-bindgen", 904 | ] 905 | 906 | [[package]] 907 | name = "getrandom" 908 | version = "0.2.10" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" 911 | dependencies = [ 912 | "cfg-if", 913 | "js-sys", 914 | "libc", 915 | "wasi 0.11.0+wasi-snapshot-preview1", 916 | "wasm-bindgen", 917 | ] 918 | 919 | [[package]] 920 | name = "gimli" 921 | version = "0.27.3" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" 924 | 925 | [[package]] 926 | name = "glob" 927 | version = "0.3.1" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 930 | 931 | [[package]] 932 | name = "group" 933 | version = "0.13.0" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" 936 | dependencies = [ 937 | "ff", 938 | "rand_core 0.6.4", 939 | "subtle", 940 | ] 941 | 942 | [[package]] 943 | name = "hashbrown" 944 | version = "0.12.3" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 947 | 948 | [[package]] 949 | name = "heck" 950 | version = "0.4.1" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 953 | 954 | [[package]] 955 | name = "hermit-abi" 956 | version = "0.3.2" 957 | source = "registry+https://github.com/rust-lang/crates.io-index" 958 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 959 | 960 | [[package]] 961 | name = "hex" 962 | version = "0.4.3" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 965 | 966 | [[package]] 967 | name = "hkdf" 968 | version = "0.12.3" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" 971 | dependencies = [ 972 | "hmac", 973 | ] 974 | 975 | [[package]] 976 | name = "hmac" 977 | version = "0.12.1" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 980 | dependencies = [ 981 | "digest 0.10.7", 982 | ] 983 | 984 | [[package]] 985 | name = "iana-time-zone" 986 | version = "0.1.57" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" 989 | dependencies = [ 990 | "android_system_properties", 991 | "core-foundation-sys", 992 | "iana-time-zone-haiku", 993 | "js-sys", 994 | "wasm-bindgen", 995 | "windows", 996 | ] 997 | 998 | [[package]] 999 | name = "iana-time-zone-haiku" 1000 | version = "0.1.2" 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" 1002 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1003 | dependencies = [ 1004 | "cc", 1005 | ] 1006 | 1007 | [[package]] 1008 | name = "idea" 1009 | version = "0.5.1" 1010 | source = "registry+https://github.com/rust-lang/crates.io-index" 1011 | checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" 1012 | dependencies = [ 1013 | "cipher", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "ident_case" 1018 | version = "1.0.1" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1021 | 1022 | [[package]] 1023 | name = "idna" 1024 | version = "0.3.0" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 1027 | dependencies = [ 1028 | "unicode-bidi", 1029 | "unicode-normalization", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "indexmap" 1034 | version = "1.9.3" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 1037 | dependencies = [ 1038 | "autocfg", 1039 | "hashbrown", 1040 | ] 1041 | 1042 | [[package]] 1043 | name = "indicatif" 1044 | version = "0.17.6" 1045 | source = "registry+https://github.com/rust-lang/crates.io-index" 1046 | checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" 1047 | dependencies = [ 1048 | "console", 1049 | "instant", 1050 | "number_prefix", 1051 | "portable-atomic", 1052 | "unicode-width", 1053 | ] 1054 | 1055 | [[package]] 1056 | name = "inout" 1057 | version = "0.1.3" 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" 1059 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 1060 | dependencies = [ 1061 | "generic-array", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "instant" 1066 | version = "0.1.12" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 1069 | dependencies = [ 1070 | "cfg-if", 1071 | ] 1072 | 1073 | [[package]] 1074 | name = "is-terminal" 1075 | version = "0.4.9" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" 1078 | dependencies = [ 1079 | "hermit-abi", 1080 | "rustix", 1081 | "windows-sys 0.48.0", 1082 | ] 1083 | 1084 | [[package]] 1085 | name = "itertools" 1086 | version = "0.10.5" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 1089 | dependencies = [ 1090 | "either", 1091 | ] 1092 | 1093 | [[package]] 1094 | name = "js-sys" 1095 | version = "0.3.64" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 1098 | dependencies = [ 1099 | "wasm-bindgen", 1100 | ] 1101 | 1102 | [[package]] 1103 | name = "keccak" 1104 | version = "0.1.4" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" 1107 | dependencies = [ 1108 | "cpufeatures", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "lalrpop" 1113 | version = "0.19.12" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" 1116 | dependencies = [ 1117 | "ascii-canvas", 1118 | "bit-set", 1119 | "diff", 1120 | "ena", 1121 | "is-terminal", 1122 | "itertools", 1123 | "lalrpop-util", 1124 | "petgraph", 1125 | "regex", 1126 | "regex-syntax 0.6.29", 1127 | "string_cache", 1128 | "term", 1129 | "tiny-keccak", 1130 | "unicode-xid", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "lalrpop-util" 1135 | version = "0.19.12" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" 1138 | 1139 | [[package]] 1140 | name = "lazy_static" 1141 | version = "1.4.0" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1144 | dependencies = [ 1145 | "spin", 1146 | ] 1147 | 1148 | [[package]] 1149 | name = "lazycell" 1150 | version = "1.3.0" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 1153 | 1154 | [[package]] 1155 | name = "libc" 1156 | version = "0.2.147" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 1159 | 1160 | [[package]] 1161 | name = "libloading" 1162 | version = "0.7.4" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 1165 | dependencies = [ 1166 | "cfg-if", 1167 | "winapi", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "libm" 1172 | version = "0.2.7" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" 1175 | 1176 | [[package]] 1177 | name = "libmimalloc-sys" 1178 | version = "0.1.33" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" 1181 | dependencies = [ 1182 | "cc", 1183 | "libc", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "linux-raw-sys" 1188 | version = "0.4.5" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" 1191 | 1192 | [[package]] 1193 | name = "lock_api" 1194 | version = "0.4.10" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 1197 | dependencies = [ 1198 | "autocfg", 1199 | "scopeguard", 1200 | ] 1201 | 1202 | [[package]] 1203 | name = "log" 1204 | version = "0.4.20" 1205 | source = "registry+https://github.com/rust-lang/crates.io-index" 1206 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 1207 | 1208 | [[package]] 1209 | name = "md-5" 1210 | version = "0.10.5" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" 1213 | dependencies = [ 1214 | "digest 0.10.7", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "memchr" 1219 | version = "2.5.0" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 1222 | 1223 | [[package]] 1224 | name = "memoffset" 1225 | version = "0.9.0" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" 1228 | dependencies = [ 1229 | "autocfg", 1230 | ] 1231 | 1232 | [[package]] 1233 | name = "memsec" 1234 | version = "0.6.3" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "0fa0916b001582d253822171bd23f4a0229d32b9507fae236f5da8cad515ba7c" 1237 | 1238 | [[package]] 1239 | name = "mimalloc" 1240 | version = "0.1.37" 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" 1242 | checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" 1243 | dependencies = [ 1244 | "libmimalloc-sys", 1245 | ] 1246 | 1247 | [[package]] 1248 | name = "minimal-lexical" 1249 | version = "0.2.1" 1250 | source = "registry+https://github.com/rust-lang/crates.io-index" 1251 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1252 | 1253 | [[package]] 1254 | name = "miniz_oxide" 1255 | version = "0.7.1" 1256 | source = "registry+https://github.com/rust-lang/crates.io-index" 1257 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 1258 | dependencies = [ 1259 | "adler", 1260 | ] 1261 | 1262 | [[package]] 1263 | name = "nettle" 1264 | version = "7.3.0" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "b9fdccf3eae7b161910d2daa2f0155ca35041322e8fe5c5f1f2c9d0b12356336" 1267 | dependencies = [ 1268 | "getrandom 0.2.10", 1269 | "libc", 1270 | "nettle-sys", 1271 | "thiserror", 1272 | "typenum", 1273 | ] 1274 | 1275 | [[package]] 1276 | name = "nettle-sys" 1277 | version = "2.2.0" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "b5e81c347b9002da0b6b0c4060993c280e99eb14b42ecf65a2fefcd6eb3d8a73" 1280 | dependencies = [ 1281 | "bindgen", 1282 | "cc", 1283 | "libc", 1284 | "pkg-config", 1285 | "tempfile", 1286 | "vcpkg", 1287 | ] 1288 | 1289 | [[package]] 1290 | name = "new_debug_unreachable" 1291 | version = "1.0.4" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" 1294 | 1295 | [[package]] 1296 | name = "nom" 1297 | version = "7.1.3" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1300 | dependencies = [ 1301 | "memchr", 1302 | "minimal-lexical", 1303 | ] 1304 | 1305 | [[package]] 1306 | name = "num-bigint-dig" 1307 | version = "0.8.4" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 1310 | dependencies = [ 1311 | "byteorder", 1312 | "lazy_static", 1313 | "libm", 1314 | "num-integer", 1315 | "num-iter", 1316 | "num-traits", 1317 | "rand 0.8.5", 1318 | "serde", 1319 | "smallvec", 1320 | "zeroize", 1321 | ] 1322 | 1323 | [[package]] 1324 | name = "num-derive" 1325 | version = "0.4.0" 1326 | source = "registry+https://github.com/rust-lang/crates.io-index" 1327 | checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e" 1328 | dependencies = [ 1329 | "proc-macro2", 1330 | "quote", 1331 | "syn 2.0.29", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "num-integer" 1336 | version = "0.1.45" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 1339 | dependencies = [ 1340 | "autocfg", 1341 | "num-traits", 1342 | ] 1343 | 1344 | [[package]] 1345 | name = "num-iter" 1346 | version = "0.1.43" 1347 | source = "registry+https://github.com/rust-lang/crates.io-index" 1348 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 1349 | dependencies = [ 1350 | "autocfg", 1351 | "num-integer", 1352 | "num-traits", 1353 | ] 1354 | 1355 | [[package]] 1356 | name = "num-traits" 1357 | version = "0.2.16" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" 1360 | dependencies = [ 1361 | "autocfg", 1362 | "libm", 1363 | ] 1364 | 1365 | [[package]] 1366 | name = "num_cpus" 1367 | version = "1.16.0" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 1370 | dependencies = [ 1371 | "hermit-abi", 1372 | "libc", 1373 | ] 1374 | 1375 | [[package]] 1376 | name = "number_prefix" 1377 | version = "0.4.0" 1378 | source = "registry+https://github.com/rust-lang/crates.io-index" 1379 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 1380 | 1381 | [[package]] 1382 | name = "object" 1383 | version = "0.31.1" 1384 | source = "registry+https://github.com/rust-lang/crates.io-index" 1385 | checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" 1386 | dependencies = [ 1387 | "memchr", 1388 | ] 1389 | 1390 | [[package]] 1391 | name = "once_cell" 1392 | version = "1.18.0" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 1395 | 1396 | [[package]] 1397 | name = "p256" 1398 | version = "0.13.2" 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" 1400 | checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" 1401 | dependencies = [ 1402 | "ecdsa", 1403 | "elliptic-curve", 1404 | "primeorder", 1405 | "sha2", 1406 | ] 1407 | 1408 | [[package]] 1409 | name = "p384" 1410 | version = "0.13.0" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" 1413 | dependencies = [ 1414 | "ecdsa", 1415 | "elliptic-curve", 1416 | "primeorder", 1417 | "sha2", 1418 | ] 1419 | 1420 | [[package]] 1421 | name = "parking_lot" 1422 | version = "0.12.1" 1423 | source = "registry+https://github.com/rust-lang/crates.io-index" 1424 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1425 | dependencies = [ 1426 | "lock_api", 1427 | "parking_lot_core", 1428 | ] 1429 | 1430 | [[package]] 1431 | name = "parking_lot_core" 1432 | version = "0.9.8" 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" 1434 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 1435 | dependencies = [ 1436 | "cfg-if", 1437 | "libc", 1438 | "redox_syscall 0.3.5", 1439 | "smallvec", 1440 | "windows-targets 0.48.5", 1441 | ] 1442 | 1443 | [[package]] 1444 | name = "peeking_take_while" 1445 | version = "0.1.2" 1446 | source = "registry+https://github.com/rust-lang/crates.io-index" 1447 | checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" 1448 | 1449 | [[package]] 1450 | name = "pem-rfc7468" 1451 | version = "0.7.0" 1452 | source = "registry+https://github.com/rust-lang/crates.io-index" 1453 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 1454 | dependencies = [ 1455 | "base64ct", 1456 | ] 1457 | 1458 | [[package]] 1459 | name = "petgraph" 1460 | version = "0.6.3" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" 1463 | dependencies = [ 1464 | "fixedbitset", 1465 | "indexmap", 1466 | ] 1467 | 1468 | [[package]] 1469 | name = "pgp" 1470 | version = "0.10.2" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "27e1f8e085bfa9b85763fe3ddaacbe90a09cd847b3833129153a6cb063bbe132" 1473 | dependencies = [ 1474 | "aes", 1475 | "base64", 1476 | "bitfield", 1477 | "block-padding", 1478 | "blowfish", 1479 | "bstr", 1480 | "buffer-redux", 1481 | "byteorder", 1482 | "camellia", 1483 | "cast5", 1484 | "cfb-mode", 1485 | "chrono", 1486 | "cipher", 1487 | "crc24", 1488 | "curve25519-dalek", 1489 | "derive_builder", 1490 | "des", 1491 | "digest 0.10.7", 1492 | "ed25519-dalek", 1493 | "elliptic-curve", 1494 | "flate2", 1495 | "generic-array", 1496 | "hex", 1497 | "idea", 1498 | "log", 1499 | "md-5", 1500 | "nom", 1501 | "num-bigint-dig", 1502 | "num-derive", 1503 | "num-traits", 1504 | "p256", 1505 | "p384", 1506 | "rand 0.8.5", 1507 | "ripemd", 1508 | "rsa", 1509 | "sha1", 1510 | "sha2", 1511 | "sha3", 1512 | "signature", 1513 | "smallvec", 1514 | "thiserror", 1515 | "twofish", 1516 | "x25519-dalek", 1517 | "zeroize", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "phf_shared" 1522 | version = "0.10.0" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" 1525 | dependencies = [ 1526 | "siphasher", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "pkcs1" 1531 | version = "0.7.5" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 1534 | dependencies = [ 1535 | "der", 1536 | "pkcs8", 1537 | "spki", 1538 | ] 1539 | 1540 | [[package]] 1541 | name = "pkcs8" 1542 | version = "0.10.2" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1545 | dependencies = [ 1546 | "der", 1547 | "spki", 1548 | ] 1549 | 1550 | [[package]] 1551 | name = "pkg-config" 1552 | version = "0.3.27" 1553 | source = "registry+https://github.com/rust-lang/crates.io-index" 1554 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 1555 | 1556 | [[package]] 1557 | name = "platforms" 1558 | version = "3.0.2" 1559 | source = "registry+https://github.com/rust-lang/crates.io-index" 1560 | checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" 1561 | 1562 | [[package]] 1563 | name = "portable-atomic" 1564 | version = "1.4.2" 1565 | source = "registry+https://github.com/rust-lang/crates.io-index" 1566 | checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" 1567 | 1568 | [[package]] 1569 | name = "ppv-lite86" 1570 | version = "0.2.17" 1571 | source = "registry+https://github.com/rust-lang/crates.io-index" 1572 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1573 | 1574 | [[package]] 1575 | name = "precomputed-hash" 1576 | version = "0.1.1" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 1579 | 1580 | [[package]] 1581 | name = "primeorder" 1582 | version = "0.13.2" 1583 | source = "registry+https://github.com/rust-lang/crates.io-index" 1584 | checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" 1585 | dependencies = [ 1586 | "elliptic-curve", 1587 | ] 1588 | 1589 | [[package]] 1590 | name = "proc-macro2" 1591 | version = "1.0.66" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" 1594 | dependencies = [ 1595 | "unicode-ident", 1596 | ] 1597 | 1598 | [[package]] 1599 | name = "quote" 1600 | version = "1.0.33" 1601 | source = "registry+https://github.com/rust-lang/crates.io-index" 1602 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 1603 | dependencies = [ 1604 | "proc-macro2", 1605 | ] 1606 | 1607 | [[package]] 1608 | name = "rand" 1609 | version = "0.7.3" 1610 | source = "registry+https://github.com/rust-lang/crates.io-index" 1611 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1612 | dependencies = [ 1613 | "getrandom 0.1.16", 1614 | "libc", 1615 | "rand_chacha 0.2.2", 1616 | "rand_core 0.5.1", 1617 | "rand_hc", 1618 | ] 1619 | 1620 | [[package]] 1621 | name = "rand" 1622 | version = "0.8.5" 1623 | source = "registry+https://github.com/rust-lang/crates.io-index" 1624 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1625 | dependencies = [ 1626 | "libc", 1627 | "rand_chacha 0.3.1", 1628 | "rand_core 0.6.4", 1629 | ] 1630 | 1631 | [[package]] 1632 | name = "rand_chacha" 1633 | version = "0.2.2" 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" 1635 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1636 | dependencies = [ 1637 | "ppv-lite86", 1638 | "rand_core 0.5.1", 1639 | ] 1640 | 1641 | [[package]] 1642 | name = "rand_chacha" 1643 | version = "0.3.1" 1644 | source = "registry+https://github.com/rust-lang/crates.io-index" 1645 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1646 | dependencies = [ 1647 | "ppv-lite86", 1648 | "rand_core 0.6.4", 1649 | ] 1650 | 1651 | [[package]] 1652 | name = "rand_core" 1653 | version = "0.5.1" 1654 | source = "registry+https://github.com/rust-lang/crates.io-index" 1655 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1656 | dependencies = [ 1657 | "getrandom 0.1.16", 1658 | ] 1659 | 1660 | [[package]] 1661 | name = "rand_core" 1662 | version = "0.6.4" 1663 | source = "registry+https://github.com/rust-lang/crates.io-index" 1664 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1665 | dependencies = [ 1666 | "getrandom 0.2.10", 1667 | ] 1668 | 1669 | [[package]] 1670 | name = "rand_hc" 1671 | version = "0.2.0" 1672 | source = "registry+https://github.com/rust-lang/crates.io-index" 1673 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1674 | dependencies = [ 1675 | "rand_core 0.5.1", 1676 | ] 1677 | 1678 | [[package]] 1679 | name = "rayon" 1680 | version = "1.7.0" 1681 | source = "registry+https://github.com/rust-lang/crates.io-index" 1682 | checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" 1683 | dependencies = [ 1684 | "either", 1685 | "rayon-core", 1686 | ] 1687 | 1688 | [[package]] 1689 | name = "rayon-core" 1690 | version = "1.11.0" 1691 | source = "registry+https://github.com/rust-lang/crates.io-index" 1692 | checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" 1693 | dependencies = [ 1694 | "crossbeam-channel", 1695 | "crossbeam-deque", 1696 | "crossbeam-utils", 1697 | "num_cpus", 1698 | ] 1699 | 1700 | [[package]] 1701 | name = "redox_syscall" 1702 | version = "0.2.16" 1703 | source = "registry+https://github.com/rust-lang/crates.io-index" 1704 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1705 | dependencies = [ 1706 | "bitflags 1.3.2", 1707 | ] 1708 | 1709 | [[package]] 1710 | name = "redox_syscall" 1711 | version = "0.3.5" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 1714 | dependencies = [ 1715 | "bitflags 1.3.2", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "redox_users" 1720 | version = "0.4.3" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1723 | dependencies = [ 1724 | "getrandom 0.2.10", 1725 | "redox_syscall 0.2.16", 1726 | "thiserror", 1727 | ] 1728 | 1729 | [[package]] 1730 | name = "regex" 1731 | version = "1.9.3" 1732 | source = "registry+https://github.com/rust-lang/crates.io-index" 1733 | checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" 1734 | dependencies = [ 1735 | "aho-corasick", 1736 | "memchr", 1737 | "regex-automata", 1738 | "regex-syntax 0.7.4", 1739 | ] 1740 | 1741 | [[package]] 1742 | name = "regex-automata" 1743 | version = "0.3.6" 1744 | source = "registry+https://github.com/rust-lang/crates.io-index" 1745 | checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" 1746 | dependencies = [ 1747 | "aho-corasick", 1748 | "memchr", 1749 | "regex-syntax 0.7.4", 1750 | ] 1751 | 1752 | [[package]] 1753 | name = "regex-syntax" 1754 | version = "0.6.29" 1755 | source = "registry+https://github.com/rust-lang/crates.io-index" 1756 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 1757 | 1758 | [[package]] 1759 | name = "regex-syntax" 1760 | version = "0.7.4" 1761 | source = "registry+https://github.com/rust-lang/crates.io-index" 1762 | checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" 1763 | 1764 | [[package]] 1765 | name = "rfc6979" 1766 | version = "0.4.0" 1767 | source = "registry+https://github.com/rust-lang/crates.io-index" 1768 | checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" 1769 | dependencies = [ 1770 | "hmac", 1771 | "subtle", 1772 | ] 1773 | 1774 | [[package]] 1775 | name = "ripemd" 1776 | version = "0.1.3" 1777 | source = "registry+https://github.com/rust-lang/crates.io-index" 1778 | checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" 1779 | dependencies = [ 1780 | "digest 0.10.7", 1781 | ] 1782 | 1783 | [[package]] 1784 | name = "rsa" 1785 | version = "0.9.2" 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" 1787 | checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" 1788 | dependencies = [ 1789 | "byteorder", 1790 | "const-oid", 1791 | "digest 0.10.7", 1792 | "num-bigint-dig", 1793 | "num-integer", 1794 | "num-iter", 1795 | "num-traits", 1796 | "pkcs1", 1797 | "pkcs8", 1798 | "rand_core 0.6.4", 1799 | "signature", 1800 | "spki", 1801 | "subtle", 1802 | "zeroize", 1803 | ] 1804 | 1805 | [[package]] 1806 | name = "rustc-demangle" 1807 | version = "0.1.23" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 1810 | 1811 | [[package]] 1812 | name = "rustc-hash" 1813 | version = "1.1.0" 1814 | source = "registry+https://github.com/rust-lang/crates.io-index" 1815 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 1816 | 1817 | [[package]] 1818 | name = "rustc_version" 1819 | version = "0.4.0" 1820 | source = "registry+https://github.com/rust-lang/crates.io-index" 1821 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 1822 | dependencies = [ 1823 | "semver", 1824 | ] 1825 | 1826 | [[package]] 1827 | name = "rustix" 1828 | version = "0.38.8" 1829 | source = "registry+https://github.com/rust-lang/crates.io-index" 1830 | checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" 1831 | dependencies = [ 1832 | "bitflags 2.4.0", 1833 | "errno", 1834 | "libc", 1835 | "linux-raw-sys", 1836 | "windows-sys 0.48.0", 1837 | ] 1838 | 1839 | [[package]] 1840 | name = "rustversion" 1841 | version = "1.0.14" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 1844 | 1845 | [[package]] 1846 | name = "safemem" 1847 | version = "0.3.3" 1848 | source = "registry+https://github.com/rust-lang/crates.io-index" 1849 | checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" 1850 | 1851 | [[package]] 1852 | name = "scopeguard" 1853 | version = "1.2.0" 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" 1855 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1856 | 1857 | [[package]] 1858 | name = "sec1" 1859 | version = "0.7.3" 1860 | source = "registry+https://github.com/rust-lang/crates.io-index" 1861 | checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" 1862 | dependencies = [ 1863 | "base16ct", 1864 | "der", 1865 | "generic-array", 1866 | "pkcs8", 1867 | "subtle", 1868 | "zeroize", 1869 | ] 1870 | 1871 | [[package]] 1872 | name = "semver" 1873 | version = "1.0.18" 1874 | source = "registry+https://github.com/rust-lang/crates.io-index" 1875 | checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" 1876 | 1877 | [[package]] 1878 | name = "sequoia-openpgp" 1879 | version = "1.16.0" 1880 | source = "registry+https://github.com/rust-lang/crates.io-index" 1881 | checksum = "30efff3f9930e85b4284e76bbdad741f36412dfb1e370efd0de5866ae1a11dfc" 1882 | dependencies = [ 1883 | "anyhow", 1884 | "base64", 1885 | "buffered-reader", 1886 | "bzip2", 1887 | "chrono", 1888 | "dyn-clone", 1889 | "flate2", 1890 | "getrandom 0.2.10", 1891 | "idna", 1892 | "lalrpop", 1893 | "lalrpop-util", 1894 | "lazy_static", 1895 | "libc", 1896 | "memsec", 1897 | "nettle", 1898 | "once_cell", 1899 | "rand 0.7.3", 1900 | "regex", 1901 | "regex-syntax 0.6.29", 1902 | "sha1collisiondetection", 1903 | "thiserror", 1904 | "xxhash-rust", 1905 | ] 1906 | 1907 | [[package]] 1908 | name = "serde" 1909 | version = "1.0.184" 1910 | source = "registry+https://github.com/rust-lang/crates.io-index" 1911 | checksum = "2c911f4b04d7385c9035407a4eff5903bf4fe270fa046fda448b69e797f4fff0" 1912 | dependencies = [ 1913 | "serde_derive", 1914 | ] 1915 | 1916 | [[package]] 1917 | name = "serde_derive" 1918 | version = "1.0.184" 1919 | source = "registry+https://github.com/rust-lang/crates.io-index" 1920 | checksum = "c1df27f5b29406ada06609b2e2f77fb34f6dbb104a457a671cc31dbed237e09e" 1921 | dependencies = [ 1922 | "proc-macro2", 1923 | "quote", 1924 | "syn 2.0.29", 1925 | ] 1926 | 1927 | [[package]] 1928 | name = "sha-1" 1929 | version = "0.10.1" 1930 | source = "registry+https://github.com/rust-lang/crates.io-index" 1931 | checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" 1932 | dependencies = [ 1933 | "cfg-if", 1934 | "cpufeatures", 1935 | "digest 0.10.7", 1936 | "sha1-asm", 1937 | ] 1938 | 1939 | [[package]] 1940 | name = "sha1" 1941 | version = "0.10.5" 1942 | source = "registry+https://github.com/rust-lang/crates.io-index" 1943 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1944 | dependencies = [ 1945 | "cfg-if", 1946 | "cpufeatures", 1947 | "digest 0.10.7", 1948 | ] 1949 | 1950 | [[package]] 1951 | name = "sha1-asm" 1952 | version = "0.5.2" 1953 | source = "registry+https://github.com/rust-lang/crates.io-index" 1954 | checksum = "2ba6947745e7f86be3b8af00b7355857085dbdf8901393c89514510eb61f4e21" 1955 | dependencies = [ 1956 | "cc", 1957 | ] 1958 | 1959 | [[package]] 1960 | name = "sha1collisiondetection" 1961 | version = "0.2.7" 1962 | source = "registry+https://github.com/rust-lang/crates.io-index" 1963 | checksum = "b20793cf8330b2c7da4c438116660fed24e380bcb8a1bcfff2581b5593a0b38e" 1964 | dependencies = [ 1965 | "digest 0.9.0", 1966 | "generic-array", 1967 | ] 1968 | 1969 | [[package]] 1970 | name = "sha2" 1971 | version = "0.10.7" 1972 | source = "registry+https://github.com/rust-lang/crates.io-index" 1973 | checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" 1974 | dependencies = [ 1975 | "cfg-if", 1976 | "cpufeatures", 1977 | "digest 0.10.7", 1978 | ] 1979 | 1980 | [[package]] 1981 | name = "sha3" 1982 | version = "0.10.8" 1983 | source = "registry+https://github.com/rust-lang/crates.io-index" 1984 | checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" 1985 | dependencies = [ 1986 | "digest 0.10.7", 1987 | "keccak", 1988 | ] 1989 | 1990 | [[package]] 1991 | name = "shlex" 1992 | version = "1.1.0" 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" 1994 | checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" 1995 | 1996 | [[package]] 1997 | name = "signature" 1998 | version = "2.1.0" 1999 | source = "registry+https://github.com/rust-lang/crates.io-index" 2000 | checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" 2001 | dependencies = [ 2002 | "digest 0.10.7", 2003 | "rand_core 0.6.4", 2004 | ] 2005 | 2006 | [[package]] 2007 | name = "siphasher" 2008 | version = "0.3.10" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" 2011 | 2012 | [[package]] 2013 | name = "smallvec" 2014 | version = "1.11.0" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" 2017 | 2018 | [[package]] 2019 | name = "spin" 2020 | version = "0.5.2" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 2023 | 2024 | [[package]] 2025 | name = "spki" 2026 | version = "0.7.2" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" 2029 | dependencies = [ 2030 | "base64ct", 2031 | "der", 2032 | ] 2033 | 2034 | [[package]] 2035 | name = "string_cache" 2036 | version = "0.8.7" 2037 | source = "registry+https://github.com/rust-lang/crates.io-index" 2038 | checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" 2039 | dependencies = [ 2040 | "new_debug_unreachable", 2041 | "once_cell", 2042 | "parking_lot", 2043 | "phf_shared", 2044 | "precomputed-hash", 2045 | ] 2046 | 2047 | [[package]] 2048 | name = "strsim" 2049 | version = "0.10.0" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2052 | 2053 | [[package]] 2054 | name = "subtle" 2055 | version = "2.5.0" 2056 | source = "registry+https://github.com/rust-lang/crates.io-index" 2057 | checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" 2058 | 2059 | [[package]] 2060 | name = "syn" 2061 | version = "1.0.109" 2062 | source = "registry+https://github.com/rust-lang/crates.io-index" 2063 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 2064 | dependencies = [ 2065 | "proc-macro2", 2066 | "quote", 2067 | "unicode-ident", 2068 | ] 2069 | 2070 | [[package]] 2071 | name = "syn" 2072 | version = "2.0.29" 2073 | source = "registry+https://github.com/rust-lang/crates.io-index" 2074 | checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" 2075 | dependencies = [ 2076 | "proc-macro2", 2077 | "quote", 2078 | "unicode-ident", 2079 | ] 2080 | 2081 | [[package]] 2082 | name = "tempfile" 2083 | version = "3.8.0" 2084 | source = "registry+https://github.com/rust-lang/crates.io-index" 2085 | checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" 2086 | dependencies = [ 2087 | "cfg-if", 2088 | "fastrand", 2089 | "redox_syscall 0.3.5", 2090 | "rustix", 2091 | "windows-sys 0.48.0", 2092 | ] 2093 | 2094 | [[package]] 2095 | name = "term" 2096 | version = "0.7.0" 2097 | source = "registry+https://github.com/rust-lang/crates.io-index" 2098 | checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" 2099 | dependencies = [ 2100 | "dirs-next", 2101 | "rustversion", 2102 | "winapi", 2103 | ] 2104 | 2105 | [[package]] 2106 | name = "thiserror" 2107 | version = "1.0.47" 2108 | source = "registry+https://github.com/rust-lang/crates.io-index" 2109 | checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" 2110 | dependencies = [ 2111 | "thiserror-impl", 2112 | ] 2113 | 2114 | [[package]] 2115 | name = "thiserror-impl" 2116 | version = "1.0.47" 2117 | source = "registry+https://github.com/rust-lang/crates.io-index" 2118 | checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" 2119 | dependencies = [ 2120 | "proc-macro2", 2121 | "quote", 2122 | "syn 2.0.29", 2123 | ] 2124 | 2125 | [[package]] 2126 | name = "time" 2127 | version = "0.1.45" 2128 | source = "registry+https://github.com/rust-lang/crates.io-index" 2129 | checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" 2130 | dependencies = [ 2131 | "libc", 2132 | "wasi 0.10.0+wasi-snapshot-preview1", 2133 | "winapi", 2134 | ] 2135 | 2136 | [[package]] 2137 | name = "tiny-keccak" 2138 | version = "2.0.2" 2139 | source = "registry+https://github.com/rust-lang/crates.io-index" 2140 | checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" 2141 | dependencies = [ 2142 | "crunchy", 2143 | ] 2144 | 2145 | [[package]] 2146 | name = "tinyvec" 2147 | version = "1.6.0" 2148 | source = "registry+https://github.com/rust-lang/crates.io-index" 2149 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 2150 | dependencies = [ 2151 | "tinyvec_macros", 2152 | ] 2153 | 2154 | [[package]] 2155 | name = "tinyvec_macros" 2156 | version = "0.1.1" 2157 | source = "registry+https://github.com/rust-lang/crates.io-index" 2158 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 2159 | 2160 | [[package]] 2161 | name = "twofish" 2162 | version = "0.7.1" 2163 | source = "registry+https://github.com/rust-lang/crates.io-index" 2164 | checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" 2165 | dependencies = [ 2166 | "cipher", 2167 | ] 2168 | 2169 | [[package]] 2170 | name = "typenum" 2171 | version = "1.16.0" 2172 | source = "registry+https://github.com/rust-lang/crates.io-index" 2173 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 2174 | 2175 | [[package]] 2176 | name = "unicode-bidi" 2177 | version = "0.3.13" 2178 | source = "registry+https://github.com/rust-lang/crates.io-index" 2179 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 2180 | 2181 | [[package]] 2182 | name = "unicode-ident" 2183 | version = "1.0.11" 2184 | source = "registry+https://github.com/rust-lang/crates.io-index" 2185 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 2186 | 2187 | [[package]] 2188 | name = "unicode-normalization" 2189 | version = "0.1.22" 2190 | source = "registry+https://github.com/rust-lang/crates.io-index" 2191 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 2192 | dependencies = [ 2193 | "tinyvec", 2194 | ] 2195 | 2196 | [[package]] 2197 | name = "unicode-width" 2198 | version = "0.1.10" 2199 | source = "registry+https://github.com/rust-lang/crates.io-index" 2200 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 2201 | 2202 | [[package]] 2203 | name = "unicode-xid" 2204 | version = "0.2.4" 2205 | source = "registry+https://github.com/rust-lang/crates.io-index" 2206 | checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" 2207 | 2208 | [[package]] 2209 | name = "utf8parse" 2210 | version = "0.2.1" 2211 | source = "registry+https://github.com/rust-lang/crates.io-index" 2212 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 2213 | 2214 | [[package]] 2215 | name = "vanity_gpg" 2216 | version = "0.3.2" 2217 | dependencies = [ 2218 | "anyhow", 2219 | "backtrace", 2220 | "byteorder", 2221 | "cc", 2222 | "chrono", 2223 | "clap", 2224 | "colored", 2225 | "hex", 2226 | "indicatif", 2227 | "log", 2228 | "mimalloc", 2229 | "nettle", 2230 | "pgp", 2231 | "rand 0.8.5", 2232 | "rayon", 2233 | "regex", 2234 | "sequoia-openpgp", 2235 | "sha-1", 2236 | "smallvec", 2237 | "thiserror", 2238 | ] 2239 | 2240 | [[package]] 2241 | name = "vcpkg" 2242 | version = "0.2.15" 2243 | source = "registry+https://github.com/rust-lang/crates.io-index" 2244 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2245 | 2246 | [[package]] 2247 | name = "version_check" 2248 | version = "0.9.4" 2249 | source = "registry+https://github.com/rust-lang/crates.io-index" 2250 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 2251 | 2252 | [[package]] 2253 | name = "wasi" 2254 | version = "0.9.0+wasi-snapshot-preview1" 2255 | source = "registry+https://github.com/rust-lang/crates.io-index" 2256 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 2257 | 2258 | [[package]] 2259 | name = "wasi" 2260 | version = "0.10.0+wasi-snapshot-preview1" 2261 | source = "registry+https://github.com/rust-lang/crates.io-index" 2262 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 2263 | 2264 | [[package]] 2265 | name = "wasi" 2266 | version = "0.11.0+wasi-snapshot-preview1" 2267 | source = "registry+https://github.com/rust-lang/crates.io-index" 2268 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2269 | 2270 | [[package]] 2271 | name = "wasm-bindgen" 2272 | version = "0.2.87" 2273 | source = "registry+https://github.com/rust-lang/crates.io-index" 2274 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 2275 | dependencies = [ 2276 | "cfg-if", 2277 | "wasm-bindgen-macro", 2278 | ] 2279 | 2280 | [[package]] 2281 | name = "wasm-bindgen-backend" 2282 | version = "0.2.87" 2283 | source = "registry+https://github.com/rust-lang/crates.io-index" 2284 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 2285 | dependencies = [ 2286 | "bumpalo", 2287 | "log", 2288 | "once_cell", 2289 | "proc-macro2", 2290 | "quote", 2291 | "syn 2.0.29", 2292 | "wasm-bindgen-shared", 2293 | ] 2294 | 2295 | [[package]] 2296 | name = "wasm-bindgen-macro" 2297 | version = "0.2.87" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 2300 | dependencies = [ 2301 | "quote", 2302 | "wasm-bindgen-macro-support", 2303 | ] 2304 | 2305 | [[package]] 2306 | name = "wasm-bindgen-macro-support" 2307 | version = "0.2.87" 2308 | source = "registry+https://github.com/rust-lang/crates.io-index" 2309 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 2310 | dependencies = [ 2311 | "proc-macro2", 2312 | "quote", 2313 | "syn 2.0.29", 2314 | "wasm-bindgen-backend", 2315 | "wasm-bindgen-shared", 2316 | ] 2317 | 2318 | [[package]] 2319 | name = "wasm-bindgen-shared" 2320 | version = "0.2.87" 2321 | source = "registry+https://github.com/rust-lang/crates.io-index" 2322 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 2323 | 2324 | [[package]] 2325 | name = "winapi" 2326 | version = "0.3.9" 2327 | source = "registry+https://github.com/rust-lang/crates.io-index" 2328 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2329 | dependencies = [ 2330 | "winapi-i686-pc-windows-gnu", 2331 | "winapi-x86_64-pc-windows-gnu", 2332 | ] 2333 | 2334 | [[package]] 2335 | name = "winapi-i686-pc-windows-gnu" 2336 | version = "0.4.0" 2337 | source = "registry+https://github.com/rust-lang/crates.io-index" 2338 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2339 | 2340 | [[package]] 2341 | name = "winapi-x86_64-pc-windows-gnu" 2342 | version = "0.4.0" 2343 | source = "registry+https://github.com/rust-lang/crates.io-index" 2344 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2345 | 2346 | [[package]] 2347 | name = "windows" 2348 | version = "0.48.0" 2349 | source = "registry+https://github.com/rust-lang/crates.io-index" 2350 | checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" 2351 | dependencies = [ 2352 | "windows-targets 0.48.5", 2353 | ] 2354 | 2355 | [[package]] 2356 | name = "windows-sys" 2357 | version = "0.45.0" 2358 | source = "registry+https://github.com/rust-lang/crates.io-index" 2359 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 2360 | dependencies = [ 2361 | "windows-targets 0.42.2", 2362 | ] 2363 | 2364 | [[package]] 2365 | name = "windows-sys" 2366 | version = "0.48.0" 2367 | source = "registry+https://github.com/rust-lang/crates.io-index" 2368 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 2369 | dependencies = [ 2370 | "windows-targets 0.48.5", 2371 | ] 2372 | 2373 | [[package]] 2374 | name = "windows-targets" 2375 | version = "0.42.2" 2376 | source = "registry+https://github.com/rust-lang/crates.io-index" 2377 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 2378 | dependencies = [ 2379 | "windows_aarch64_gnullvm 0.42.2", 2380 | "windows_aarch64_msvc 0.42.2", 2381 | "windows_i686_gnu 0.42.2", 2382 | "windows_i686_msvc 0.42.2", 2383 | "windows_x86_64_gnu 0.42.2", 2384 | "windows_x86_64_gnullvm 0.42.2", 2385 | "windows_x86_64_msvc 0.42.2", 2386 | ] 2387 | 2388 | [[package]] 2389 | name = "windows-targets" 2390 | version = "0.48.5" 2391 | source = "registry+https://github.com/rust-lang/crates.io-index" 2392 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 2393 | dependencies = [ 2394 | "windows_aarch64_gnullvm 0.48.5", 2395 | "windows_aarch64_msvc 0.48.5", 2396 | "windows_i686_gnu 0.48.5", 2397 | "windows_i686_msvc 0.48.5", 2398 | "windows_x86_64_gnu 0.48.5", 2399 | "windows_x86_64_gnullvm 0.48.5", 2400 | "windows_x86_64_msvc 0.48.5", 2401 | ] 2402 | 2403 | [[package]] 2404 | name = "windows_aarch64_gnullvm" 2405 | version = "0.42.2" 2406 | source = "registry+https://github.com/rust-lang/crates.io-index" 2407 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 2408 | 2409 | [[package]] 2410 | name = "windows_aarch64_gnullvm" 2411 | version = "0.48.5" 2412 | source = "registry+https://github.com/rust-lang/crates.io-index" 2413 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 2414 | 2415 | [[package]] 2416 | name = "windows_aarch64_msvc" 2417 | version = "0.42.2" 2418 | source = "registry+https://github.com/rust-lang/crates.io-index" 2419 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 2420 | 2421 | [[package]] 2422 | name = "windows_aarch64_msvc" 2423 | version = "0.48.5" 2424 | source = "registry+https://github.com/rust-lang/crates.io-index" 2425 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 2426 | 2427 | [[package]] 2428 | name = "windows_i686_gnu" 2429 | version = "0.42.2" 2430 | source = "registry+https://github.com/rust-lang/crates.io-index" 2431 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 2432 | 2433 | [[package]] 2434 | name = "windows_i686_gnu" 2435 | version = "0.48.5" 2436 | source = "registry+https://github.com/rust-lang/crates.io-index" 2437 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 2438 | 2439 | [[package]] 2440 | name = "windows_i686_msvc" 2441 | version = "0.42.2" 2442 | source = "registry+https://github.com/rust-lang/crates.io-index" 2443 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 2444 | 2445 | [[package]] 2446 | name = "windows_i686_msvc" 2447 | version = "0.48.5" 2448 | source = "registry+https://github.com/rust-lang/crates.io-index" 2449 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 2450 | 2451 | [[package]] 2452 | name = "windows_x86_64_gnu" 2453 | version = "0.42.2" 2454 | source = "registry+https://github.com/rust-lang/crates.io-index" 2455 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 2456 | 2457 | [[package]] 2458 | name = "windows_x86_64_gnu" 2459 | version = "0.48.5" 2460 | source = "registry+https://github.com/rust-lang/crates.io-index" 2461 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 2462 | 2463 | [[package]] 2464 | name = "windows_x86_64_gnullvm" 2465 | version = "0.42.2" 2466 | source = "registry+https://github.com/rust-lang/crates.io-index" 2467 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 2468 | 2469 | [[package]] 2470 | name = "windows_x86_64_gnullvm" 2471 | version = "0.48.5" 2472 | source = "registry+https://github.com/rust-lang/crates.io-index" 2473 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 2474 | 2475 | [[package]] 2476 | name = "windows_x86_64_msvc" 2477 | version = "0.42.2" 2478 | source = "registry+https://github.com/rust-lang/crates.io-index" 2479 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 2480 | 2481 | [[package]] 2482 | name = "windows_x86_64_msvc" 2483 | version = "0.48.5" 2484 | source = "registry+https://github.com/rust-lang/crates.io-index" 2485 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 2486 | 2487 | [[package]] 2488 | name = "x25519-dalek" 2489 | version = "2.0.0" 2490 | source = "registry+https://github.com/rust-lang/crates.io-index" 2491 | checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" 2492 | dependencies = [ 2493 | "curve25519-dalek", 2494 | "rand_core 0.6.4", 2495 | "serde", 2496 | "zeroize", 2497 | ] 2498 | 2499 | [[package]] 2500 | name = "xxhash-rust" 2501 | version = "0.8.6" 2502 | source = "registry+https://github.com/rust-lang/crates.io-index" 2503 | checksum = "735a71d46c4d68d71d4b24d03fdc2b98e38cea81730595801db779c04fe80d70" 2504 | 2505 | [[package]] 2506 | name = "zeroize" 2507 | version = "1.6.0" 2508 | source = "registry+https://github.com/rust-lang/crates.io-index" 2509 | checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" 2510 | dependencies = [ 2511 | "zeroize_derive", 2512 | ] 2513 | 2514 | [[package]] 2515 | name = "zeroize_derive" 2516 | version = "1.4.2" 2517 | source = "registry+https://github.com/rust-lang/crates.io-index" 2518 | checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" 2519 | dependencies = [ 2520 | "proc-macro2", 2521 | "quote", 2522 | "syn 2.0.29", 2523 | ] 2524 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vanity_gpg" 3 | version = "0.3.2" 4 | edition = "2021" 5 | authors = ["Kay Lin "] 6 | description = "A simple tool for generating and filtering vanity GPG keys, c0nCurr3nt1Y" 7 | homepage = "https://github.com/RedL0tus/VanityGPG" 8 | repository = "https://github.com/RedL0tus/VanityGPG" 9 | keywords = [ "GPG", "Vanity", "VanityGPG" ] 10 | readme = "README.md" 11 | license = "MIT" 12 | categories = [ "command-line-utilities" ] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [features] 17 | default = [ "sequoia" ] 18 | sequoia = [ "sequoia-openpgp" ] 19 | rpgp = [ "pgp", "rand", "chrono", "smallvec", "sha-1" ] 20 | 21 | [dev-dependencies] 22 | hex = "^0.4" 23 | 24 | [build-dependencies] 25 | cc = "1.0" 26 | 27 | [dependencies] 28 | log = { version = "^0.4", features = [ "std" ] } 29 | pgp = { version = "^0.10", optional = true } 30 | clap = { version = "^4.3", features = [ "derive" ] } 31 | rand = { version = "^0.8", optional = true } 32 | rayon = "^1.7" 33 | regex = "^1.9" 34 | sha-1 = { version = "^0.10", features = [ "asm", "compress" ], optional = true } 35 | anyhow = "^1.0" 36 | chrono = { version = "^0.4", optional = true } 37 | nettle = "^7.3" 38 | colored = "^2.0" 39 | mimalloc = { version = "^0.1", default-features = false } 40 | smallvec = { version = "^1.11", optional = true } 41 | backtrace = "^0.3" 42 | byteorder = "^1.4" 43 | indicatif = "^0.17" 44 | thiserror = "^1.0" 45 | sequoia-openpgp = { version = "^1.16", optional = true } 46 | 47 | [profile.test] 48 | opt-level = 3 49 | debug = true 50 | debug-assertions = false 51 | overflow-checks = false 52 | 53 | [profile.release] 54 | opt-level = 3 55 | debug = true 56 | debug-assertions = false 57 | overflow-checks = false 58 | lto = true 59 | panic = 'unwind' 60 | incremental = false 61 | codegen-units = 1 62 | rpath = false 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kay Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VanityGPG (vanity_gpg) 2 | ====================== 3 | 4 | [![license](https://img.shields.io/github/license/RedL0tus/VanityGPG.svg)](LICENSE) 5 | [![crates.io](http://meritbadge.herokuapp.com/vanity_gpg)](https://crates.io/crates/vanity_gpg) 6 | 7 | A simple tool for generating and filtering vanity GPG keys (a.k.a. A OpenPGP key fingerprint collision tool), c0nCurr3nt1Y. 8 | 9 | Install 10 | ------- 11 | 12 | Currently(v0.3), VanityGPG offers two sets of backends, [`Sequoia-OpenPGP`](https://sequoia-pgp.org/) and [`rPGP`](https://github.com/rpgp/rpgp). If you have `libclang` available in your system, the default sequoia backend is recommend. 13 | 14 | Install dependencies (assuming you are using Ubuntu, bruh) for the sequoia backend: 15 | ```bash 16 | apt install git rustc cargo clang make pkg-config nettle-dev libssl-dev capnproto libsqlite3-dev 17 | ``` 18 | 19 | Install VanityGPG with `cargo`: 20 | ```bash 21 | cargo install vanity_gpg 22 | ``` 23 | 24 | If your system does not offer `libclang`, there is also a pure rust `rPGP` backend available: 25 | 26 | ```bash 27 | cargo install vanity_gpg --no-default-features --features rpgp 28 | ``` 29 | 30 | **If the rPGP backend is used, it's not recommended to use the key generated by it as your main key. It uses a PRNG for generating random numbers, which is considered (kind of) insecure.** 31 | 32 | Performance 33 | ----------- 34 | 35 | With the following parameters: 36 | 37 | ```bash 38 | ./vanity_gpg -c Ed25519 -jX -u "Kay Lin " -p "(8B){5,20}$|(B8){5,20}$|(EB){5,20}$|(BE){5,20}$|(EF){5,20}$|(FE){5,20}$|A{10,40}$|B{10,40}$|C{10,40}$|D{10,40}$|E{10,40}$|F{10,40}$|1{10,40}$|2{10,40}$|3{10,40}$|4{10,40}$|5{10,40}$|6{10,40}$|7{10,40}$|8{10,40}$|9{10,40}$|0{10,40}$|1145141919810$" 39 | ``` 40 | 41 | | System/Backend | Sequoia | Notes | 42 | |--------------------------------------|---------------------|----------------------------------------------| 43 | | Tegra210 (X1) @ 1.9GHz (-j4) | ~6,300,000 hash/s | Fedora AArch64, sequoia backend, Jetson Nano | 44 | | Intel Xeon E3-1231 V3 @ 3.4GHz (-j8) | ~15,000,000 hash/s | FreeBSD, sequoia backend, without jemalloc | 45 | | Intel Core i7-8569U @ 2.8GHz (-j8) | ~18,000,000 hash/s | macOS, sequoia backend, built with Nix | 46 | | AMD Ryzen 5 3600 @ 3.9GHz (-j12) | ~80,000,000 hash/s | NixOS, sequoia backend | 47 | | AMD Ryzen 7 3700x @ 4.1GHz (-j16) | ~120,000,000 hash/s | AOSC OS, sequoia backend | 48 | 49 | Credits 50 | ------- 51 | 52 | [`Sequoia-OpenPGP`](https://sequoia-pgp.org/) and the [`rPGP`](https://github.com/rpgp/rpgp) teams for their awesome works. 53 | 54 | [@nwalfield](https://github.com/nwalfield) for the extremely helpful tips that improves VanityGPG's performance for several orders of magnitude ([#2](https://github.com/RedL0tus/VanityGPG/issues/2)). 55 | 56 | Usage 57 | ----- 58 | 59 | ``` 60 | vanity_gpg 0.3.0 61 | A simple tool for generating and filtering vanity GPG keys, c0nCurr3nt1Y 62 | 63 | USAGE: 64 | vanity_gpg [FLAGS] [OPTIONS] --pattern 65 | 66 | FLAGS: 67 | -d, --dry-run Dry run (does not save matched keys) 68 | -h, --help Prints help information 69 | -v, --verbose Verbose level 70 | -V, --version Prints version information 71 | 72 | OPTIONS: 73 | -c, --cipher-suite 74 | Cipher suite [default: Ed25519] [possible values: Ed25519, RSA2048, RSA3072, RSA4096, 75 | NISTP256, NISTP384, NISTP521] 76 | 77 | -j, --jobs Number of threads [default: 8] 78 | -p, --pattern Regex pattern for matching fingerprints 79 | -u, --user-id OpenPGP compatible user ID 80 | ``` 81 | 82 | Notes: 83 | - There will be an extra thread spawned for displaying summary. 84 | - It's recommended to use multiple rules with regex for maximum efficiency. 85 | 86 | Errata 87 | ------ 88 | 89 | On AArch64 machines, you may have to disable the `"asm"` feature for `sha-1` before compiling. 90 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | #[cfg(target_arch = "aarch64")] 3 | { 4 | use cc::Build; 5 | Build::new().file("src/hex_neon.c").compile("hex"); 6 | } 7 | 8 | #[cfg(target_arch = "loongarch64")] 9 | { 10 | use cc::Build; 11 | let result = Build::new().file("src/hex_lsx.c").flag("-mlsx").try_compile("hex"); 12 | 13 | match result { 14 | Ok(_) => println!("cargo:rustc-cfg=compilerSupportLSX"), 15 | Err(_) => {} 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | nixpkgs = import { 3 | config.allowUnfree = false; 4 | overlays = [ ]; 5 | }; 6 | platform_dependencies = if nixpkgs.stdenv.hostPlatform.system == "x86_64-darwin" then nixpkgs.darwin.apple_sdk.frameworks.Security 7 | else ""; 8 | in 9 | with nixpkgs; 10 | stdenv.mkDerivation rec { 11 | name = "vanityPGP"; 12 | env = buildEnv { name = name; paths = buildInputs; }; 13 | buildInputs = [ 14 | # List packages that should be on the path 15 | # You can search for package names using nix-env -qaP | grep 16 | stdenv clang nettle pkg-config capnproto sqlite rustc cargo llvm 17 | llvmPackages.libclang platform_dependencies 18 | ]; 19 | 20 | LIBCLANG_PATH="${llvmPackages.libclang}/lib"; 21 | 22 | shellHook = '' 23 | export NIX_SHELL_ENV=${name} 24 | ''; 25 | } 26 | -------------------------------------------------------------------------------- /src/hex_lsx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const uint8_t nine = 9; 6 | const uint8_t and_mask = 0xf; 7 | const uint8_t bin_a = 0x37; 8 | 9 | void sha1_to_hex_lsx(const uint8_t *binary, uint8_t *hex) { 10 | __m128i ascii_zero = __lsx_vldrepl_b((const uint8_t*)"0", 0); 11 | __m128i nines = __lsx_vldrepl_b(&nine, 0); 12 | __m128i ascii_a = __lsx_vldrepl_b(&bin_a, 0); 13 | __m128i and4bits = __lsx_vldrepl_b(&and_mask, 0); 14 | 15 | __m128i invec = __lsx_vld((__m128i * const)binary, 0); 16 | 17 | __m128i masked1 = __lsx_vand_v(invec, and4bits); 18 | __m128i masked2 = __lsx_vand_v(__lsx_vsrli_b((invec), 4), and4bits); 19 | 20 | __m128i cmpmask1 = __lsx_vslt_bu(nines, masked1); 21 | __m128i cmpmask2 = __lsx_vslt_bu(nines, masked2); 22 | 23 | __m128i masked1_k = __lsx_vsadd_bu(masked1, __lsx_vbitsel_v(ascii_zero, ascii_a, cmpmask1)); 24 | __m128i masked2_k = __lsx_vsadd_bu(masked2, __lsx_vbitsel_v(ascii_zero, ascii_a, cmpmask2)); 25 | 26 | __m128i res1 = __lsx_vilvl_b(masked1_k, masked2_k); 27 | __m128i res2 = __lsx_vilvh_b(masked1_k, masked2_k); 28 | 29 | __lsx_vst(res1, hex, 0); 30 | __lsx_vst(res2, hex + 16, 0); 31 | } 32 | -------------------------------------------------------------------------------- /src/hex_neon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | const uint8_t nine = 9; 6 | const uint8_t and_mask = 0xf; 7 | const uint8_t bin_a = 0x37; 8 | 9 | void sha1_to_hex_neon(const uint8_t *binary, uint8_t *hex) { 10 | uint8x16_t ascii_zero = vld1q_dup_u8((const uint8_t*)"0"); 11 | uint8x16_t nines = vld1q_dup_u8(&nine); 12 | uint8x16_t ascii_a = vld1q_dup_u8(&bin_a); 13 | uint8x16_t and4bits = vld1q_dup_u8(&and_mask); 14 | 15 | uint8x16_t invec = vld1q_u8(binary); 16 | uint8x16_t masked1 = vandq_u8(invec, and4bits); 17 | uint8x16_t masked2 = vandq_u8(vshrq_n_u8((invec), 4), and4bits); 18 | 19 | uint8x16_t cmpmask1 = vcgtq_u8(masked1, nines); 20 | uint8x16_t cmpmask2 = vcgtq_u8(masked2, nines); 21 | 22 | uint8x16_t masked1_k = vaddq_u8(masked1, vbslq_u8(cmpmask1, ascii_a, ascii_zero)); 23 | uint8x16_t masked2_k = vaddq_u8(masked2, vbslq_u8(cmpmask2, ascii_a, ascii_zero)); 24 | 25 | uint8x16_t res1 = vzip1q_u8(masked2_k, masked1_k); 26 | uint8x16_t res2 = vzip2q_u8(masked2_k, masked1_k); 27 | 28 | vst1q_u8(hex, res1); 29 | vst1q_u8(hex + 16, res2); 30 | } 31 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # VanityGPG 2 | //! 3 | //! It works. 4 | //! 5 | //! ```rust 6 | //! use vanity_gpg::{Backend, DefaultBackend, CipherSuite}; 7 | //! 8 | //! let backend = DefaultBackend::new(CipherSuite::Curve25519).unwrap(); 9 | //! println!("Fingerprint: {}", backend.fingerprint()); 10 | //! ``` 11 | 12 | extern crate anyhow; 13 | extern crate byteorder; 14 | #[cfg(feature = "rpgp")] 15 | extern crate chrono; 16 | #[cfg(feature = "rpgp")] 17 | extern crate pgp; 18 | #[cfg(feature = "rpgp")] 19 | extern crate rand; 20 | #[cfg(feature = "sequoia")] 21 | extern crate sequoia_openpgp; 22 | #[cfg(feature = "rpgp")] 23 | extern crate sha1; 24 | #[cfg(feature = "rpgp")] 25 | extern crate smallvec; 26 | extern crate thiserror; 27 | 28 | pub mod pgp_backends; 29 | #[cfg(feature = "rpgp")] 30 | pub use pgp_backends::RPGPBackend; 31 | #[cfg(feature = "sequoia")] 32 | pub use pgp_backends::SequoiaBackend; 33 | pub use pgp_backends::{ArmoredKey, Backend, CipherSuite, DefaultBackend, UserID}; 34 | 35 | #[cfg(test)] 36 | mod meaningless_test { 37 | #[test] 38 | fn it_works() { 39 | assert_eq!(1 + 1, 2); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/logger/indicatif_backend.rs: -------------------------------------------------------------------------------- 1 | //! Indicatif backend 2 | 3 | use indicatif::{ProgressBar, ProgressStyle}; 4 | 5 | use std::time::Duration; 6 | 7 | use super::ProgressLoggerBackend; 8 | 9 | pub struct IndicatifBackend { 10 | inner: ProgressBar, 11 | } 12 | 13 | /// Implementing the backend trait for `ProgressBar` from `indicatif` 14 | impl ProgressLoggerBackend for IndicatifBackend { 15 | fn println>(&self, content: S) { 16 | self.inner.println(content.as_ref()); 17 | } 18 | 19 | fn set_message>(&self, content: S) { 20 | self.inner.set_message(content.as_ref().to_string()) 21 | } 22 | 23 | fn finish(&self) { 24 | self.inner.finish(); 25 | } 26 | } 27 | 28 | impl IndicatifBackend { 29 | pub fn init() -> Self { 30 | let progress_bar = ProgressBar::new_spinner(); 31 | progress_bar.enable_steady_tick(Duration::from_millis(100)); 32 | progress_bar.set_style( 33 | ProgressStyle::default_spinner() 34 | .tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸"]) 35 | .template("{spinner:.blue} {msg}").expect("Failed to set theme"), 36 | ); 37 | progress_bar.set_message("Initializing"); 38 | Self { 39 | inner: progress_bar, 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/logger/mod.rs: -------------------------------------------------------------------------------- 1 | //! # Logger 2 | //! 3 | //! A simple logger implementation that can be used with random progress bar implementations 4 | 5 | mod indicatif_backend; 6 | 7 | use colored::*; 8 | use log::{set_boxed_logger, set_max_level, Level, Metadata, Record, SetLoggerError}; 9 | 10 | pub use indicatif_backend::IndicatifBackend; 11 | 12 | use std::sync::{Arc, Mutex}; 13 | 14 | /// Progress bar backend 15 | pub trait ProgressLoggerBackend: Sync + Send { 16 | fn println>(&self, content: S); 17 | fn set_message>(&self, content: S); 18 | fn finish(&self); 19 | } 20 | 21 | /// Logger that work with a progress bar implementation 22 | pub struct ProgressLogger { 23 | max_level: Level, 24 | backend: Arc>, 25 | } 26 | 27 | /// Implementing `Log` trait for `ProgressLogger` 28 | impl log::Log for ProgressLogger { 29 | fn enabled(&self, metadata: &Metadata) -> bool { 30 | metadata.level() <= self.max_level 31 | } 32 | 33 | fn log(&self, record: &Record) { 34 | if !self.enabled(record.metadata()) { 35 | return; 36 | } 37 | let level_name = match record.level() { 38 | Level::Error => record.level().to_string().red(), 39 | Level::Warn => record.level().to_string().yellow(), 40 | Level::Info => record.level().to_string().cyan(), 41 | Level::Debug => record.level().to_string().purple(), 42 | Level::Trace => record.level().to_string().normal(), 43 | }; 44 | let target = if !record.target().is_empty() { 45 | record.target() 46 | } else { 47 | record.module_path().unwrap_or_default() 48 | }; 49 | self.backend.lock().unwrap().println(format!( 50 | "{:<5} [{}] {}", 51 | level_name, 52 | target, 53 | record.args() 54 | )); 55 | } 56 | 57 | fn flush(&self) {} 58 | } 59 | 60 | /// Main impl block of `ProgressLogger` 61 | impl ProgressLogger { 62 | /// Create new `ProgressLogger` instance 63 | pub fn new(max_level: Level, backend: B) -> Self { 64 | Self { 65 | max_level, 66 | backend: Arc::new(Mutex::new(backend)), 67 | } 68 | } 69 | 70 | pub fn setup(self) -> Result<(), SetLoggerError> { 71 | set_max_level(self.max_level.to_level_filter()); 72 | set_boxed_logger(Box::new(self))?; 73 | Ok(()) 74 | } 75 | 76 | /// Get `Arc>` 77 | pub fn get_backend(&self) -> Arc> { 78 | self.backend.clone() 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | //! # VanityGPG (default binary) 2 | //! 3 | //! A simple tool for generating and filtering vanity GPG keys, c0nCurr3nt1Y. 4 | //! (a.k.a. OpenPGP key fingerprint collision tool) 5 | 6 | extern crate backtrace; 7 | extern crate clap; 8 | extern crate colored; 9 | extern crate indicatif; 10 | extern crate log; 11 | extern crate mimalloc; 12 | extern crate rayon; 13 | extern crate regex; 14 | 15 | extern crate vanity_gpg; 16 | 17 | mod logger; 18 | 19 | use anyhow::Error; 20 | use backtrace::Backtrace; 21 | use clap::{Parser, ValueEnum}; 22 | use log::{debug, info, warn, Level}; 23 | use rayon::ThreadPoolBuilder; 24 | use regex::Regex; 25 | 26 | use std::env; 27 | use std::fmt; 28 | use std::fs::File; 29 | use std::io::prelude::*; 30 | use std::panic; 31 | use std::sync::atomic::{AtomicUsize, Ordering}; 32 | use std::sync::{Arc, Mutex}; 33 | use std::thread; 34 | use std::time::{Duration, Instant}; 35 | 36 | use vanity_gpg::{Backend, CipherSuite, DefaultBackend, UserID}; 37 | 38 | use logger::{IndicatifBackend, ProgressLogger, ProgressLoggerBackend}; 39 | 40 | #[global_allocator] 41 | static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; 42 | 43 | // Constants 44 | /// Default log level 45 | const PKG_LOG_LEVEL_DEFAULT: Level = Level::Warn; 46 | /// Log level with `-v` 47 | const PKG_LOG_LEVEL_VERBOSE_1: Level = Level::Info; 48 | /// Log level with `-vv` and beyond 49 | const PKG_LOG_LEVEL_VERBOSE_2: Level = Level::Debug; 50 | /// Log level with `-vvv` and beyond 51 | const PKG_LOG_LEVEL_VERBOSE_3: Level = Level::Trace; 52 | /// Program version (from `Cargo.toml`) 53 | const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); 54 | /// Program description (from `Cargo.toml`) 55 | const PKG_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); 56 | /// Program repository (from `Cargo.toml`) 57 | const PKG_REPOSITORY: &str = env!("CARGO_PKG_REPOSITORY"); 58 | 59 | /// Key reshuffle limit 60 | const KEY_RESHUFFLE_LIMIT: usize = 60 * 60 * 24 * 30; // One month ago at worst 61 | /// Counter threshold 62 | const COUNTER_THRESHOLD: usize = 133331; // Just a random number 63 | 64 | /// Possible values for CipherSuite 65 | #[derive(ValueEnum, Clone, Debug)] 66 | enum CipherSuiteValues { 67 | Ed25519, 68 | RSA2048, 69 | RSA3072, 70 | RSA4096, 71 | NISTP256, 72 | NISTP384, 73 | NISTP521, 74 | } 75 | 76 | /// Commandline option parser with `Clap` 77 | #[derive(Parser, Debug)] 78 | #[clap(version = PKG_VERSION, about = PKG_DESCRIPTION)] 79 | struct Opts { 80 | /// Concurrent key generation jobs 81 | #[clap( 82 | short = 'j', 83 | long = "jobs", 84 | help = "Number of threads", 85 | default_value = "8" 86 | )] 87 | jobs: usize, 88 | /// Regex pattern for matching fingerprints 89 | #[clap( 90 | short = 'p', 91 | long = "pattern", 92 | help = "Regex pattern for matching fingerprints" 93 | )] 94 | pattern: String, 95 | /// Cipher suite 96 | #[clap( 97 | short = 'c', 98 | long = "cipher-suite", 99 | help = "Cipher suite", 100 | )] 101 | cipher_suite: CipherSuiteValues, 102 | /// User ID 103 | #[clap(short = 'u', long = "user-id", help = "OpenPGP compatible user ID")] 104 | user_id: Option, 105 | #[clap( 106 | short = 'd', 107 | long = "dry-run", 108 | help = "Dry run (does not save matched keys)" 109 | )] 110 | dry_run: bool, 111 | /// Verbose level 112 | #[clap( 113 | short = 'v', 114 | long = "verbose", 115 | help = "Verbose level", 116 | action = clap::ArgAction::Count 117 | )] 118 | verbose: u8, 119 | } 120 | 121 | /// Counter for statistics 122 | #[derive(Debug)] 123 | struct Counter { 124 | total: AtomicUsize, 125 | success: AtomicUsize, 126 | } 127 | 128 | /// Wrapper for the backends 129 | #[derive(Debug)] 130 | struct Key { 131 | backend: B, 132 | } 133 | 134 | /// Save string to file 135 | fn save_file(file_name: String, content: &str) -> Result<(), Error> { 136 | let mut file = File::create(file_name)?; 137 | Ok(file.write_all(content.as_bytes())?) 138 | } 139 | 140 | /// Set panic hook with repository information 141 | fn setup_panic_hook() { 142 | panic::set_hook(Box::new(move |panic_info: &panic::PanicInfo| { 143 | if let Some(info) = panic_info.payload().downcast_ref::<&str>() { 144 | println!("Panic occurred: {:?}", info); 145 | } else { 146 | println!("Panic occurred"); 147 | } 148 | if let Some(location) = panic_info.location() { 149 | println!( 150 | r#"In file "{}" at line "{}""#, 151 | location.file(), 152 | location.line() 153 | ); 154 | } 155 | println!("Traceback:"); 156 | println!("{:#?}", Backtrace::new()); 157 | println!(); 158 | println!("Please report this error to {}/issues", PKG_REPOSITORY); 159 | })); 160 | } 161 | 162 | /// Setup logger and return a `ProgressBar` that can be shared between threads 163 | fn setup_logger( 164 | verbosity: u8, 165 | backend: B, 166 | ) -> Result>, Error> { 167 | let level = match verbosity { 168 | 0 => PKG_LOG_LEVEL_DEFAULT, 169 | 1 => PKG_LOG_LEVEL_VERBOSE_1, 170 | 2 => PKG_LOG_LEVEL_VERBOSE_2, 171 | _ => PKG_LOG_LEVEL_VERBOSE_3, 172 | }; 173 | let logger = ProgressLogger::new(level, backend); 174 | debug!("Logger initialized"); 175 | let cloned_backend = logger.get_backend(); 176 | logger.setup()?; 177 | Ok(cloned_backend) 178 | } 179 | 180 | /// Sub-thread that display status summary 181 | fn setup_summary(logger_backend: Arc>, counter: Arc) { 182 | let start = Instant::now(); 183 | loop { 184 | thread::sleep(Duration::from_millis(100)); 185 | debug!("Updating counter information"); 186 | let secs_elapsed = start.elapsed().as_secs(); 187 | logger_backend.lock().unwrap().set_message(&format!( 188 | "Summary: {} (avg. {:.2} hash/s)", 189 | &counter, 190 | counter.get_total() as f64 / secs_elapsed as f64 191 | )); 192 | } 193 | } 194 | 195 | impl Default for CipherSuiteValues { 196 | fn default() -> Self { 197 | Self::Ed25519 198 | } 199 | } 200 | 201 | impl From<&CipherSuiteValues> for CipherSuite { 202 | fn from(value: &CipherSuiteValues) -> Self { 203 | match &value { 204 | CipherSuiteValues::Ed25519 => CipherSuite::Curve25519, 205 | CipherSuiteValues::RSA2048 => CipherSuite::RSA2048, 206 | CipherSuiteValues::RSA3072 => CipherSuite::RSA3072, 207 | CipherSuiteValues::RSA4096 => CipherSuite::RSA4096, 208 | CipherSuiteValues::NISTP256 => CipherSuite::NistP256, 209 | CipherSuiteValues::NISTP384 => CipherSuite::NistP384, 210 | CipherSuiteValues::NISTP521 => CipherSuite::NistP521, 211 | } 212 | } 213 | } 214 | 215 | impl Counter { 216 | /// Create new instance 217 | fn new() -> Self { 218 | Self { 219 | total: AtomicUsize::new(0), 220 | success: AtomicUsize::new(0), 221 | } 222 | } 223 | 224 | /// Count towards total numbers of fingerprints generated 225 | fn count_total(&self, accumulated_counts: usize) { 226 | self.total.fetch_add(accumulated_counts, Ordering::SeqCst); 227 | } 228 | 229 | /// Count towards total numbers of fingerprints matched 230 | fn count_success(&self) { 231 | self.success.fetch_add(1, Ordering::SeqCst); 232 | } 233 | 234 | /// Get number of total fingerprints generated 235 | fn get_total(&self) -> usize { 236 | self.total.load(Ordering::SeqCst) 237 | } 238 | 239 | /// Get number of total fingerprints matched 240 | fn get_success(&self) -> usize { 241 | self.success.load(Ordering::SeqCst) 242 | } 243 | } 244 | 245 | impl fmt::Display for Counter { 246 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 247 | write!( 248 | f, 249 | "{} matched, {} total", 250 | self.get_success(), 251 | self.get_total(), 252 | ) 253 | } 254 | } 255 | 256 | impl Key { 257 | /// Create new instance 258 | fn new(backend: B) -> Key { 259 | Key { backend } 260 | } 261 | 262 | /// Get fingerprint 263 | fn get_fingerprint(&self) -> String { 264 | self.backend.fingerprint() 265 | } 266 | 267 | /// Rehash the key 268 | fn shuffle(&mut self) -> Result<(), Error> { 269 | Ok(self.backend.shuffle()?) 270 | } 271 | 272 | /// Save armored keys 273 | fn save_key(self, user_id: &UserID, dry_run: bool) -> Result<(), Error> { 274 | if dry_run { 275 | return Ok(()); 276 | } 277 | let fingerprint = self.get_fingerprint(); 278 | info!("saving [{}]", &fingerprint); 279 | let armored_keys = self.backend.get_armored_results(user_id)?; 280 | save_file( 281 | format!("{}-private.asc", &fingerprint), 282 | armored_keys.get_private_key(), 283 | )?; 284 | save_file( 285 | format!("{}-public.asc", &fingerprint), 286 | armored_keys.get_public_key(), 287 | )?; 288 | Ok(()) 289 | } 290 | } 291 | 292 | /// Start the program 293 | fn main() -> Result<(), Error> { 294 | // Setup panic hook 295 | setup_panic_hook(); 296 | 297 | // Parse commandline options 298 | let opts: Opts = Opts::parse(); 299 | 300 | // Setup logger and show some messages 301 | let logger_backend = setup_logger(opts.verbose, IndicatifBackend::init())?; 302 | warn!("Staring VanityGPG version v{}", PKG_VERSION); 303 | warn!("(So fast, such concurrency, wow)"); 304 | warn!( 305 | "if you met any issue, please file an issue report to \"{}\"", 306 | PKG_REPOSITORY 307 | ); 308 | let counter = Arc::new(Counter::new()); 309 | 310 | let pool = ThreadPoolBuilder::new() 311 | .num_threads(opts.jobs + 1) 312 | .build()?; 313 | let user_id = UserID::from(opts.user_id); 314 | 315 | for thread_id in 0..opts.jobs { 316 | let user_id_cloned = user_id.clone(); 317 | let pattern = Regex::new(&opts.pattern)?; 318 | let dry_run = opts.dry_run; 319 | let cipher_suite = CipherSuite::from(&opts.cipher_suite); 320 | let counter_cloned = Arc::clone(&counter); 321 | info!("({}): Spawning thread", thread_id); 322 | pool.spawn(move || { 323 | let mut key = Key::new(DefaultBackend::new(cipher_suite.clone()).unwrap()); 324 | let mut reshuffle_counter: usize = KEY_RESHUFFLE_LIMIT; 325 | let mut report_counter: usize = 0; 326 | loop { 327 | let fingerprint = key.get_fingerprint(); 328 | if pattern.is_match(&fingerprint) { 329 | warn!("({}): [{}] matched", thread_id, &fingerprint); 330 | counter_cloned.count_success(); 331 | key.save_key(&user_id_cloned, dry_run).unwrap_or(()); 332 | key = Key::new(DefaultBackend::new(cipher_suite.clone()).unwrap()); 333 | } else if reshuffle_counter == 0 { 334 | info!( 335 | "({}): Reshuffle limit reached, generating new primary key", 336 | thread_id 337 | ); 338 | key = Key::new(DefaultBackend::new(cipher_suite.clone()).unwrap()); 339 | reshuffle_counter = KEY_RESHUFFLE_LIMIT; 340 | } else { 341 | info!("({}): [{}] is not a match", thread_id, fingerprint); 342 | reshuffle_counter -= 1; 343 | key.shuffle().unwrap_or(()); 344 | } 345 | report_counter += 1; 346 | if report_counter >= COUNTER_THRESHOLD { 347 | counter_cloned.count_total(report_counter); 348 | report_counter = 0; 349 | } 350 | } 351 | }); 352 | } 353 | 354 | // Setup summary 355 | let logger_backend_cloned = Arc::clone(&logger_backend); 356 | let counter_cloned = Arc::clone(&counter); 357 | pool.install(move || setup_summary(logger_backend_cloned, counter_cloned)); 358 | 359 | Ok(()) 360 | } 361 | -------------------------------------------------------------------------------- /src/pgp_backends/hex.rs: -------------------------------------------------------------------------------- 1 | //! Hex calculation with SIMD 2 | //! 3 | //! Based on code from [`faster-hex`](https://github.com/nervosnetwork/faster-hex) 4 | //! Originally licensed under the terms of the MIT License. 5 | 6 | #[cfg(target_arch = "x86_64")] 7 | use std::arch::x86_64::*; 8 | 9 | #[cfg(target_arch = "aarch64")] 10 | extern "C" { 11 | #[link_name = "sha1_to_hex_neon"] 12 | fn sha1_to_hex_neon_(binary: *const u8, hex: *mut u8); 13 | } 14 | 15 | #[cfg(target_arch = "loongarch64")] 16 | #[cfg(compilerSupportLSX)] 17 | extern "C" { 18 | #[link_name = "sha1_to_hex_lsx"] 19 | fn sha1_to_hex_lsx_(binary: *const u8, hex: *mut u8); 20 | } 21 | 22 | static TABLE: &[u8; 16] = b"0123456789ABCDEF"; 23 | 24 | /// SHA-1 binary to hex conversion with SSE4.1 25 | /// We have a fixed input and output length 26 | #[target_feature(enable = "sse4.1")] 27 | #[cfg(target_arch = "x86_64")] 28 | unsafe fn sha1_to_hex_sse41(binary: &[u8], hex: &mut [u8]) { 29 | let ascii_zero = _mm_set1_epi8(b'0' as i8); 30 | let nines = _mm_set1_epi8(9); 31 | let ascii_a = _mm_set1_epi8((b'A' - 9 - 1) as i8); 32 | let and4bits = _mm_set1_epi8(0xf); 33 | 34 | let invec = _mm_loadu_si128(binary.as_ptr() as *const _); 35 | 36 | let masked1 = _mm_and_si128(invec, and4bits); 37 | let masked2 = _mm_and_si128(_mm_srli_epi64(invec, 4), and4bits); 38 | 39 | // return 0xff corresponding to the elements > 9, or 0x00 otherwise 40 | let cmpmask1 = _mm_cmpgt_epi8(masked1, nines); 41 | let cmpmask2 = _mm_cmpgt_epi8(masked2, nines); 42 | 43 | // add '0' or the offset depending on the masks 44 | let masked1 = _mm_add_epi8(masked1, _mm_blendv_epi8(ascii_zero, ascii_a, cmpmask1)); 45 | let masked2 = _mm_add_epi8(masked2, _mm_blendv_epi8(ascii_zero, ascii_a, cmpmask2)); 46 | 47 | // interleave masked1 and masked2 bytes 48 | let res1 = _mm_unpacklo_epi8(masked2, masked1); 49 | let res2 = _mm_unpackhi_epi8(masked2, masked1); 50 | 51 | _mm_storeu_si128(hex.as_mut_ptr() as *mut _, res1); 52 | _mm_storeu_si128(hex.as_mut_ptr().offset(16) as *mut _, res2); 53 | 54 | hex_fallback(&binary[16..], &mut hex[32..]); 55 | } 56 | 57 | /// SHA-1 binary to hex conversion with SSE4.1 58 | /// We have a fixed input and output length, and have to pad the input and output 59 | #[target_feature(enable = "avx2")] 60 | #[cfg(target_arch = "x86_64")] 61 | unsafe fn sha1_to_hex_avx2(binary: &[u8], hex: &mut [u8]) { 62 | // Preparing padded input and output 63 | let mut padded_output: [u8; 64] = [0x0; 64]; 64 | let mut padded_input: [u8; 32] = [0x0; 32]; 65 | std::ptr::copy_nonoverlapping(binary.as_ptr(), padded_input.as_mut_ptr(), 20); 66 | 67 | let ascii_zero = _mm256_set1_epi8(b'0' as i8); 68 | let nines = _mm256_set1_epi8(9); 69 | let ascii_a = _mm256_set1_epi8((b'A' - 9 - 1) as i8); 70 | let and4bits = _mm256_set1_epi8(0xf); 71 | 72 | let invec = _mm256_loadu_si256(padded_input.as_ptr() as *const _); 73 | let masked1 = _mm256_and_si256(invec, and4bits); 74 | let masked2 = _mm256_and_si256(_mm256_srli_epi64(invec, 4), and4bits); 75 | // return 0xff corresponding to the elements > 9, or 0x00 otherwise 76 | let cmpmask1 = _mm256_cmpgt_epi8(masked1, nines); 77 | let cmpmask2 = _mm256_cmpgt_epi8(masked2, nines); 78 | 79 | // add '0' or the offset depending on the masks 80 | let masked1 = _mm256_add_epi8(masked1, _mm256_blendv_epi8(ascii_zero, ascii_a, cmpmask1)); 81 | let masked2 = _mm256_add_epi8(masked2, _mm256_blendv_epi8(ascii_zero, ascii_a, cmpmask2)); 82 | 83 | // interleave masked1 and masked2 bytes 84 | let res1 = _mm256_unpacklo_epi8(masked2, masked1); 85 | let res2 = _mm256_unpackhi_epi8(masked2, masked1); 86 | 87 | // Store everything into the right destination now 88 | let base = padded_output.as_mut_ptr(); 89 | let base1 = base.offset(0) as *mut _; 90 | let base2 = base.offset(16) as *mut _; 91 | let base3 = base.offset(32) as *mut _; 92 | let base4 = base.offset(48) as *mut _; 93 | _mm256_storeu2_m128i(base3, base1, res1); 94 | _mm256_storeu2_m128i(base4, base2, res2); 95 | 96 | std::ptr::copy_nonoverlapping(padded_output.as_ptr(), hex.as_mut_ptr(), 40); 97 | } 98 | 99 | #[cfg(target_arch = "aarch64")] 100 | unsafe fn sha1_to_hex_neon(binary: &[u8], hex: &mut [u8]) { 101 | sha1_to_hex_neon_(binary.as_ptr(), hex.as_mut_ptr()); 102 | 103 | hex_fallback(&binary[16..], &mut hex[32..]); 104 | } 105 | 106 | #[cfg(target_arch = "loongarch64")] 107 | #[cfg(compilerSupportLSX)] 108 | unsafe fn sha1_to_hex_lsx(binary: &[u8], hex: &mut [u8]) { 109 | sha1_to_hex_lsx_(binary.as_ptr(), hex.as_mut_ptr()); 110 | 111 | hex_fallback(&binary[16..], &mut hex[32..]); 112 | } 113 | 114 | /// Software implementation of binary to hex 115 | fn hex_fallback(binary: &[u8], hex: &mut [u8]) { 116 | for (byte, slots) in binary.iter().zip(hex.chunks_mut(2)) { 117 | slots[0] = TABLE[((*byte >> 4) & 0xF) as usize]; 118 | slots[1] = TABLE[(*byte & 0xF) as usize]; 119 | } 120 | } 121 | 122 | /// SHA-1 binary to hex 123 | pub fn sha1_to_hex(binary: &[u8]) -> String { 124 | let mut result: Vec = vec![0x0; 40]; 125 | 126 | if cfg!(target_arch = "x86_64") { 127 | #[cfg(target_arch = "x86_64")] 128 | if is_x86_feature_detected!("avx2") { 129 | unsafe { sha1_to_hex_avx2(binary, &mut result) } 130 | } else if is_x86_feature_detected!("sse4.1") { 131 | unsafe { sha1_to_hex_sse41(binary, &mut result) } 132 | } else { 133 | hex_fallback(binary, &mut result); 134 | } 135 | } else if cfg!(target_arch = "aarch64") { 136 | #[cfg(target_arch = "aarch64")] 137 | unsafe { 138 | sha1_to_hex_neon(binary, &mut result) 139 | } 140 | } else if cfg!(target_arch = "loongarch64") { 141 | #[cfg(target_arch = "loongarch64")] 142 | if cfg!(compilerSupportLSX) { 143 | unsafe { sha1_to_hex_lsx(binary, &mut result) } 144 | } else { 145 | hex_fallback(binary, &mut result); 146 | } 147 | } else { 148 | hex_fallback(binary, &mut result); 149 | } 150 | 151 | unsafe { String::from_utf8_unchecked(result) } 152 | } 153 | 154 | #[cfg(test)] 155 | mod hex_test { 156 | use super::sha1_to_hex; 157 | #[cfg(target_arch = "x86_64")] 158 | use super::{sha1_to_hex_avx2, sha1_to_hex_sse41}; 159 | use hex::encode_upper; 160 | 161 | #[test] 162 | #[cfg(target_arch = "x86_64")] 163 | fn test_sha1_to_hex_sse41() { 164 | if is_x86_feature_detected!("sse4.1") { 165 | let data: &[u8; 20] = b"0123456789ABCDEFGHIJ"; 166 | let mut result: Vec = vec![0x0; 40]; 167 | unsafe { 168 | sha1_to_hex_sse41(data, &mut result); 169 | } 170 | let hex_string = unsafe { String::from_utf8_unchecked(result) }; 171 | assert_eq!(hex_string, encode_upper(data)); 172 | } 173 | } 174 | 175 | #[test] 176 | #[cfg(target_arch = "x86_64")] 177 | fn test_sha1_to_hex_avx2() { 178 | if is_x86_feature_detected!("avx2") { 179 | let data: &[u8; 20] = b"0123456789ABCDEFGHIJ"; 180 | let mut result: Vec = vec![0x0; 40]; 181 | unsafe { 182 | sha1_to_hex_avx2(data, &mut result); 183 | } 184 | let hex_string = unsafe { String::from_utf8_unchecked(result) }; 185 | assert_eq!(hex_string, encode_upper(data)); 186 | } 187 | } 188 | 189 | #[test] 190 | #[cfg(target_arch = "aarch64")] 191 | fn test_sha1_to_hex_neon() { 192 | use super::sha1_to_hex_neon; 193 | let data: &[u8; 20] = b"0123456789ABCDEFGHIJ"; 194 | let mut result: Vec = vec![0x0; 40]; 195 | unsafe { 196 | sha1_to_hex_neon(data, &mut result); 197 | } 198 | let hex_string = unsafe { String::from_utf8_unchecked(result) }; 199 | assert_eq!(hex_string, encode_upper(data)); 200 | } 201 | 202 | #[test] 203 | #[cfg(target_arch = "loongarch64")] 204 | #[cfg(compilerSupportLSX)] 205 | fn test_sha1_to_hex_lsx() { 206 | use super::sha1_to_hex_lsx; 207 | let data: &[u8; 20] = b"0123456789ABCDEFGHIJ"; 208 | let mut result: Vec = vec![0x0; 40]; 209 | unsafe { 210 | sha1_to_hex_lsx(data, &mut result); 211 | } 212 | let hex_string = unsafe { String::from_utf8_unchecked(result) }; 213 | assert_eq!(hex_string, encode_upper(data)); 214 | } 215 | 216 | #[test] 217 | fn test_sha1_to_hex() { 218 | let data: &[u8; 20] = b"0123456789ABCDEFGHIJ"; 219 | assert_eq!(sha1_to_hex(data), encode_upper(data)); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/pgp_backends/mod.rs: -------------------------------------------------------------------------------- 1 | //! OpenPGP processing backends 2 | //! 3 | //! This module contains adapters or wrappers for different OpenPGP implementations. 4 | mod hex; 5 | 6 | #[cfg(feature = "rpgp")] 7 | mod rpgp_backend; 8 | #[cfg(feature = "sequoia")] 9 | mod sequoia_backend; 10 | 11 | pub use anyhow::Error as UniversalError; 12 | use thiserror::Error; 13 | 14 | pub use self::hex::sha1_to_hex; 15 | 16 | #[cfg(feature = "sequoia")] 17 | pub use sequoia_backend::SequoiaBackend; 18 | 19 | #[cfg(feature = "rpgp")] 20 | pub use rpgp_backend::RPGPBackend; 21 | 22 | use std::str::FromStr; 23 | 24 | /// The default backend 25 | #[cfg(any( 26 | all(feature = "sequoia", not(feature = "rpgp")), 27 | all(feature = "sequoia", feature = "rpgp") 28 | ))] 29 | pub type DefaultBackend = SequoiaBackend; 30 | 31 | /// The default backend 32 | #[cfg(all(feature = "rpgp", not(feature = "sequoia")))] 33 | pub type DefaultBackend = RPGPBackend; 34 | 35 | /// Universal PGP errors 36 | #[derive(Clone, Debug, Error)] 37 | pub enum PGPError { 38 | #[error("Cipher suite not supported: {0}")] 39 | CipherSuiteNotSupported(String), 40 | #[error("Algorithm is not supported by the current backend: {0}")] 41 | AlgorithmNotSupportedByTheCurrentBackend(String), 42 | #[error("Failed to generate key")] 43 | KeyGenerationFailed, 44 | #[error("This is a mysterious error, it should never appear")] 45 | MysteriousError, 46 | #[error("Invalid key generated")] 47 | InvalidKeyGenerated, 48 | #[error("Failed to modify generation time")] 49 | FailedToModifyGenerationTime, 50 | } 51 | 52 | /// Cipher suites for OpenPGP keys 53 | #[derive(Debug, Clone)] 54 | pub enum CipherSuite { 55 | RSA2048, 56 | RSA3072, 57 | RSA4096, 58 | Curve25519, 59 | NistP256, 60 | NistP384, 61 | NistP521, 62 | } 63 | 64 | /// Variations of RSA keys 65 | #[derive(Debug, Clone)] 66 | pub enum Rsa { 67 | RSA2048, 68 | RSA3072, 69 | RSA4096, 70 | } 71 | 72 | /// Variations of ECC curves 73 | #[derive(Debug, Clone)] 74 | pub enum Curve { 75 | Cv25519, 76 | Ed25519, 77 | NistP256, 78 | NistP384, 79 | NistP521, 80 | } 81 | 82 | /// Algorithms 83 | #[derive(Debug, Clone)] 84 | pub enum Algorithms { 85 | Rsa(Rsa), 86 | Ecc(Curve), 87 | } 88 | 89 | /// UserID 90 | #[derive(Debug, Clone)] 91 | pub struct UserID { 92 | id: Option, 93 | } 94 | 95 | /// Wrapped armored keys 96 | #[derive(Debug, Clone)] 97 | pub struct ArmoredKey { 98 | public: String, 99 | private: String, 100 | } 101 | 102 | /// Backend adaptor trait 103 | pub trait Backend { 104 | /// Get the fingerprint of the key 105 | fn fingerprint(&self) -> String; 106 | 107 | /// Rehash the fingerprint 108 | fn shuffle(&mut self) -> Result<(), PGPError>; 109 | 110 | /// Get armored secret key and public key 111 | fn get_armored_results(self, uid: &UserID) -> Result; 112 | } 113 | 114 | impl FromStr for UserID { 115 | type Err = PGPError; 116 | 117 | fn from_str(s: &str) -> Result { 118 | Ok(Self { 119 | id: Some(s.to_string()), 120 | }) 121 | } 122 | } 123 | 124 | impl From for UserID { 125 | fn from(string: String) -> Self { 126 | Self { id: Some(string) } 127 | } 128 | } 129 | 130 | impl From> for UserID { 131 | fn from(string: Option) -> Self { 132 | Self { id: string } 133 | } 134 | } 135 | 136 | impl Default for CipherSuite { 137 | fn default() -> Self { 138 | Self::Curve25519 139 | } 140 | } 141 | 142 | impl FromStr for CipherSuite { 143 | type Err = PGPError; 144 | 145 | fn from_str(s: &str) -> Result { 146 | match s.to_lowercase().as_str() { 147 | "rsa2048" | "rsa2k" => Ok(CipherSuite::RSA2048), 148 | "rsa3072" | "rsa3k" => Ok(CipherSuite::RSA3072), 149 | "rsa4096" | "rsa4k" => Ok(CipherSuite::RSA4096), 150 | "cv25519" | "ed25519" | "curve25519" => Ok(CipherSuite::Curve25519), 151 | "nistp256" | "p256" => Ok(CipherSuite::NistP256), 152 | "nistp384" | "p384" => Ok(CipherSuite::NistP384), 153 | "nistp521" | "p521" => Ok(CipherSuite::NistP521), 154 | s => Err(PGPError::CipherSuiteNotSupported(String::from(s))), 155 | } 156 | } 157 | } 158 | 159 | impl CipherSuite { 160 | /// Get the specific algorithm from cipher suite 161 | fn get_algorithm(&self, encryption: bool) -> Algorithms { 162 | match self { 163 | CipherSuite::RSA2048 => Algorithms::Rsa(Rsa::RSA2048), 164 | CipherSuite::RSA3072 => Algorithms::Rsa(Rsa::RSA3072), 165 | CipherSuite::RSA4096 => Algorithms::Rsa(Rsa::RSA4096), 166 | CipherSuite::Curve25519 => { 167 | if encryption { 168 | Algorithms::Ecc(Curve::Cv25519) 169 | } else { 170 | Algorithms::Ecc(Curve::Ed25519) 171 | } 172 | } 173 | CipherSuite::NistP256 => Algorithms::Ecc(Curve::NistP256), 174 | CipherSuite::NistP384 => Algorithms::Ecc(Curve::NistP384), 175 | CipherSuite::NistP521 => Algorithms::Ecc(Curve::NistP521), 176 | } 177 | } 178 | 179 | /// Get singing key algorithm with the current cipher suite 180 | pub fn get_signing_key_algorithm(&self) -> Algorithms { 181 | self.get_algorithm(false) 182 | } 183 | 184 | /// Get the encryption algorithm with the current cipher suite 185 | pub fn get_encryption_key_algorithm(&self) -> Algorithms { 186 | self.get_algorithm(true) 187 | } 188 | } 189 | 190 | impl UserID { 191 | /// Unwrap the UserID 192 | pub fn get_id(&self) -> Option { 193 | self.id.clone() 194 | } 195 | } 196 | 197 | impl ArmoredKey { 198 | /// Create new instance 199 | pub fn new>(public: S, private: S) -> Self { 200 | Self { 201 | public: public.into(), 202 | private: private.into(), 203 | } 204 | } 205 | 206 | /// Get a reference to the public key 207 | pub fn get_public_key(&self) -> &str { 208 | &self.public 209 | } 210 | 211 | /// Get a reference to the private key 212 | pub fn get_private_key(&self) -> &str { 213 | &self.private 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/pgp_backends/rpgp_backend.rs: -------------------------------------------------------------------------------- 1 | //! rPGP backend 2 | //! 3 | //! This is a wrapper of the `rPGP` crate for generating vanity OpenPGP keys. 4 | 5 | use byteorder::{BigEndian, ByteOrder}; 6 | use chrono::{DateTime, TimeZone, Utc}; 7 | use pgp::composed::{KeyDetails, SecretKey, SecretSubkey}; 8 | use pgp::crypto::hash::HashAlgorithm; 9 | use pgp::crypto::public_key::PublicKeyAlgorithm; 10 | use pgp::crypto::sym::SymmetricKeyAlgorithm; 11 | use pgp::crypto::{ecdh, eddsa, rsa}; 12 | use pgp::key::KeyType; 13 | use pgp::packet::{ 14 | KeyFlags, PublicKey as PublicKeyPacket, PublicSubkey as PublicSubkeyPacket, 15 | SecretKey as SecretKeyPacket, SecretSubkey as SecretSubkeyPacket, UserId as UserIDPacket, 16 | }; 17 | use pgp::ser::Serialize; 18 | use pgp::types::{ 19 | CompressionAlgorithm, KeyVersion, PublicParams, SecretKeyTrait, SecretParams, Version, 20 | }; 21 | use rand::rngs::StdRng; 22 | use rand::SeedableRng; 23 | use sha1::{Digest, Sha1}; 24 | use smallvec::smallvec; 25 | 26 | use super::{sha1_to_hex, ArmoredKey, Backend, CipherSuite, PGPError, UniversalError, UserID}; 27 | 28 | /// Converter for transmuting to struct with private fields 29 | #[allow(dead_code)] 30 | struct PublicKeyPacketConverter { 31 | packet_version: Version, 32 | version: KeyVersion, 33 | algorithm: PublicKeyAlgorithm, 34 | created_at: DateTime, 35 | expiration: Option, 36 | public_params: PublicParams, 37 | } 38 | 39 | /// Converter for transmuting to struct with private fields 40 | #[allow(dead_code)] 41 | struct SecretKeyPacketConverter { 42 | details: PublicKeyPacket, 43 | secret_params: SecretParams, 44 | } 45 | 46 | /// Converter for transmuting to struct with private fields 47 | #[allow(dead_code)] 48 | struct SecretSubkeyPacketConverter { 49 | details: PublicSubkeyPacket, 50 | secret_params: SecretParams, 51 | } 52 | 53 | /// VanityGPG backend powered by rPGP 54 | #[derive(Debug)] 55 | pub struct RPGPBackend { 56 | public_params: PublicParams, 57 | secret_params: SecretParams, 58 | key_type: KeyType, 59 | cipher_suite: CipherSuite, 60 | timestamp: u32, 61 | packet_cache: Vec, 62 | } 63 | 64 | /// Generate key with the required `CipherSuite` 65 | // So messy, wow 66 | fn generate_key( 67 | cipher_suite: &CipherSuite, 68 | for_signing: bool, 69 | ) -> Result<(KeyType, PublicParams, SecretParams), PGPError> { 70 | let mut rng = StdRng::from_entropy(); 71 | match { 72 | match cipher_suite { 73 | &CipherSuite::RSA2048 => { 74 | Ok((KeyType::Rsa(2048), rsa::generate_key(&mut rng, 2048usize))) 75 | } 76 | &CipherSuite::RSA3072 => { 77 | Ok((KeyType::Rsa(3072), rsa::generate_key(&mut rng, 3072usize))) 78 | } 79 | &CipherSuite::RSA4096 => { 80 | Ok((KeyType::Rsa(4096), rsa::generate_key(&mut rng, 4096usize))) 81 | } 82 | &CipherSuite::Curve25519 => { 83 | if for_signing { 84 | Ok((KeyType::EdDSA, Ok(eddsa::generate_key(&mut rng)))) 85 | } else { 86 | Ok((KeyType::ECDH, Ok(ecdh::generate_key(&mut rng)))) 87 | } 88 | } 89 | _ => Err(PGPError::AlgorithmNotSupportedByTheCurrentBackend( 90 | "NIST ECC curves are not supported".to_string(), 91 | )), 92 | } 93 | } { 94 | Ok((key_type, Ok((public_params, plain_secret_params)))) => Ok(( 95 | key_type, 96 | public_params, 97 | SecretParams::Plain(plain_secret_params), 98 | )), 99 | Ok((_key_type, Err(_))) => Err(PGPError::KeyGenerationFailed), 100 | Err(e) => Err(e), 101 | } 102 | } 103 | 104 | impl Into for PublicKeyPacketConverter { 105 | /// Transmuting to `PublicKeyPacket` 106 | fn into(self) -> PublicKeyPacket { 107 | unsafe { std::mem::transmute::(self) } 108 | } 109 | } 110 | 111 | impl Into for PublicKeyPacketConverter { 112 | /// Transmuting to `PublicSubkeyPacket` 113 | fn into(self) -> PublicSubkeyPacket { 114 | unsafe { std::mem::transmute::(self) } 115 | } 116 | } 117 | 118 | impl PublicKeyPacketConverter { 119 | /// Create new instance 120 | fn new(algorithm: PublicKeyAlgorithm, public_params: PublicParams, created_at: u32) -> Self { 121 | Self { 122 | packet_version: Version::New, 123 | version: KeyVersion::V4, 124 | algorithm, 125 | created_at: Utc.timestamp(created_at as i64, 0), 126 | expiration: None, 127 | public_params, 128 | } 129 | } 130 | } 131 | 132 | impl Into for SecretKeyPacketConverter { 133 | /// Transmuting to `SecretKeyPacket` 134 | fn into(self) -> SecretKeyPacket { 135 | unsafe { std::mem::transmute::(self) } 136 | } 137 | } 138 | 139 | impl SecretKeyPacketConverter { 140 | /// Create new instance 141 | fn new(details: PublicKeyPacket, secret_params: SecretParams) -> Self { 142 | Self { 143 | details, 144 | secret_params, 145 | } 146 | } 147 | } 148 | 149 | impl Into for SecretSubkeyPacketConverter { 150 | /// Transmuting to `SecretSubkeyPacket` 151 | fn into(self) -> SecretSubkeyPacket { 152 | unsafe { std::mem::transmute::(self) } 153 | } 154 | } 155 | 156 | impl SecretSubkeyPacketConverter { 157 | /// Create new instance 158 | fn new(details: PublicSubkeyPacket, secret_params: SecretParams) -> Self { 159 | Self { 160 | details, 161 | secret_params, 162 | } 163 | } 164 | } 165 | 166 | impl Backend for RPGPBackend { 167 | fn fingerprint(&self) -> String { 168 | let mut hasher = Sha1::new(); 169 | hasher.update(&self.packet_cache); 170 | sha1_to_hex(&hasher.finalize().to_vec()) 171 | } 172 | 173 | fn shuffle(&mut self) -> Result<(), PGPError> { 174 | self.timestamp -= 1; 175 | BigEndian::write_u32(&mut self.packet_cache[4..8], self.timestamp); 176 | Ok(()) 177 | } 178 | 179 | fn get_armored_results(self, uid: &UserID) -> Result { 180 | // Generate Subkey 181 | let mut subkey_flags = KeyFlags::default(); 182 | subkey_flags.set_encrypt_storage(true); 183 | subkey_flags.set_encrypt_comms(true); 184 | let (subkey_type, subkey_public_params, subkey_secret_params) = 185 | generate_key(&self.cipher_suite, false)?; 186 | let public_subkey_packet: PublicSubkeyPacket = PublicKeyPacketConverter::new( 187 | subkey_type.to_alg(), 188 | subkey_public_params, 189 | self.timestamp, 190 | ) 191 | .into(); 192 | let secret_subkey_packet: SecretSubkeyPacket = 193 | SecretSubkeyPacketConverter::new(public_subkey_packet, subkey_secret_params).into(); 194 | let secret_subkey = SecretSubkey::new(secret_subkey_packet, subkey_flags); 195 | 196 | let uid_packet = 197 | UserIDPacket::from_str(Default::default(), &uid.get_id().unwrap_or("".to_string())); 198 | let mut key_flags = KeyFlags::default(); 199 | key_flags.set_certify(true); 200 | key_flags.set_sign(true); 201 | let key_details = KeyDetails::new( 202 | uid_packet, 203 | Vec::new(), 204 | Vec::new(), 205 | key_flags, 206 | smallvec![SymmetricKeyAlgorithm::AES256, SymmetricKeyAlgorithm::AES128,], 207 | smallvec![HashAlgorithm::SHA2_512, HashAlgorithm::SHA2_256], 208 | smallvec![CompressionAlgorithm::ZLIB], 209 | None, 210 | ); 211 | let primary_public_key_packet: PublicKeyPacket = PublicKeyPacketConverter::new( 212 | self.key_type.to_alg(), 213 | self.public_params, 214 | self.timestamp, 215 | ) 216 | .into(); 217 | let primary_secret_key_packet: SecretKeyPacket = 218 | SecretKeyPacketConverter::new(primary_public_key_packet, self.secret_params).into(); 219 | 220 | let signed_secret_key = SecretKey::new( 221 | primary_secret_key_packet, 222 | key_details, 223 | Default::default(), 224 | vec![secret_subkey], 225 | ) 226 | .sign(|| "".to_string())?; 227 | 228 | let signed_public_key = signed_secret_key 229 | .public_key() 230 | .sign(&signed_secret_key, || "".to_string())?; 231 | 232 | Ok(ArmoredKey::new( 233 | signed_public_key.to_armored_string(None)?, 234 | signed_secret_key.to_armored_string(None)?, 235 | )) 236 | } 237 | } 238 | 239 | impl RPGPBackend { 240 | /// Create new instance 241 | pub fn new>(cipher_suite: C) -> Result { 242 | let valid_cipher_suite = cipher_suite.into(); 243 | if let Ok((key_type, public_params, secret_params)) = 244 | generate_key(&valid_cipher_suite, true) 245 | { 246 | let timestamp = Utc::now().timestamp() as u32; 247 | let mut packet_cache: Vec = vec![0x99, 0, 0, 4, 0, 0, 0, 0]; // Version 4 248 | BigEndian::write_u32(&mut packet_cache[4..8], timestamp); // Timestamp 249 | packet_cache.push(key_type.to_alg() as u8); // Algorithm identifier 250 | public_params 251 | .to_writer(&mut packet_cache) 252 | .expect("Failed to write public_params to packet cache"); 253 | let packet_length = (packet_cache.len() as u16) - 3; 254 | BigEndian::write_u16(&mut packet_cache[1..3], packet_length); 255 | Ok(Self { 256 | public_params, 257 | secret_params, 258 | key_type, 259 | cipher_suite: valid_cipher_suite, 260 | timestamp, 261 | packet_cache, 262 | }) 263 | } else { 264 | Err(PGPError::KeyGenerationFailed) 265 | } 266 | } 267 | 268 | #[allow(dead_code)] 269 | /// Get public params 270 | pub(crate) fn get_public_params(self) -> PublicParams { 271 | self.public_params 272 | } 273 | 274 | #[allow(dead_code)] 275 | /// Get `u32` timestamp 276 | // Boo! You've just found something that will go wrong after the year 2038 277 | pub(crate) fn get_timestamp(&self) -> u32 { 278 | self.timestamp 279 | } 280 | } 281 | 282 | #[cfg(test)] 283 | mod rpgp_backend_test { 284 | use super::{ 285 | Backend, CipherSuite, PublicKeyAlgorithm, PublicKeyPacket, PublicKeyPacketConverter, 286 | RPGPBackend, UserID, 287 | }; 288 | use hex::encode_upper; 289 | use pgp::composed::{Deserializable, SignedSecretKey}; 290 | use pgp::types::KeyTrait; 291 | use std::io::Cursor; 292 | 293 | #[test] 294 | fn ed25519_key_generation() { 295 | let backend = RPGPBackend::new(CipherSuite::Curve25519).unwrap(); 296 | let timestamp = backend.get_timestamp(); 297 | let public_params = backend.get_public_params(); 298 | let _public_key_packet: PublicKeyPacket = 299 | PublicKeyPacketConverter::new(PublicKeyAlgorithm::EdDSA, public_params, timestamp) 300 | .into(); 301 | } 302 | 303 | #[test] 304 | fn ed25519_fingerprint_calculation() { 305 | let backend = RPGPBackend::new(CipherSuite::Curve25519).unwrap(); 306 | let fingerprint_custom = backend.fingerprint(); 307 | let timestamp = backend.get_timestamp(); 308 | let public_params = backend.get_public_params(); 309 | let public_key_packet: PublicKeyPacket = 310 | PublicKeyPacketConverter::new(PublicKeyAlgorithm::EdDSA, public_params, timestamp) 311 | .into(); 312 | let fingerprint_rpgp = encode_upper(public_key_packet.fingerprint()); 313 | 314 | assert_eq!(fingerprint_custom, fingerprint_rpgp); 315 | } 316 | 317 | #[test] 318 | fn ed25519_shuffle() { 319 | let mut backend = RPGPBackend::new(CipherSuite::Curve25519).unwrap(); 320 | let fingerprint_custom_before = backend.fingerprint(); 321 | let timestamp_before = backend.get_timestamp(); 322 | backend.shuffle().unwrap(); 323 | let fingerprint_custom_after = backend.fingerprint(); 324 | let timestamp_after = backend.get_timestamp(); 325 | assert_ne!(timestamp_before, timestamp_after); 326 | 327 | let public_params = backend.get_public_params(); 328 | let public_key_packet_before: PublicKeyPacket = PublicKeyPacketConverter::new( 329 | PublicKeyAlgorithm::EdDSA, 330 | public_params.clone(), 331 | timestamp_before, 332 | ) 333 | .into(); 334 | let fingerprint_rpgp_before = encode_upper(public_key_packet_before.fingerprint()); 335 | let public_key_packet_after: PublicKeyPacket = PublicKeyPacketConverter::new( 336 | PublicKeyAlgorithm::EdDSA, 337 | public_params, 338 | timestamp_after, 339 | ) 340 | .into(); 341 | let fingerprint_rpgp_after = encode_upper(public_key_packet_after.fingerprint()); 342 | 343 | assert_eq!(fingerprint_custom_before, fingerprint_rpgp_before); 344 | assert_eq!(fingerprint_custom_after, fingerprint_rpgp_after); 345 | } 346 | 347 | #[test] 348 | fn ed25519_export() { 349 | let mut backend = RPGPBackend::new(CipherSuite::Curve25519).unwrap(); 350 | backend.shuffle().unwrap(); 351 | let fingerprint_before = backend.fingerprint(); 352 | let uid = UserID::from("Tiansuo Li <114514@example.com>".to_string()); 353 | let results = backend.get_armored_results(&uid).unwrap(); 354 | assert!(!results.get_private_key().is_empty()); 355 | assert!(!results.get_public_key().is_empty()); 356 | 357 | let cursor = Cursor::new(results.get_private_key()); 358 | 359 | let key = SignedSecretKey::from_armor_single(cursor).unwrap().0; 360 | let fingerprint_after = encode_upper(key.fingerprint()); 361 | assert_eq!(fingerprint_before, fingerprint_after); 362 | assert_eq!(key.algorithm(), PublicKeyAlgorithm::EdDSA); 363 | assert_eq!( 364 | &key.details.users[0].id.id(), 365 | &"Tiansuo Li <114514@example.com>" 366 | ); 367 | key.verify().unwrap(); 368 | } 369 | 370 | #[test] 371 | fn rsa2048_key_generation() { 372 | let backend = RPGPBackend::new(CipherSuite::RSA2048).unwrap(); 373 | let timestamp = backend.get_timestamp(); 374 | let public_params = backend.get_public_params(); 375 | let _public_key_packet: PublicKeyPacket = 376 | PublicKeyPacketConverter::new(PublicKeyAlgorithm::RSA, public_params, timestamp).into(); 377 | } 378 | 379 | #[test] 380 | fn rsa2048_fingerprint_calculation() { 381 | let backend = RPGPBackend::new(CipherSuite::RSA2048).unwrap(); 382 | let fingerprint_custom = backend.fingerprint(); 383 | let timestamp = backend.get_timestamp(); 384 | let public_params = backend.get_public_params(); 385 | let public_key_packet: PublicKeyPacket = 386 | PublicKeyPacketConverter::new(PublicKeyAlgorithm::RSA, public_params, timestamp).into(); 387 | let fingerprint_rpgp = encode_upper(public_key_packet.fingerprint()); 388 | 389 | assert_eq!(fingerprint_custom, fingerprint_rpgp); 390 | } 391 | 392 | #[test] 393 | fn rsa2048_shuffle() { 394 | let mut backend = RPGPBackend::new(CipherSuite::RSA2048).unwrap(); 395 | let fingerprint_custom_before = backend.fingerprint(); 396 | let timestamp_before = backend.get_timestamp(); 397 | backend.shuffle().unwrap(); 398 | let fingerprint_custom_after = backend.fingerprint(); 399 | let timestamp_after = backend.get_timestamp(); 400 | assert_ne!(timestamp_before, timestamp_after); 401 | 402 | let public_params = backend.get_public_params(); 403 | let public_key_packet_before: PublicKeyPacket = PublicKeyPacketConverter::new( 404 | PublicKeyAlgorithm::RSA, 405 | public_params.clone(), 406 | timestamp_before, 407 | ) 408 | .into(); 409 | let fingerprint_rpgp_before = encode_upper(public_key_packet_before.fingerprint()); 410 | let public_key_packet_after: PublicKeyPacket = 411 | PublicKeyPacketConverter::new(PublicKeyAlgorithm::RSA, public_params, timestamp_after) 412 | .into(); 413 | let fingerprint_rpgp_after = encode_upper(public_key_packet_after.fingerprint()); 414 | 415 | assert_eq!(fingerprint_custom_before, fingerprint_rpgp_before); 416 | assert_eq!(fingerprint_custom_after, fingerprint_rpgp_after); 417 | } 418 | 419 | #[test] 420 | fn rsa2048_export() { 421 | let mut backend = RPGPBackend::new(CipherSuite::RSA2048).unwrap(); 422 | backend.shuffle().unwrap(); 423 | let fingerprint_before = backend.fingerprint(); 424 | let uid = UserID::from("Tiansuo Li <114514@example.com>".to_string()); 425 | let results = backend.get_armored_results(&uid).unwrap(); 426 | assert!(!results.get_private_key().is_empty()); 427 | assert!(!results.get_public_key().is_empty()); 428 | 429 | let cursor = Cursor::new(results.get_private_key()); 430 | 431 | let key = SignedSecretKey::from_armor_single(cursor).unwrap().0; 432 | let fingerprint_after = encode_upper(key.fingerprint()); 433 | assert_eq!(fingerprint_before, fingerprint_after); 434 | assert_eq!(key.algorithm(), PublicKeyAlgorithm::RSA); 435 | assert_eq!( 436 | &key.details.users[0].id.id(), 437 | &"Tiansuo Li <114514@example.com>" 438 | ); 439 | key.verify().unwrap(); 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /src/pgp_backends/sequoia_backend.rs: -------------------------------------------------------------------------------- 1 | //! Sequoia-OpenPGP backend 2 | //! 3 | //! This is a wrapper of the `Sequoia-OpenPGP` crate for generating vanity OpenPGP keys. 4 | 5 | use byteorder::{BigEndian, ByteOrder}; 6 | use nettle::hash::insecure_do_not_use::Sha1; 7 | use nettle::hash::Hash; 8 | use sequoia_openpgp::armor::{Kind, Writer}; 9 | use sequoia_openpgp::packet::key::{Key4, PrimaryRole, SecretParts}; 10 | use sequoia_openpgp::packet::signature::SignatureBuilder; 11 | use sequoia_openpgp::packet::Key; 12 | use sequoia_openpgp::packet::UserID as SequoiaUserID; 13 | use sequoia_openpgp::serialize::{MarshalInto, SerializeInto}; 14 | use sequoia_openpgp::types::{ 15 | Curve as SequoiaCurve, Features, HashAlgorithm, KeyFlags, SignatureType, SymmetricAlgorithm, 16 | }; 17 | use sequoia_openpgp::{Cert, Packet}; 18 | 19 | use super::{ 20 | sha1_to_hex, Algorithms, ArmoredKey, Backend, CipherSuite, Curve, PGPError, Rsa, 21 | UniversalError, UserID, 22 | }; 23 | 24 | use std::io::Write; 25 | use std::time::Duration; 26 | use std::time::UNIX_EPOCH; 27 | 28 | /// The `Sequoia-OpenPGP` backend wrapper 29 | #[derive(Debug)] 30 | pub struct SequoiaBackend { 31 | primary_key: Key4, 32 | cipher_suite: CipherSuite, 33 | timestamp: u32, 34 | packet_cache: Vec, 35 | } 36 | 37 | /// Generate key with the required `CipherSuite` 38 | fn generate_key( 39 | algorithm: Algorithms, 40 | for_signing: bool, 41 | ) -> Result, PGPError> { 42 | let wrapped_key: Result, UniversalError> = match algorithm { 43 | Algorithms::Rsa(rsa) => match rsa { 44 | Rsa::RSA2048 => Key4::generate_rsa(2048), 45 | Rsa::RSA3072 => Key4::generate_rsa(3072), 46 | Rsa::RSA4096 => Key4::generate_rsa(4096), 47 | }, 48 | Algorithms::Ecc(curve) => match curve { 49 | Curve::Ed25519 => Key4::generate_ecc(for_signing, SequoiaCurve::Ed25519), 50 | Curve::Cv25519 => Key4::generate_ecc(for_signing, SequoiaCurve::Cv25519), 51 | Curve::NistP256 => Key4::generate_ecc(for_signing, SequoiaCurve::NistP256), 52 | Curve::NistP384 => Key4::generate_ecc(for_signing, SequoiaCurve::NistP384), 53 | Curve::NistP521 => Key4::generate_ecc(for_signing, SequoiaCurve::NistP521), 54 | }, 55 | }; 56 | if let Ok(key) = wrapped_key { 57 | Ok(key) 58 | } else { 59 | Err(PGPError::KeyGenerationFailed) 60 | } 61 | } 62 | 63 | impl Backend for SequoiaBackend { 64 | fn fingerprint(&self) -> String { 65 | let mut hasher = Sha1::default(); 66 | hasher.update(&self.packet_cache); 67 | let mut digest_buffer: [u8; 20] = [0; 20]; 68 | hasher.digest(&mut digest_buffer); 69 | // hex_string(&digest_buffer).unwrap() 70 | sha1_to_hex(&digest_buffer) 71 | } 72 | 73 | fn shuffle(&mut self) -> Result<(), PGPError> { 74 | self.timestamp -= 1; 75 | BigEndian::write_u32(&mut self.packet_cache[4..8], self.timestamp); 76 | Ok(()) 77 | } 78 | 79 | fn get_armored_results(mut self, uid: &UserID) -> Result { 80 | let creation_time = UNIX_EPOCH + Duration::from_secs(self.timestamp as u64); 81 | self.primary_key.set_creation_time(creation_time)?; 82 | let mut packets = Vec::::new(); 83 | let mut signer = self.primary_key.clone().into_keypair()?; 84 | let primary_key_packet = Key::V4(self.primary_key); 85 | 86 | // Direct key signature and the secret key 87 | let direct_key_signature = SignatureBuilder::new(SignatureType::DirectKey) 88 | .set_hash_algo(HashAlgorithm::SHA512) 89 | .set_features(Features::sequoia())? 90 | .set_key_flags(KeyFlags::empty().set_certification().set_signing())? 91 | .set_signature_creation_time(creation_time)? 92 | .set_key_validity_period(None)? 93 | .set_preferred_hash_algorithms(vec![HashAlgorithm::SHA512, HashAlgorithm::SHA256])? 94 | .set_preferred_symmetric_algorithms(vec![ 95 | SymmetricAlgorithm::AES256, 96 | SymmetricAlgorithm::AES128, 97 | ])? 98 | .sign_direct_key(&mut signer, Some(primary_key_packet.parts_as_public()))?; 99 | packets.push(Packet::SecretKey(primary_key_packet)); 100 | packets.push(direct_key_signature.clone().into()); 101 | 102 | // Build certificate 103 | let mut cert = Cert::from_packets(packets.into_iter())?; 104 | 105 | // UID 106 | if let Some(uid_string) = uid.get_id() { 107 | let uid_signature_builder = SignatureBuilder::from(direct_key_signature) 108 | .set_signature_creation_time(creation_time)? 109 | .set_revocation_key(vec![])? // Remove revocation certificate 110 | .set_type(SignatureType::PositiveCertification) 111 | .set_hash_algo(HashAlgorithm::SHA512); 112 | let uid_packet = SequoiaUserID::from(uid_string); 113 | let uid_signature = uid_packet.bind(&mut signer, &cert, uid_signature_builder)?; 114 | cert = cert.insert_packets(vec![Packet::from(uid_packet), uid_signature.into()])?; 115 | } 116 | 117 | // Encryption subkey 118 | let mut subkey = generate_key(self.cipher_suite.get_encryption_key_algorithm(), false)? 119 | .parts_into_secret()? 120 | .role_into_subordinate(); 121 | subkey.set_creation_time(creation_time)?; 122 | let subkey_packet = Key::V4(subkey); 123 | let subkey_signature_builder = SignatureBuilder::new(SignatureType::SubkeyBinding) 124 | .set_signature_creation_time(creation_time)? 125 | .set_hash_algo(HashAlgorithm::SHA512) 126 | .set_features(Features::sequoia())? 127 | .set_key_flags(KeyFlags::empty().set_storage_encryption())? 128 | .set_key_validity_period(None)?; 129 | let subkey_signature = subkey_packet.bind(&mut signer, &cert, subkey_signature_builder)?; 130 | cert = cert.insert_packets(vec![ 131 | Packet::SecretSubkey(subkey_packet), 132 | subkey_signature.into(), 133 | ])?; 134 | 135 | if cert.unknowns().next().is_none() { 136 | // Get armored texts 137 | let armored_public_key = String::from_utf8(SerializeInto::to_vec(&cert.armored())?)?; 138 | let private_hex = SerializeInto::to_vec(&cert.as_tsk())?; 139 | let mut private_key_writer = Writer::new(Vec::new(), Kind::SecretKey)?; 140 | private_key_writer.write_all(&private_hex)?; 141 | let armored_private_key = 142 | String::from_utf8_lossy(&private_key_writer.finalize()?).to_string(); 143 | 144 | Ok(ArmoredKey::new(armored_public_key, armored_private_key)) 145 | } else { 146 | Err(PGPError::InvalidKeyGenerated.into()) 147 | } 148 | } 149 | } 150 | 151 | impl SequoiaBackend { 152 | /// Create new instance 153 | pub fn new>(cipher_suite: C) -> Result { 154 | let ciphers = cipher_suite.into(); 155 | let primary_key = generate_key(ciphers.get_signing_key_algorithm(), true)?; 156 | 157 | // Build packet cache 158 | let mut packet_cache: Vec = vec![0x99, 0, 0, 4, 0, 0, 0, 0]; 159 | let packet_length = 6 + primary_key.mpis().serialized_len() as u16; 160 | BigEndian::write_u16(&mut packet_cache[1..3], packet_length); // Packet length 161 | let timestamp = primary_key 162 | .creation_time() 163 | .duration_since(UNIX_EPOCH) 164 | .expect("Failed to get timestamp") 165 | .as_secs() as u32; 166 | BigEndian::write_u32(&mut packet_cache[4..8], timestamp); // Timestamp 167 | packet_cache.push(primary_key.pk_algo().into()); // Algorithm identifier 168 | let mut public_key_buffer = 169 | MarshalInto::to_vec(primary_key.mpis()).expect("Failed to serialize public key"); 170 | packet_cache.append(&mut public_key_buffer); // Public key 171 | 172 | Ok(Self { 173 | primary_key, 174 | cipher_suite: ciphers, 175 | timestamp, 176 | packet_cache, 177 | }) 178 | } 179 | 180 | /// Get primary key 181 | #[allow(dead_code)] 182 | pub(crate) fn get_primary_key(self) -> Key4 { 183 | self.primary_key 184 | } 185 | 186 | /// Get `u32` timestamp 187 | // Boo! You've just found something that will go wrong after the year 2038 188 | #[allow(dead_code)] 189 | pub(crate) fn get_timestamp(&self) -> u32 { 190 | self.timestamp 191 | } 192 | } 193 | 194 | #[cfg(test)] 195 | mod sequoia_backend_test { 196 | use super::{Backend, Cert, CipherSuite, Key, SequoiaBackend, UserID}; 197 | use anyhow::Error; 198 | use sequoia_openpgp::armor::{Reader, ReaderMode}; 199 | use sequoia_openpgp::packet::Signature; 200 | use sequoia_openpgp::parse::Parse; 201 | use sequoia_openpgp::types::PublicKeyAlgorithm; 202 | use std::io::{Cursor, Read}; 203 | use std::time::{Duration, UNIX_EPOCH}; 204 | 205 | #[test] 206 | fn ed25519_key_generation() { 207 | let backend = SequoiaBackend::new(CipherSuite::Curve25519).unwrap(); 208 | let key = backend.get_primary_key(); 209 | assert_eq!(key.pk_algo(), PublicKeyAlgorithm::EdDSA); 210 | } 211 | 212 | #[test] 213 | fn ed25519_fingerprint_calculation() { 214 | let backend = SequoiaBackend::new(CipherSuite::Curve25519).unwrap(); 215 | let fingerprint_custom = backend.fingerprint(); 216 | let fingerprint_sequoia = backend.get_primary_key().fingerprint().to_hex(); 217 | assert_eq!(fingerprint_custom, fingerprint_sequoia); 218 | } 219 | 220 | #[test] 221 | fn ed25519_shuffle() { 222 | let mut backend = SequoiaBackend::new(CipherSuite::Curve25519).unwrap(); 223 | let fingerprint_custom_before = backend.fingerprint(); 224 | let timestamp_before = backend.get_timestamp() as u64; 225 | backend.shuffle().unwrap(); 226 | let fingerprint_custom_after = backend.fingerprint(); 227 | let timestamp_after = backend.get_timestamp() as u64; 228 | assert_ne!(timestamp_before, timestamp_after); 229 | 230 | let mut primary_key = backend.get_primary_key(); 231 | primary_key 232 | .set_creation_time(UNIX_EPOCH.clone() + Duration::from_secs(timestamp_before)) 233 | .unwrap(); 234 | let fingerprint_sequoia_before = primary_key.fingerprint().to_hex(); 235 | primary_key 236 | .set_creation_time(UNIX_EPOCH.clone() + Duration::from_secs(timestamp_after)) 237 | .unwrap(); 238 | let fingerprint_sequoia_after = primary_key.fingerprint().to_hex(); 239 | 240 | assert_eq!(fingerprint_custom_before, fingerprint_sequoia_before); 241 | assert_eq!(fingerprint_custom_after, fingerprint_sequoia_after); 242 | } 243 | 244 | #[test] 245 | fn ed25519_export() { 246 | let mut backend = SequoiaBackend::new(CipherSuite::Curve25519).unwrap(); 247 | backend.shuffle().unwrap(); 248 | let fingerprint_before = backend.fingerprint(); 249 | let uid = UserID::from("Tiansuo Li <114514@example.com>".to_string()); 250 | let results = backend.get_armored_results(&uid).unwrap(); 251 | assert!(!results.get_private_key().is_empty()); 252 | assert!(!results.get_public_key().is_empty()); 253 | 254 | let mut cursor = Cursor::new(results.get_private_key()); 255 | let mut reader = Reader::new(&mut cursor, ReaderMode::VeryTolerant); 256 | let mut content = Vec::new(); 257 | reader.read_to_end(&mut content).unwrap(); 258 | let cert = Cert::from_bytes(&content).unwrap(); 259 | let fingerprint_after = cert.fingerprint().to_hex(); 260 | assert_eq!(fingerprint_before, fingerprint_after); 261 | assert!(cert.is_tsk()); 262 | assert!(cert 263 | .bad_signatures() 264 | .collect::>() 265 | .is_empty()); 266 | for uid_after in cert.userids() { 267 | assert_eq!( 268 | String::from_utf8_lossy(uid_after.value()), 269 | "Tiansuo Li <114514@example.com>" 270 | ); 271 | } 272 | let pk = match cert.primary_key().key().clone() { 273 | Key::V4(key_4) => key_4, 274 | _ => unreachable!(), 275 | }; 276 | assert_eq!(pk.pk_algo(), PublicKeyAlgorithm::EdDSA); 277 | } 278 | 279 | #[test] 280 | fn rsa4096_key_generation() { 281 | let backend = SequoiaBackend::new(CipherSuite::RSA4096).unwrap(); 282 | let key = backend.get_primary_key(); 283 | assert_eq!(key.pk_algo(), PublicKeyAlgorithm::RSAEncryptSign); 284 | } 285 | 286 | #[test] 287 | fn rsa4096_fingerprint_calculation() { 288 | let backend = SequoiaBackend::new(CipherSuite::RSA4096).unwrap(); 289 | let fingerprint_custom = backend.fingerprint(); 290 | let fingerprint_sequoia = backend.get_primary_key().fingerprint().to_hex(); 291 | assert_eq!(fingerprint_custom, fingerprint_sequoia); 292 | } 293 | 294 | #[test] 295 | fn rsa4096_shuffle() { 296 | let mut backend = SequoiaBackend::new(CipherSuite::RSA4096).unwrap(); 297 | let fingerprint_custom_before = backend.fingerprint(); 298 | let timestamp_before = backend.get_timestamp() as u64; 299 | backend.shuffle().unwrap(); 300 | let fingerprint_custom_after = backend.fingerprint(); 301 | let timestamp_after = backend.get_timestamp() as u64; 302 | assert_ne!(timestamp_before, timestamp_after); 303 | 304 | let mut primary_key = backend.get_primary_key(); 305 | primary_key 306 | .set_creation_time(UNIX_EPOCH.clone() + Duration::from_secs(timestamp_before)) 307 | .unwrap(); 308 | let fingerprint_sequoia_before = primary_key.fingerprint().to_hex(); 309 | primary_key 310 | .set_creation_time(UNIX_EPOCH.clone() + Duration::from_secs(timestamp_after)) 311 | .unwrap(); 312 | let fingerprint_sequoia_after = primary_key.fingerprint().to_hex(); 313 | 314 | assert_eq!(fingerprint_custom_before, fingerprint_sequoia_before); 315 | assert_eq!(fingerprint_custom_after, fingerprint_sequoia_after); 316 | } 317 | 318 | #[test] 319 | fn rsa4096_export() -> Result<(), Error> { 320 | let mut backend = SequoiaBackend::new(CipherSuite::RSA4096).unwrap(); 321 | backend.shuffle().unwrap(); 322 | let fingerprint_before = backend.fingerprint(); 323 | let uid = UserID::from("Tiansuo Li <114514@example.com>".to_string()); 324 | let results = backend.get_armored_results(&uid).unwrap(); 325 | assert!(!results.get_private_key().is_empty()); 326 | assert!(!results.get_public_key().is_empty()); 327 | 328 | let mut cursor = Cursor::new(results.get_private_key()); 329 | let mut reader = Reader::new(&mut cursor, ReaderMode::VeryTolerant); 330 | let mut content = Vec::new(); 331 | reader.read_to_end(&mut content).unwrap(); 332 | let cert = Cert::from_bytes(&content).unwrap(); 333 | let fingerprint_after = cert.fingerprint().to_hex(); 334 | assert_eq!(fingerprint_before, fingerprint_after); 335 | assert!(cert.is_tsk()); 336 | assert!(cert 337 | .bad_signatures() 338 | .collect::>() 339 | .is_empty()); 340 | for uid_after in cert.userids() { 341 | assert_eq!( 342 | String::from_utf8_lossy(uid_after.value()), 343 | "Tiansuo Li <114514@example.com>" 344 | ); 345 | } 346 | let pk = match cert.primary_key().key().clone() { 347 | Key::V4(key_4) => key_4, 348 | _ => unreachable!(), 349 | }; 350 | assert_eq!(pk.pk_algo(), PublicKeyAlgorithm::RSAEncryptSign); 351 | Ok(()) 352 | } 353 | } 354 | --------------------------------------------------------------------------------