sequoia-sq-0.33.0/.cargo_vcs_info.json0000644000000001360000000000100132060ustar { "git": { "sha1": "195ef2bf9b218ff4d6f25b1854f9f4558f449672" }, "path_in_vcs": "" }sequoia-sq-0.33.0/.ci/all_commits.sh000075500000000000000000000014771046102023000153220ustar 00000000000000#!/usr/bin/env bash # Test all commits on this branch but the last one. # # Used in the all_commits ci job to ensure all commits build # and tests pass at least for the sequoia-openpgp crate. # Use dummy identity to make git rebase happy. git config user.name "C.I. McTestface" git config user.email "ci.mctestface@example.com" # If the previous commit already is on main we're done. git merge-base --is-ancestor HEAD~ origin/main && echo "All commits tested already" && exit 0 # Leave out the last commit - it has already been checked. git checkout HEAD~ git rebase origin/main \ --exec 'echo ===; echo ===; echo ===; git log -n 1;' \ --exec 'cargo test -p sequoia-sq' && echo "All commits passed tests" && exit 0 # The rebase failed - probably because a test failed. git rebase --abort; exit 1 sequoia-sq-0.33.0/.gitattributes000064400000000000000000000000231046102023000146640ustar 00000000000000* text=auto eol=lf sequoia-sq-0.33.0/.gitignore000064400000000000000000000001021046102023000137570ustar 00000000000000/target/ **/*.rs.bk *~ .gdb_history .dir-locals.el /*.html /*.pdf sequoia-sq-0.33.0/.gitlab-ci.yml000064400000000000000000000173711046102023000144430ustar 00000000000000stages: - pre-check - build - test - deploy # These stanzas do some common management tasks before and after the # job-specific before_script and after_script stanzas are run. # before_script_start configures any default global state. The # job-specific before_script can override this state, if required. # before_script_end prints out information about the environment to # improve debugging; it does not modify the environment. # after_script_end does some common management tasks after the # job-specific after_script is run. It prints information about the # environment, and does some clean up. # # Add this to your stanza as follows: # # before_script: # - *before_script_start # - *** YOUR CODE HERE *** # - *before_script_end # after_script: # - *** YOUR CODE HERE *** # - *after_script_end .before_script_start: &before_script_start - 'if test "x${RUSTFLAGS+SET}" = xSET; then echo "\$RUSTFLAGS is set ($RUSTFLAGS)"; exit 1; fi' .before_script_end: &before_script_end - 'if test "x${RUSTFLAGS+SET}" = xSET; then echo "WARNING: before_script set \$RUSTFLAGS ($RUSTFLAGS)"; fi' - rustc --version --verbose - cargo --version - clang -v - if [ -d $CARGO_TARGET_DIR ]; then find $CARGO_TARGET_DIR | wc --lines; du -sh $CARGO_TARGET_DIR; fi - if [ -d $CARGO_HOME ]; then find $CARGO_HOME | wc --lines; du -sh $CARGO_HOME; fi .after_script_end: &after_script_end - if [ -d $CARGO_TARGET_DIR ]; then find $CARGO_TARGET_DIR -type f -atime +7 -delete; fi - if [ -d $CARGO_TARGET_DIR ]; then du -sh $CARGO_TARGET_DIR; fi - if [ -d $CARGO_HOME ]; then du -sh $CARGO_HOME; fi before_script: - *before_script_start - *before_script_end after_script: - *after_script_end trixie: tags: - linux stage: build interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/trixie:latest script: - cargo test --features=subplot - if ! git diff --quiet Cargo.lock ; then echo "Cargo.lock changed. Please add the change to the corresponding commit." ; git diff ; false ; fi - if ! git diff --quiet ; then echo "The build changed the source. Please investigate." ; git diff ; fi variables: CARGO_TARGET_DIR: /target CARGO_HOME: /cargo sq-features: tags: - linux stage: build interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/trixie:latest only: refs: - tags - web - schedules parallel: matrix: - FEATURES: - "" - "autocrypt" - "autocrypt,compression-bzip2" - "compression-bzip2" script: - cargo test --no-default-features --features crypto-nettle --features $FEATURES variables: CARGO_TARGET_DIR: /target CARGO_HOME: /cargo trixie-crypto-openssl: tags: - linux stage: build interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/trixie:latest dependencies: - codespell script: - cargo test --no-default-features --features crypto-openssl,compression-bzip2 variables: CARGO_TARGET_DIR: /target CARGO_HOME: /cargo all_commits: # Test each commit up to main, to facilitate bisecting. stage: test interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/rust-stable:latest needs: ["rust-stable"] script: - .ci/all_commits.sh variables: CARGO_TARGET_DIR: /target CARGO_HOME: /cargo GIT_STRATEGY: clone codespell: tags: - linux stage: pre-check interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/trixie:latest before_script: - *before_script_start - codespell --version - *before_script_end script: - codespell --summary -L "crate,ede,iff,mut,nd,te,uint,KeyServer,keyserver,Keyserver,keyservers,Keyservers,keypair,keypairs,KeyPair,fpr,dedup,deriver,certi,certp,certo" -S "*.bin,*.gpg,*.pgp,./.git,*/target,Cargo.lock" deny: tags: - linux stage: test interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/rust-stable:latest before_script: - *before_script_start - cargo install --locked cargo-deny - *before_script_end script: - cargo deny check rust-stable: tags: - linux stage: build interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/rust-stable:latest before_script: - *before_script_start - rustup override set stable - *before_script_end script: - cargo test --features=subplot variables: CARGO_TARGET_DIR: /target CARGO_HOME: /cargo clippy: tags: - linux stage: build interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/rust-stable:latest before_script: - *before_script_start - apt-get -y install libssl-dev capnproto libsqlite3-dev - rustup default 1.70.0 - rustup component add clippy - cargo clippy --version - *before_script_end script: - cargo clippy variables: CARGO_TARGET_DIR: /target CARGO_HOME: /cargo windows-gnu-cng: tags: - win - win2019 stage: build interruptible: true image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/windows-gnu only: variables: # Forks of this project most likely use gitlab's shared windows runners, which # do not use the docker executor, so disable the windows jobs for forks. - $CI_PROJECT_NAMESPACE == "sequoia-pgp" before_script: # We don't call *before_script_start or *before_script_end as we # don't have bash, clang, etc. - rustup default "1.70.0" - rustc --version --verbose - cargo --version script: # https://github.com/rust-lang/cargo/issues/5015 - pacman --noconfirm --needed -S mingw-w64-x86_64-openssl - cargo test --tests --no-default-features --features crypto-cng,compression-bzip2,subplot after_script: [] # scriptlet doesn't work on Powershell variables: CFLAGS: "" # Silence some C warnings when compiling under Windows docker-build-push: # Official docker image. image: docker:stable stage: build services: - docker:dind tags: - docker - self-hosted before_script: - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY script: - > docker build --no-cache --target sq --tag "$IMAGE":latest . # smoke test - docker run "$IMAGE":latest --help - docker push "$IMAGE":latest after_script: [] only: refs: - /docker/i # refs containing 'docker' keyword - tags - web - schedules variables: CI_REGISTRY: "registry.gitlab.com" IMAGE: "$CI_REGISTRY/sequoia-pgp/sequoia-sq" DOCKER_HOST: tcp://docker:2376 pages: stage: deploy image: 192.168.122.1:5000/sequoia-pgp/build-docker-image/trixie-pandoc:latest script: - ASSET_OUT_DIR=/tmp/assets cargo doc --no-deps -p sequoia-sq - mkdir public - mv -v target/doc public/impl - for M in /tmp/assets/man-pages/*; do pandoc -s $M -L src/man-pandoc.lua -H src/man-pandoc.inc.html -o $M.html ; done - mkdir public/man - mv -v /tmp/assets/man-pages/*.html public/man - mkdir public/subplot - pandoc -s -o public/subplot/sq-subplot.html sq-subplot.md - pandoc -s -o public/subplot/sq-subplot.pdf sq-subplot.md - echo "/sequoia-sq/ /sequoia-sq/man/sq.1.html 302" > public/_redirects - echo "/sequoia-sq/impl /sequoia-sq/impl/sq/index.html 302" >> public/_redirects - echo "/sequoia-sq/man /sequoia-sq/man/sq.1.html 302" >> public/_redirects - echo "/sequoia-sq/subplot /sequoia-sq/subplot/sq-subplot.html 302" >> public/_redirects artifacts: paths: - public only: - main variables: DEBIAN_FRONTEND: noninteractive CARGO_HOME: $CI_PROJECT_DIR/../cargo CARGO_FLAGS: --color always CARGO_INCREMENTAL: 0 RUST_BACKTRACE: full CFLAGS: -Werror QUICKCHECK_GENERATOR_SIZE: 500 # https://github.com/BurntSushi/quickcheck/pull/240 sequoia-sq-0.33.0/Cargo.lock0000644000003270110000000000100111650ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aead" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common", "generic-array", ] [[package]] name = "aes" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if", "cipher", "cpufeatures", "zeroize", ] [[package]] name = "aes-gcm" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", "aes", "cipher", "ctr", "ghash", "subtle", ] [[package]] name = "ahash" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", "version_check", "zerocopy", ] [[package]] name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "aligned" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a21b9440a626c7fc8573a9e3d3a06b75c7c97754c2949bc7857b90353ca655" dependencies = [ "as-slice", ] [[package]] name = "allocator-api2" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anstream" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", "windows-sys 0.52.0", ] [[package]] name = "anyhow" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "as-slice" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" dependencies = [ "stable_deref_trait", ] [[package]] name = "ascii-canvas" version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" dependencies = [ "term", ] [[package]] name = "assert_cmd" version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00ad3f3a942eee60335ab4342358c161ee296829e0d16ff42fc1d6cb07815467" dependencies = [ "anstyle", "bstr", "doc-comment", "predicates", "predicates-core", "predicates-tree", "wait-timeout", ] [[package]] name = "async-trait" version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] [[package]] name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bindgen" version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ "bitflags 2.4.2", "cexpr", "clang-sys", "lazy_static", "lazycell", "peeking_take_while", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn 2.0.48", ] [[package]] name = "bit-set" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "block-padding" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ "generic-array", ] [[package]] name = "blowfish" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" dependencies = [ "byteorder", "cipher", ] [[package]] name = "botan" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350081af1a3c6883f8a1f863ac553bfe6922589aad60008a70947765ed57c53e" dependencies = [ "botan-sys", ] [[package]] name = "botan-sys" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f49dde1b8ebd2996cc41c55c39f6ef8b54e38148d8973aeba0792b87b1621ca" [[package]] name = "bstr" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "regex-automata 0.4.3", "serde", ] [[package]] name = "buffered-reader" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b9b0a25eb06e83579bc985d836e1e3b957a7201301b48538764d2b2e78090d4" dependencies = [ "bzip2", "flate2", "lazy_static", "libc", ] [[package]] name = "bumpalo" version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "bzip2" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", ] [[package]] name = "bzip2-sys" version = "0.1.11+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" dependencies = [ "cc", "libc", "pkg-config", ] [[package]] name = "camellia" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" dependencies = [ "byteorder", "cipher", ] [[package]] name = "cast5" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" dependencies = [ "cipher", ] [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfb-mode" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" dependencies = [ "cipher", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-targets 0.48.5", ] [[package]] name = "cipher" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", "zeroize", ] [[package]] name = "clang-sys" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", ] [[package]] name = "clap_builder" version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", "terminal_size", ] [[package]] name = "clap_complete" version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb0d4825b75ff281318c393e8e1b80c4da9fb75a6b1d98547d389d6fe1f48d2" dependencies = [ "clap", ] [[package]] name = "clap_derive" version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "clap_lex" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clap_mangen" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a7c2b01e5e779c19f46a94bbd398f33ae63b0f78c07108351fb4536845bb7fd" dependencies = [ "clap", "roff", ] [[package]] name = "cmac" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" dependencies = [ "cipher", "dbl", "digest", ] [[package]] name = "colorchoice" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "core-foundation" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "core-foundation-sys" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", "crossbeam-queue", "crossbeam-utils", ] [[package]] name = "crossbeam-channel" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-queue" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", "rand_core", "subtle", "zeroize", ] [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", "rand_core", "typenum", ] [[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ "cipher", ] [[package]] name = "curve25519-dalek" version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", "platforms", "rustc_version", "subtle", "zeroize", ] [[package]] name = "curve25519-dalek-derive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "cvt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ae9bf77fbf2d39ef573205d554d87e86c12f1994e9ea335b0651b9b278bcf1" dependencies = [ "cfg-if", ] [[package]] name = "data-encoding" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "dbl" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" dependencies = [ "generic-array", ] [[package]] name = "der" version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" dependencies = [ "const-oid", "pem-rfc7468", "zeroize", ] [[package]] name = "deranged" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] [[package]] name = "des" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" dependencies = [ "cipher", ] [[package]] name = "deunicode" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a" [[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "difflib" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "const-oid", "crypto-common", "subtle", ] [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-next" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ "cfg-if", "dirs-sys-next", ] [[package]] name = "dirs-sys" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", "redox_users", "windows-sys 0.48.0", ] [[package]] name = "dirs-sys-next" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", "winapi", ] [[package]] name = "doc-comment" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dot-writer" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d1b11bd5e7e98406c6ff39fbc94d6e910a489b978ce7f17c19fce91a1195b7a" [[package]] name = "dsa" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d88afbb2443ba68ef8593de497e830b2e276434e1408f85cd760b1107b44ead0" dependencies = [ "digest", "num-bigint-dig", "num-traits", "pkcs8", "rfc6979", "sha2", "signature", "zeroize", ] [[package]] name = "dyn-clone" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "eax" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9954fabd903b82b9d7a68f65f97dc96dd9ad368e40ccc907a7c19d53e6bfac28" dependencies = [ "aead", "cipher", "cmac", "ctr", "subtle", ] [[package]] name = "ecb" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a8bfa975b1aec2145850fcaa1c6fe269a16578c44705a532ae3edc92b8881c7" dependencies = [ "cipher", ] [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest", "elliptic-curve", "rfc6979", "signature", "spki", ] [[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", "signature", ] [[package]] name = "ed25519-dalek" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" dependencies = [ "curve25519-dalek", "ed25519", "rand_core", "serde", "sha2", "subtle", "zeroize", ] [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ "base16ct", "crypto-bigint", "digest", "ff", "generic-array", "group", "hkdf", "pem-rfc7468", "pkcs8", "rand_core", "sec1", "subtle", "zeroize", ] [[package]] name = "ena" version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" dependencies = [ "log", ] [[package]] name = "encoding_rs" version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] [[package]] name = "endian-type" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enum-as-inner" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ "heck", "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "enumber" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa35b49b30d8f4219e279f22c4b7c899aa7f98f475da4eff84b75f17ba11ed19" dependencies = [ "quote", "syn 1.0.109", ] [[package]] name = "env_logger" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", "log", "regex", "termcolor", ] [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] name = "fallible-iterator" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fallible-streaming-iterator" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fd-lock" version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e5768da2206272c81ef0b5e951a41862938a6070da63bcea197899942d3b947" dependencies = [ "cfg-if", "rustix", "windows-sys 0.52.0", ] [[package]] name = "fehler" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5729fe49ba028cd550747b6e62cd3d841beccab5390aa398538c31a2d983635" dependencies = [ "fehler-macros", ] [[package]] name = "fehler-macros" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccb5acb1045ebbfa222e2c50679e392a71dd77030b78fb0189f2d9c5974400f9" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", ] [[package]] name = "ff" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core", "subtle", ] [[package]] name = "fiat-crypto" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" [[package]] name = "file_diff" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31a7a908b8f32538a2143e59a6e4e2508988832d5d4d6f7c156b3cbc762643a5" [[package]] name = "filetime" version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", "redox_syscall", "windows-sys 0.52.0", ] [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "float-cmp" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ "num-traits", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fs2" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" dependencies = [ "libc", "winapi", ] [[package]] name = "fs_at" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "982f82cc75107eef84f417ad6c53ae89bf65b561937ca4a3b3b0fd04d0aa2425" dependencies = [ "aligned", "cfg-if", "cvt", "libc", "nix", "windows-sys 0.48.0", ] [[package]] name = "futures-channel" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-io" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "futures-sink" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-macro", "futures-task", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "generator" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", "log", "rustversion", "windows", ] [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", "zeroize", ] [[package]] name = "getopts" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ "unicode-width", ] [[package]] name = "getrandom" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", "libc", "wasi", "wasm-bindgen", ] [[package]] name = "ghash" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" dependencies = [ "opaque-debug", "polyval", ] [[package]] name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git-testament" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "710c78d2b68e46e62f5ba63ba0a7a2986640f37f9ecc07903b9ad4e7b2dbfc8e" dependencies = [ "git-testament-derive", ] [[package]] name = "git-testament-derive" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b31494efbbe1a6730f6943759c21b92c8dc431cb4df177e6f2a6429c3c96842" dependencies = [ "log", "proc-macro2", "quote", "syn 2.0.48", "time", ] [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", "log", "regex-automata 0.4.3", "regex-syntax 0.8.2", ] [[package]] name = "globwalk" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" dependencies = [ "bitflags 1.3.2", "ignore", "walkdir", ] [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core", "subtle", ] [[package]] name = "h2" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", "http", "indexmap 2.1.0", "slab", "tokio", "tokio-util", "tracing", ] [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", ] [[package]] name = "hashlink" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ "hashbrown 0.14.3", ] [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hickory-client" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f3e08124cf0ddda93b1186d4af73599de401f3b52f14cd9aaa719049379462e" dependencies = [ "cfg-if", "data-encoding", "futures-channel", "futures-util", "hickory-proto", "once_cell", "radix_trie", "rand", "thiserror", "tokio", "tracing", ] [[package]] name = "hickory-proto" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "091a6fbccf4860009355e3efc52ff4acf37a63489aad7435372d44ceeb6fbbcf" dependencies = [ "async-trait", "cfg-if", "data-encoding", "enum-as-inner", "futures-channel", "futures-io", "futures-util", "idna 0.4.0", "ipnet", "once_cell", "openssl", "rand", "thiserror", "tinyvec", "tokio", "tracing", "url", ] [[package]] name = "hickory-resolver" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35b8f021164e6a984c9030023544c57789c51760065cd510572fedcfb04164e8" dependencies = [ "cfg-if", "futures-util", "hickory-proto", "ipconfig", "lru-cache", "once_cell", "parking_lot", "rand", "resolv-conf", "smallvec", "thiserror", "tokio", "tracing", ] [[package]] name = "hkdf" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] [[package]] name = "hmac" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ "digest", ] [[package]] name = "hostname" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", "winapi", ] [[package]] name = "html-escape" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" dependencies = [ "utf8-width", ] [[package]] name = "http" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", "itoa", ] [[package]] name = "http-body" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", "pin-project-lite", ] [[package]] name = "httparse" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humansize" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" dependencies = [ "libm", ] [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", "want", ] [[package]] name = "hyper-tls" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", "hyper", "native-tls", "tokio", "tokio-native-tls", ] [[package]] name = "iana-time-zone" version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "idea" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" dependencies = [ "cipher", ] [[package]] name = "idna" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] name = "idna" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] name = "ignore" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", "log", "memchr", "regex-automata 0.4.3", "same-file", "walkdir", "winapi-util", ] [[package]] name = "indexmap" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", ] [[package]] name = "indexmap" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.3", ] [[package]] name = "inout" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ "block-padding", "generic-array", ] [[package]] name = "ipconfig" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ "socket2", "widestring", "windows-sys 0.48.0", "winreg", ] [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", "rustix", "windows-sys 0.52.0", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] [[package]] name = "lalrpop" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", "diff", "ena", "is-terminal", "itertools", "lalrpop-util", "petgraph", "regex", "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", "unicode-xid", ] [[package]] name = "lalrpop-util" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ "spin", ] [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.4.2", "libc", "redox_syscall", ] [[package]] name = "libsqlite3-sys" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" dependencies = [ "pkg-config", "vcpkg", ] [[package]] name = "line-col" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e69cdf6b85b5c8dce514f694089a2cf8b1a702f6cd28607bcb3cf296c9778db" [[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "loom" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" dependencies = [ "cfg-if", "generator", "scoped-tls", "serde", "serde_json", "tracing", "tracing-subscriber", ] [[package]] name = "lru-cache" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" dependencies = [ "linked-hash-map", ] [[package]] name = "match_cfg" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matchers" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ "regex-automata 0.1.10", ] [[package]] name = "md-5" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ "cfg-if", "digest", ] [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memsec" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa0916b001582d253822171bd23f4a0229d32b9507fae236f5da8cad515ba7c" [[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "mio" version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", "windows-sys 0.48.0", ] [[package]] name = "native-tls" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", "log", "openssl", "openssl-probe", "openssl-sys", "schannel", "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "nettle" version = "7.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9fdccf3eae7b161910d2daa2f0155ca35041322e8fe5c5f1f2c9d0b12356336" dependencies = [ "getrandom", "libc", "nettle-sys", "thiserror", "typenum", ] [[package]] name = "nettle-sys" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b495053a10a19a80e3a26bf1212e92e29350797b5f5bdc58268c3f3f818e66ec" dependencies = [ "bindgen", "cc", "libc", "pkg-config", "tempfile", "vcpkg", ] [[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "nibble_vec" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" dependencies = [ "smallvec", ] [[package]] name = "nix" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", ] [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] [[package]] name = "normalize-line-endings" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "normpath" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" dependencies = [ "windows-sys 0.48.0", ] [[package]] name = "nu-ansi-term" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", "winapi", ] [[package]] name = "num-bigint-dig" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" dependencies = [ "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", "rand", "smallvec", "zeroize", ] [[package]] name = "num-integer" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", ] [[package]] name = "num-iter" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", ] [[package]] name = "num_cpus" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] [[package]] name = "object" version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openpgp-cert-d" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2c3b55a1bd2b7b15b1d969fcde543bf6b679294f9efd3c2360459d49ae62ce" dependencies = [ "anyhow", "dirs", "fd-lock", "libc", "sha1collisiondetection", "tempfile", "thiserror", "walkdir", ] [[package]] name = "openssl" version = "0.10.62" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" dependencies = [ "bitflags 2.4.2", "cfg-if", "foreign-types", "libc", "once_cell", "openssl-macros", "openssl-sys", ] [[package]] name = "openssl-macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" version = "0.9.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" dependencies = [ "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "overload" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p256" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ "ecdsa", "elliptic-curve", "primeorder", "sha2", ] [[package]] name = "parking_lot" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets 0.48.5", ] [[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pem-rfc7468" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" dependencies = [ "pest", "pest_generator", ] [[package]] name = "pest_generator" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "pest_meta" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" dependencies = [ "once_cell", "pest", "sha2", ] [[package]] name = "petgraph" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", "indexmap 2.1.0", ] [[package]] name = "phf_shared" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ "siphasher", ] [[package]] name = "pikchr" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b430b470a0dfac4e22cd248210e3ef005346acd1ada670d74d6bdcdbab0dc96e" dependencies = [ "cc", "libc", ] [[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkcs1" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ "der", "pkcs8", "spki", ] [[package]] name = "pkcs8" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", "spki", ] [[package]] name = "pkg-config" version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "platforms" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "polyval" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" dependencies = [ "cfg-if", "cpufeatures", "opaque-debug", "universal-hash", ] [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" dependencies = [ "anstyle", "difflib", "float-cmp", "normalize-line-endings", "predicates-core", "regex", ] [[package]] name = "predicates-core" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] name = "predicates-tree" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" dependencies = [ "predicates-core", "termtree", ] [[package]] name = "primeorder" version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ "elliptic-curve", ] [[package]] name = "proc-macro2" version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "pulldown-cmark" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" dependencies = [ "bitflags 1.3.2", "getopts", "memchr", "unicase", ] [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "radix_trie" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" dependencies = [ "endian-type", "nibble_vec", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "rayon" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "redox_syscall" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", "libredox", "thiserror", ] [[package]] name = "regex" version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.3", "regex-syntax 0.8.2", ] [[package]] name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ "regex-syntax 0.6.29", ] [[package]] name = "regex-automata" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", "regex-syntax 0.8.2", ] [[package]] name = "regex-syntax" version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "regex-syntax" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "remove_dir_all" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23895cfadc1917fed9c6ed76a8c2903615fa3704f7493ff82b364c6540acc02b" dependencies = [ "aligned", "cfg-if", "cvt", "fs_at", "lazy_static", "libc", "normpath", "windows-sys 0.45.0", ] [[package]] name = "reqwest" version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", "http", "http-body", "hyper", "hyper-tls", "ipnet", "js-sys", "log", "mime", "native-tls", "once_cell", "percent-encoding", "pin-project-lite", "serde", "serde_json", "serde_urlencoded", "system-configuration", "tokio", "tokio-native-tls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", "winreg", ] [[package]] name = "resolv-conf" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ "hostname", "quick-error", ] [[package]] name = "rfc6979" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ "hmac", "subtle", ] [[package]] name = "ripemd" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ "digest", ] [[package]] name = "roadmap" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a129e44a647b309ed394a092e21eabcb58537802c6912920ef4ea76239421234" dependencies = [ "anyhow", "serde", "serde_yaml 0.8.26", "textwrap", "thiserror", ] [[package]] name = "roff" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rpassword" version = "7.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" dependencies = [ "libc", "rtoolbox", "windows-sys 0.48.0", ] [[package]] name = "rsa" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" dependencies = [ "const-oid", "digest", "num-bigint-dig", "num-integer", "num-traits", "pkcs1", "pkcs8", "rand_core", "signature", "spki", "subtle", "zeroize", ] [[package]] name = "rtoolbox" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" dependencies = [ "libc", "windows-sys 0.48.0", ] [[package]] name = "rusqlite" version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d" dependencies = [ "bitflags 2.4.2", "fallible-iterator", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", "smallvec", ] [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] [[package]] name = "rustix" version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] [[package]] name = "rustversion" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "schannel" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "scoped-tls" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", "generic-array", "pkcs8", "subtle", "zeroize", ] [[package]] name = "security-framework" version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "semver" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "sequoia-autocrypt" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e24fc0ec87c156a35f24fc153ab694e0f37cd6fa87c1cf5005c9f4fa5e10415b" dependencies = [ "base64", "sequoia-openpgp", ] [[package]] name = "sequoia-cert-store" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f44e2775a51e844809b1f393c5098dd414f79555b61b29a98f0dede289b86515" dependencies = [ "anyhow", "crossbeam", "dirs", "num_cpus", "openpgp-cert-d", "rayon", "rusqlite", "sequoia-net", "sequoia-openpgp", "smallvec", "thiserror", "tokio", ] [[package]] name = "sequoia-net" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6abf810ba698339f332b946b485cc815c13a0f750189009bc10514c71fba814b" dependencies = [ "anyhow", "base64", "futures-util", "hickory-client", "hickory-resolver", "http", "hyper", "hyper-tls", "libc", "percent-encoding", "reqwest", "sequoia-openpgp", "tempfile", "thiserror", "tokio", "url", "z-base-32", ] [[package]] name = "sequoia-openpgp" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ea026cf8a70d331c742e3ad7e68fd405d0743ff86630fb4334a1bf8d0e194c7" dependencies = [ "aes", "aes-gcm", "anyhow", "base64", "block-padding", "blowfish", "botan", "buffered-reader", "bzip2", "camellia", "cast5", "cfb-mode", "chrono", "cipher", "des", "digest", "dsa", "dyn-clone", "eax", "ecb", "ecdsa", "ed25519", "ed25519-dalek", "flate2", "getrandom", "idea", "idna 0.4.0", "lalrpop", "lalrpop-util", "lazy_static", "libc", "md-5", "memsec", "nettle", "num-bigint-dig", "once_cell", "openssl", "openssl-sys", "p256", "rand", "rand_core", "regex", "regex-syntax 0.8.2", "ripemd", "rsa", "sha1collisiondetection", "sha2", "thiserror", "twofish", "typenum", "win-crypto-ng", "winapi", "x25519-dalek", "xxhash-rust", ] [[package]] name = "sequoia-policy-config" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "757d45d308f2bd9c0d6fdd640f320998ad24856bdf2890ddd28d3c3b85808274" dependencies = [ "anyhow", "chrono", "sequoia-openpgp", "serde", "thiserror", "toml", ] [[package]] name = "sequoia-sq" version = "0.33.0" dependencies = [ "anyhow", "assert_cmd", "buffered-reader", "cfg-if", "chrono", "clap", "clap_complete", "dirs", "dot-writer", "fehler", "humantime", "itertools", "libc", "predicates", "roff", "rpassword", "sequoia-autocrypt", "sequoia-cert-store", "sequoia-net", "sequoia-openpgp", "sequoia-policy-config", "sequoia-wot", "serde", "serde_json", "subplot-build", "subplotlib", "tempfile", "termcolor", "terminal_size", "textwrap", "tokio", ] [[package]] name = "sequoia-wot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "383672b024f126625127ec2b709b1e2f8d4814ab1bf4f800abb1a9fdc8dedcd3" dependencies = [ "anyhow", "chrono", "clap", "clap_complete", "clap_mangen", "crossbeam", "dot-writer", "enumber", "num_cpus", "sequoia-cert-store", "sequoia-openpgp", "sequoia-policy-config", "thiserror", ] [[package]] name = "serde" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde-aux" version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a86348501c129f3ad50c2f4635a01971f76974cd8a3f335988a0f1581c082765" dependencies = [ "serde", "serde_json", ] [[package]] name = "serde_derive" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "serde_json" version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "serde_urlencoded" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", "ryu", "serde", ] [[package]] name = "serde_yaml" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap 1.9.3", "ryu", "serde", "yaml-rust", ] [[package]] name = "serde_yaml" version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" dependencies = [ "indexmap 2.1.0", "itoa", "ryu", "serde", "unsafe-libyaml", ] [[package]] name = "sha1collisiondetection" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31c0b86a052106b16741199985c9ec2bf501f619f70c48fa479b44b093ad9a68" dependencies = [ "const-oid", "digest", "generic-array", ] [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sharded-slab" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "shell-words" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "signature" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core", ] [[package]] name = "siphasher" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "slug" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" dependencies = [ "deunicode", "wasm-bindgen", ] [[package]] name = "smallvec" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b187f0231d56fe41bfb12034819dd2bf336422a5866de41bc3fec4b2e3883e8" [[package]] name = "smawk" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", ] [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "state" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b" dependencies = [ "loom", ] [[package]] name = "string_cache" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", "parking_lot", "phf_shared", "precomputed-hash", ] [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subplot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2c5723f41235a3deefab3cfd6164a5b780802f596fa97eb40dfcf3c39c36b21" dependencies = [ "anyhow", "base64", "clap", "env_logger", "file_diff", "git-testament", "html-escape", "lazy_static", "line-col", "log", "pikchr", "pulldown-cmark", "regex", "roadmap", "serde", "serde-aux", "serde_json", "serde_yaml 0.9.30", "tempfile", "tempfile-fast", "tera", "thiserror", "time", "walkdir", ] [[package]] name = "subplot-build" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd58ff7123e83e5a5ed5bcdcd9f6f23226eea5b08bc310e129cad5d24b18fabe" dependencies = [ "subplot", "tempfile", "tracing", ] [[package]] name = "subplotlib" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fc3c17998cc92ec00493a7d1c0d0256f8977c7baed553777ba347dd6d1c3ccf" dependencies = [ "base64", "fehler", "filetime", "fs2", "glob", "lazy_static", "regex", "remove_dir_all", "shell-words", "state", "subplot-build", "subplotlib-derive", "tempfile", "time", "unescape", ] [[package]] name = "subplotlib-derive" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0234a041a912954e3cc81230b9f64f6a471c4297e65053e6ad733bb3e473bc60" dependencies = [ "fehler", "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "subtle" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "system-configuration" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", ] [[package]] name = "tempfile" version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", "windows-sys 0.52.0", ] [[package]] name = "tempfile-fast" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a74be8531b1a9d607004a32b8f50dd8093b09ec6b0a6af004e33051068e87af6" dependencies = [ "libc", "rand", "tempfile", ] [[package]] name = "tera" version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8" dependencies = [ "globwalk", "humansize", "lazy_static", "percent-encoding", "pest", "pest_derive", "rand", "regex", "serde", "serde_json", "slug", "unic-segment", ] [[package]] name = "term" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", "winapi", ] [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", "windows-sys 0.48.0", ] [[package]] name = "termtree" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "textwrap" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" dependencies = [ "smawk", "unicode-linebreak", "unicode-width", ] [[package]] name = "thiserror" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "thread_local" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ "cfg-if", "once_cell", ] [[package]] name = "time" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", "powerfmt", "serde", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] [[package]] name = "tiny-keccak" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" dependencies = [ "crunchy", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", "socket2", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "tokio-native-tls" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", ] [[package]] name = "tokio-util" version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", "tracing", ] [[package]] name = "toml" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] [[package]] name = "tower-service" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", ] [[package]] name = "tracing-log" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ "log", "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", "once_cell", "regex", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", ] [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twofish" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" dependencies = [ "cipher", ] [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unescape" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" [[package]] name = "unic-char-property" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" dependencies = [ "unic-char-range", ] [[package]] name = "unic-char-range" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" [[package]] name = "unic-common" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" [[package]] name = "unic-segment" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" dependencies = [ "unic-ucd-segment", ] [[package]] name = "unic-ucd-segment" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" dependencies = [ "unic-char-property", "unic-char-range", "unic-ucd-version", ] [[package]] name = "unic-ucd-version" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" dependencies = [ "unic-common", ] [[package]] name = "unicase" version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-linebreak" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "universal-hash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", "subtle", ] [[package]] name = "unsafe-libyaml" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "url" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna 0.5.0", "percent-encoding", ] [[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] name = "utf8parse" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wait-timeout" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ "libc", ] [[package]] name = "walkdir" version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ "try-lock", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "web-sys" version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "widestring" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "win-crypto-ng" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99abfb435a71e54ab2971d8d8c32f1a7e006cdbf527f71743b1d45b93517bb92" dependencies = [ "cipher", "doc-comment", "rand_core", "winapi", "zeroize", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets 0.52.0", ] [[package]] name = "windows-sys" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ "windows-targets 0.42.2", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.0", ] [[package]] name = "windows-targets" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ "windows_aarch64_gnullvm 0.42.2", "windows_aarch64_msvc 0.42.2", "windows_i686_gnu 0.42.2", "windows_i686_msvc 0.42.2", "windows_x86_64_gnu 0.42.2", "windows_x86_64_gnullvm 0.42.2", "windows_x86_64_msvc 0.42.2", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm 0.52.0", "windows_aarch64_msvc 0.52.0", "windows_i686_gnu 0.52.0", "windows_i686_msvc 0.52.0", "windows_x86_64_gnu 0.52.0", "windows_x86_64_gnullvm 0.52.0", "windows_x86_64_msvc 0.52.0", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winreg" version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "x25519-dalek" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" dependencies = [ "curve25519-dalek", "rand_core", "zeroize", ] [[package]] name = "xxhash-rust" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53be06678ed9e83edb1745eb72efc0bbcd7b5c3c35711a860906aed827a13d61" [[package]] name = "yaml-rust" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] [[package]] name = "z-base-32" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a0d98613370af88e15bd2047702d7c78c8c6aba44403eb227c8ad706871f92" [[package]] name = "zerocopy" version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] [[package]] name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", "syn 2.0.48", ] sequoia-sq-0.33.0/Cargo.toml0000644000000104750000000000100112130ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.70" name = "sequoia-sq" version = "0.33.0" authors = [ "Azul ", "Heiko Schaefer ", "Igor Matuszewski ", "Justus Winter ", "Kai Michaelis ", "Lars Wirzenius ", "Neal H. Walfield ", "Nora Widdecke ", "Wiktor Kwapisiewicz ", ] build = "build.rs" description = "Command-line frontends for Sequoia" homepage = "https://sequoia-pgp.org/" documentation = "https://docs.rs/sequoia-sq" readme = "README.md" keywords = [ "cryptography", "openpgp", "pgp", "encryption", "signing", ] categories = [ "cryptography", "authentication", "command-line-utilities", ] license = "LGPL-2.0-or-later" repository = "https://gitlab.com/sequoia-pgp/sequoia-sq" [profile.release] debug = 2 [[bin]] name = "sq" path = "src/sq.rs" bench = false [dependencies.anyhow] version = "1.0.18" [dependencies.buffered-reader] version = "1.0.0" features = ["compression-deflate"] default-features = false [dependencies.chrono] version = "0.4.10" [dependencies.clap] version = "4" features = [ "derive", "env", "string", "wrap_help", ] [dependencies.dirs] version = "5" [dependencies.dot-writer] version = "0.1.3" optional = true [dependencies.humantime] version = "2" [dependencies.itertools] version = ">=0.10, <0.13" [dependencies.rpassword] version = "7.0" [dependencies.sequoia-autocrypt] version = "0.25" default-features = false [dependencies.sequoia-cert-store] version = "0.4" [dependencies.sequoia-net] version = "0.28" default-features = false [dependencies.sequoia-openpgp] version = "1.17" features = ["compression-deflate"] default-features = false [dependencies.sequoia-policy-config] version = "0.6" [dependencies.sequoia-wot] version = "0.9" [dependencies.serde] version = "1.0.137" features = ["derive"] [dependencies.serde_json] version = "1.0.80" [dependencies.tempfile] version = "3.1" [dependencies.termcolor] version = "1.2.0" [dependencies.terminal_size] version = ">=0.2.6, <0.4" [dependencies.textwrap] version = ">=0.15, <0.17" [dependencies.tokio] version = "1.13.1" [dev-dependencies.assert_cmd] version = "2" [dev-dependencies.fehler] version = "1.0.0" [dev-dependencies.libc] version = "0.2" [dev-dependencies.predicates] version = ">=2, <4" [dev-dependencies.subplotlib] version = ">=0.7, <0.10" [build-dependencies.anyhow] version = "1.0.18" [build-dependencies.buffered-reader] version = "1.0.0" features = ["compression-deflate"] default-features = false [build-dependencies.cfg-if] version = "1" [build-dependencies.chrono] version = "0.4.10" [build-dependencies.clap] version = "4" features = [ "derive", "env", "string", "wrap_help", ] [build-dependencies.clap_complete] version = "4" [build-dependencies.roff] version = "0.2.1" [build-dependencies.sequoia-net] version = "0.28" default-features = false [build-dependencies.sequoia-openpgp] version = "1.17" default-features = false [build-dependencies.serde] version = "1.0.137" features = ["derive"] [build-dependencies.subplot-build] version = ">=0.7, <0.10" optional = true [build-dependencies.terminal_size] version = ">=0.2.6, <0.4" [features] compression-bzip2 = ["sequoia-openpgp/compression-bzip2"] crypto-botan = ["sequoia-openpgp/crypto-botan"] crypto-botan2 = ["sequoia-openpgp/crypto-botan2"] crypto-cng = ["sequoia-openpgp/crypto-cng"] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] crypto-openssl = ["sequoia-openpgp/crypto-openssl"] crypto-rust = ["sequoia-openpgp/crypto-rust"] default = [ "crypto-nettle", "compression-bzip2", "dot-writer", ] subplot = ["subplot-build"] [badges.gitlab] repository = "sequoia-pgp/sequoia-sq" [badges.maintenance] status = "actively-developed" sequoia-sq-0.33.0/Cargo.toml.orig000064400000000000000000000060551046102023000146730ustar 00000000000000[package] name = "sequoia-sq" description = "Command-line frontends for Sequoia" version = "0.33.0" authors = [ "Azul ", "Heiko Schaefer ", "Igor Matuszewski ", "Justus Winter ", "Kai Michaelis ", "Lars Wirzenius ", "Neal H. Walfield ", "Nora Widdecke ", "Wiktor Kwapisiewicz ", ] build = "build.rs" documentation = "https://docs.rs/sequoia-sq" homepage = "https://sequoia-pgp.org/" repository = "https://gitlab.com/sequoia-pgp/sequoia-sq" readme = "README.md" keywords = ["cryptography", "openpgp", "pgp", "encryption", "signing"] categories = ["cryptography", "authentication", "command-line-utilities"] license = "LGPL-2.0-or-later" edition = "2021" rust-version = "1.70" [badges] gitlab = { repository = "sequoia-pgp/sequoia-sq" } maintenance = { status = "actively-developed" } [dependencies] buffered-reader = { version = "1.0.0", default-features = false, features = ["compression-deflate"] } dirs = "5" dot-writer = { version = "0.1.3", optional = true } sequoia-openpgp = { version = "1.17", default-features = false, features = ["compression-deflate"] } sequoia-autocrypt = { version = "0.25", default-features = false } sequoia-net = { version = "0.28", default-features = false } sequoia-policy-config = "0.6" anyhow = "1.0.18" chrono = "0.4.10" clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } humantime = "2" itertools = ">=0.10, <0.13" sequoia-cert-store = "0.4" sequoia-wot = "0.9" tempfile = "3.1" tokio = { version = "1.13.1" } rpassword = "7.0" serde_json = "1.0.80" serde = { version = "1.0.137", features = ["derive"] } terminal_size = ">=0.2.6, <0.4" termcolor = "1.2.0" textwrap = ">=0.15, <0.17" [build-dependencies] anyhow = "1.0.18" buffered-reader = { version = "1.0.0", default-features = false, features = ["compression-deflate"] } clap = { version = "4", features = ["derive", "env", "string", "wrap_help"] } clap_complete = "4" chrono = "0.4.10" roff = "0.2.1" serde = { version = "1.0.137", features = ["derive"] } sequoia-openpgp = { version = "1.17", default-features = false } sequoia-net = { version = "0.28", default-features = false } subplot-build = { version = ">=0.7, <0.10", optional = true } cfg-if = "1" terminal_size = ">=0.2.6, <0.4" [dev-dependencies] subplotlib = ">=0.7, <0.10" fehler = "1.0.0" assert_cmd = "2" predicates = ">=2, <4" libc = "0.2" [[bin]] name = "sq" path = "src/sq.rs" bench = false [features] default = [ "crypto-nettle", "compression-bzip2", "dot-writer", ] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] crypto-openssl = ["sequoia-openpgp/crypto-openssl"] crypto-botan = ["sequoia-openpgp/crypto-botan"] crypto-botan2 = ["sequoia-openpgp/crypto-botan2"] crypto-cng = ["sequoia-openpgp/crypto-cng"] crypto-rust = ["sequoia-openpgp/crypto-rust"] compression-bzip2 = ["sequoia-openpgp/compression-bzip2"] subplot = ["subplot-build"] [profile.release] debug = true sequoia-sq-0.33.0/Dockerfile000064400000000000000000000034671046102023000140020ustar 00000000000000# See https://gitlab.com/sequoia-pgp/sequoia/-/blob/main/README.md#debian # for system requirements FROM debian:bookworm AS build # create a sandbox user for the build (in ~builder) and install (in /opt) # give it permissions to the build dir and home # upgrade everything # add dependencies, as specified by the Sequoia README.md file RUN groupadd builder && \ useradd --no-log-init --create-home --gid builder builder && \ apt-get update && \ apt-get upgrade --assume-yes && \ apt-get install --assume-yes --no-install-recommends \ ca-certificates \ capnproto \ cargo \ git \ libclang-dev \ libsqlite3-dev \ libssl-dev \ make \ nettle-dev \ pkg-config \ rustc \ && \ apt-get clean && \ chown builder /opt COPY --chown=builder:builder . /home/builder/sequoia # switch to the sandbox user USER builder # retry build because cargo sometimes segfaults during download (#918854) # # the `build-release` target is used instead of the default because # `install` calls it after anyways RUN cd /home/builder/sequoia && \ CARGO_TARGET_DIR=target cargo build -p sequoia-sq --release && \ install --strip -D --target-directory /opt/usr/local/bin \ target/release/sq FROM debian:bookworm-slim AS sq-base RUN groupadd user && \ useradd --no-log-init -g user user && \ mkdir /home/user && \ chown -R user:user /home/user && \ apt-get update && \ apt-get upgrade --assume-yes && \ apt-get install --assume-yes ca-certificates libssl3 libsqlite3-0 && \ apt-get clean && \ rm -fr -- /var/lib/apt/lists/* /var/cache/* FROM sq-base AS sq COPY --from=build /opt/usr/local/bin/sq /usr/local/bin/sq COPY --from=build /etc/ssl/certs /etc/ssl/certs ENTRYPOINT ["/usr/local/bin/sq"] sequoia-sq-0.33.0/LICENSE.txt000064400000000000000000000627421046102023000136340ustar 00000000000000Sequoia PGP sq is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Sequoia PGP sq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --- GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! sequoia-sq-0.33.0/NEWS000064400000000000000000000236671046102023000125130ustar 00000000000000 -*- org -*- #+TITLE: sequoia-sq NEWS – history of user-visible changes #+STARTUP: content hidestars * Changes in 0.33.0 ** Notable changes - The command line interface has been restructured. Please consult the manual pages and review any code and documents using the interface. Notably: - `sq import` and `sq export` have been moved to `sq cert`. - `sq wot` has been renamed to `sq pki`. - `sq link` and `sq certify` have been moved to `sq pki`. - `sq lookup, `sq keyserver`, `sq wkd`, and `sq dane` have been moved to `sq network`. - All commands retrieving certificates from network services are now called `fetch`, e.g. `sq network fetch` and `sq network dane fetch`. The command for publishing certs on key servers is now called `sq network keyserver publish`. - `sq armor`, `sq dearmor`, and `sq packet` have been moved to `sq toolbox`. - `sq --version` is now `sq version`, and `sq output-versions` has been integrated with that command. - The manual page generation has been improved, and manual pages and shell completions are generated during the build process. To write the assets to a predictable location, set the environment variable `ASSET_OUT_DIR` to a suitable location. * Changes in 0.32.0 ** New functionality - Support for password-encrypted keys has been improved. For example, a newly generated subkey can be password protected. - When encrypting a message with a password, or creating a new password-protected key or subkey, or changing passwords on a key, sq now prompts you to repeat the password to catch typos. - Literal data metadata can now be set using `--set-metadata-filename` and `--set-metadata-time`. - sq now reads the file /etc/crypto-policies/back-ends/sequoia.config to configure its cryptographic policy. The file to load can be overridden using the SEQUOIA_CRYPTO_POLICY environment variable. For more information on the format, see: https://docs.rs/sequoia-policy-config/latest/sequoia_policy_config/#format - New subcommand: `sq dane generate`. Generates DANE records for the given domain and certificates. DANE is a way to distribute OpenPGP certificates via DNS. https://www.rfc-editor.org/rfc/rfc7929.html - When querying network resources via `sq keyserver get`, `sq wkd get`, or `sq dane get`, multiple queries can be given that are executed simultaneously. - When querying key servers via `sq keyserver get` or `sq keyserver send`, multiple servers are queried simultaneously. - There are now four default keyservers: - hkps://keys.openpgp.org - hkps://mail-api.proton.me - hkps://keys.mailvelope.com - hkps://keyserver.ubuntu.com - New subcommand: `sq lookup`. Searches for certificates using all supported network services. ** Notable changes - Padding has been disabled to increase compatibility with other implementations. The padding method we previously used relies on a compressed data packet to pad the message. However, some implementations do not gracefully process these padded encryption containers, so until we get proper padding support from the next revision of OpenPGP, we disable padding. - Message notarization has been disabled. Message notarization and their semantics are not well defined, and there is no consensus on how to do that. - When doing a userid, subkey, or third-party certificate revocation, with the cert given to --certificate-file containing secret key material, we previously emitted a revocation certificate containing secret key material. This has been fixed, and tests have been added to ensure secret key material is only emitted where we expect it to be. * Changes in 0.31.0 ** New functionality - `sq key subkey add` allows to create and add a new subkey to an existing certificate. - The functionality of `sq-keyring-linter` is now available as `sq keyring lint`. - The new subcommands `sq key revoke`, `sq key subkey revoke` and `sq key userid revoke`, allow writing to a file using the `--output` option. ** Notable changes - The `--keyring` option is now global and can be specified anywhere when calling `sq`. ** Deprecated functionality - The `--expires` and `--expires-in` options used in various subcommands are deprecated in favor of the unifying `--expiry`. - `sq key generate --export FILE` is deprecated in favor of the more generic `sq key generate --output FILE`. - The `sq revoke certificate` command has been renamed to `sq key revoke`. - The `sq revoke subkey` command has been renamed to `sq key subkey revoke`. - The `sq revoke userid` command has been renamed to `sq key userid revoke`. * Changes in 0.30.1 ** Notable changes - The `crypto-botan` feature now selects Botan's v3 interface. Use the new `crypto-botan2` feature to continue using Botan's v2 interface. ** Notable fixes - Several parser bugs were fixed in sequoia-openpgp 1.16.0 and buffered-reader 1.2.0. These are all low-severity as Rust correctly detects the out of bounds access and panics. Update Cargo.lock to make sure we use these versions. * Changes in 0.30 ** New functionality - `sq key adopt` now honors `--time`. - Add `sq key adopt --expire` to allow setting an adopted key's expiration time. - Add support for using pEp's certificate store. A pEp certificate store can be used by specifying `sq --pep-cert-store PATH` or setting the environment variable `PEP_CERT_STORE`. * Changes in 0.29 ** New functionality - `sq` now supports and implicitly uses a certificate store. By default, `sq` uses the standard OpenPGP certificate directory. This is located at `$HOME/.local/share/pgp.cert.d` on XDG compliant systems. - `sq --no-cert-store`: A new switch to disable the use of the certificate store. - `sq --cert-store`: A new option to use an alternate certificate store. Currently, only OpenPGP certificate directories are supported. - `sq import`: A new command to import certificates into the certificate store. - `sq export`: A new command to export certificates from the certificate store. - `sq encrypt --recipient-cert`: A new option to specify a recipient's certificate by fingerprint or key ID, which is then looked up in the certificate store. - `sq verify --signer-cert`: A new option to specify a signer's certificate by fingerprint or key ID, which is then looked up in the certificate store. - `sq verify` now also implicitly looks for missing certificates in the certificate store. But, unless they are explicitly named using `--signer-cert`, they are not considered authenticated and the verification will always fail. - `sq certify`: If the certificate to certify is a fingerprint or Key ID, then the corresponding certificate is looked up in the certificate store. - Add a global option, `--time`, to set the reference time. This option replaces the various subcommand's `--time` argument as well as `sq key generate` and `sq key userid add`'s `--creation-time` arguments. - Add top-level option, `--trust-root`, to allow the user to specify trust roots. - Extend `sq encrypt` to allow addressing recipients by User ID (`--recipient-userid`) or email address (`--recipient-email`). Only User IDs that can be fully authenticated are considered. - Extend `sq verify` to verify certificates looked up from the certificate store using the web of trust. If the signature includes a Signer's User ID packet, and the binding can be fully authenticated, consider the signature to be authenticated. If there is no Signer's User ID packet, consider the signature to be authenticated if any binding can fully be authenticated. - Add `sq link add`, which uses the local trust root to certify the specified bindings. - Add `sq link retract`, which retracts certifications made by the local trust root on the specified bindings. - Add `sq link list`, which lists the links. - Add a top-level option, `--keyring`, to allow the user to specify additional keyrings to search for certificates. - Import web of trust subcommands from sq-wot. Specifically, add: - `sq wot authenticate` to authenticate a binding. - `sq wot lookup` to find a certificate with a particular User ID. - `sq wot identify` to list authenticated bindings for a certificate. - `sq wot list` to list authenticated bindings. - `sq wot path` to authenticate and lint a path in a web of trust. - `sq keyserver get`, `sq wkd get`, and `sq dane get` now import any certificates into the certificate store by default instead of exporting them on stdout. It is still possible to export them using the `--output` option. - When `sq keyserver get` (for verifying key servers), `sq wkd get`, or `sq dane get` saves a certificate to the local certificate store, `sq` certifies the validated User IDs (all returned User IDs in the case of verifying key servers; User IDs that contain the looked up email address in the case of WKD and DANE) using a local service-specific proxy CA. If the proxy key doesn't exist, it is created, and certified as a minimally trusted CA (trust amount 1 of 120) by the local trust root. The proxy certificates can be managed in the usual way using `sq link add` and `sq link retract`. - Extend `sq inspect` to inspect certificates from the certificate store using the `--cert` option. ** Deprecated functionality - `sq key generate --creation-time TIME` is deprecated in favor of `sq key generate --time TIME`. - `sq key user id --creation-time TIME` is deprecated in favor of `sq user id --time TIME`. * Started the NEWS file. sequoia-sq-0.33.0/README.md000064400000000000000000000032501046102023000132550ustar 00000000000000# sq, the Sequoia-PGP command line tool [Sequoia-PGP][] is an implementation of OpenPGP in Rust. It includes a suite of library crates, which are meant to be used from applications. This crate provides the `sq` command line application. `sq` is aimed at command line users as a way to use OpenPGP conveniently from the command line. See the [sq user guide][] for instructions. The program also has built-in help, using the `--help` option and `help` subcommand: ~~~sh $ sq help ... ~~~ You can also browse the [manual pages][], look at our [acceptance criteria][], and browse the [rustdoc output][] if you want to learn about the implementation. [Sequoia-PGP]: https://sequoia-pgp.org/ [sq user guide]: https://sequoia-pgp.gitlab.io/sq-user-guide/ [manual pages]: https://sequoia-pgp.gitlab.io/sequoia-sq/man/ [acceptance criteria]: https://sequoia-pgp.gitlab.io/sequoia-sq/subplot/ [rustdoc output]: https://sequoia-pgp.gitlab.io/sequoia-sq/impl/ ## Installing The `sq` tool can be installed using cargo: ```sh cargo install sequoia-sq ``` Please see [sequoia-openpgp's README] for how to install build dependencies on your system. [sequoia-openpgp's README]: https://gitlab.com/sequoia-pgp/sequoia#requirements-and-msrv ## Building from source This crate can be built from a source checkout using the standard `cargo` toolchain: ```sh cargo build ``` The above creates the `sq` executable, the manual pages, and its shell completions. By default, the manual pages and shell completions are put into the `cargo` target directory, but the exact location is unpredictable. To write the assets to a predictable location, set the environment variable `ASSET_OUT_DIR` to a suitable location. sequoia-sq-0.33.0/build.rs000064400000000000000000000037171046102023000134530ustar 00000000000000use std::env; use std::fs; use std::path::PathBuf; use clap::ValueEnum; use clap_complete::Shell; use anyhow::Result; pub mod cli { #![allow(unused_macros)] include!("src/macros.rs"); include!("src/cli/mod.rs"); } pub mod man { include!("src/man.rs"); } fn main() { println!("cargo:rerun-if-changed=build.rs"); // Generate subplot tests. #[cfg(feature = "subplot")] subplot_build::codegen("sq.subplot") .expect("failed to generate code with Subplot"); let mut sq = cli::build(); generate_shell_completions(&mut sq).unwrap(); generate_man_pages(&sq).unwrap(); } /// Variable name to control the asset out directory with. const ASSET_OUT_DIR: &str = "ASSET_OUT_DIR"; /// Returns the directory to write the given assets to. fn asset_out_dir(asset: &str) -> Result { println!("cargo:rerun-if-env-changed={}", ASSET_OUT_DIR); let outdir: PathBuf = env::var_os(ASSET_OUT_DIR).unwrap_or_else( || env::var_os("OUT_DIR").expect("OUT_DIR not set")).into(); if outdir.exists() && ! outdir.is_dir() { return Err( anyhow::anyhow!("{}={:?} is not a directory", ASSET_OUT_DIR, outdir)); } let path = outdir.join(asset); fs::create_dir_all(&path)?; Ok(path) } /// Generates shell completions. fn generate_shell_completions(sq: &mut clap::Command) -> Result<()> { let path = asset_out_dir("shell-completions")?; for shell in Shell::value_variants() { clap_complete::generate_to(*shell, sq, "sq", &path)?; }; println!("cargo:warning=shell completions written to {}", path.display()); Ok(()) } /// Generates man pages. fn generate_man_pages(sq: &clap::Command) -> Result<()> { let path = asset_out_dir("man-pages")?; for man in man::manpages(sq) { std::fs::write(path.join(man.filename()), man.troff_source())?; } println!("cargo:warning=man pages written to {}", path.display()); Ok(()) } sequoia-sq-0.33.0/deny.toml000064400000000000000000000013441046102023000136340ustar 00000000000000[advisories] ignore = [ "RUSTSEC-2020-0071", # chrono not affected by time 0.1 issue # fehler is unmaintained. # # fehler is used by subplot and thus an indirect dependency. Remove # when a new version subplot is released without fehler. See # https://gitlab.com/subplot/subplot/-/issues/340. "RUSTSEC-2023-0067", ] unmaintained = "deny" yanked = "deny" [bans] multiple-versions = "allow" deny = [ # does not have responsible disclosure policy: # https://github.com/briansmith/ring#bug-reporting {name = "ring"}, ] [licenses] allow = [ "Apache-2.0", "BSD-3-Clause", "BSL-1.0", "CC0-1.0", "GPL-2.0", "GPL-3.0", "ISC", "LGPL-2.0", "LGPL-3.0", "MIT", "MIT-0", "MPL-2.0", "Unicode-DFS-2016", ] sequoia-sq-0.33.0/sq-subplot.md000064400000000000000000001611501046102023000144350ustar 00000000000000--- title: "Sequoia-PGP sq" subtitle: "integration tests, requirements, acceptance criteria" authors: "The Sequoia-PGP project" bindings: - subplot/sq-subplot.yaml - lib/files.yaml - lib/runcmd.yaml impls: rust: - subplot/sq-subplot.rs classes: - json ... # Introduction The [Sequoia-PGP][] project is an implementation of the [OpenPGP][] standard for encryption and digital signatures. Sequoia itself is a library for the Rust programming language, as well as the `sq` command line tool for people to use directly. This document captures the requirements and acceptance criteria for the `sq` tool and how they are verified, and at the same time acts as an integration test for the tool. [Sequoia-PGP]: https://sequoia-pgp.org/ [OpenPGP]: https://en.wikipedia.org/wiki/Pretty_Good_Privacy#OpenPGP ## Testing approach for sq This document explicitly only covers integration and acceptance testing of the `sq` command line tool. It does not try to verify that the underlying library implements OpenPGP correctly: the library has its own test suite for that. Instead, this document concentrates on making sure the `sq` command line tool behaves as it should from an end-user's point of view. We make the following simplifying assumption: we know the `sq` developers as competent developers, and assume that they don't entangle unrelated functionality. By this we mean that we feel we can assume that the code in `sq` that reads input files is separate from the code that compresses it, which in turn is independent of the code that writes output as text or binary data. Thus, we verify each such functionality independently of each other. This drastically cuts down the number of feature combinations we need to test. If this assumption turns out to be incorrect, we will rethink and revise the testing approach as needed. We also know, by inspection, that `sq` uses the well-known, well-respected Rust library `clap` for parsing the command line. Because of this we feel it's not necessary to verify that, for example, `sq` notices that a required argument is missing from the command line, or that it notices that there are extra arguments present. We will concentrate on testing that when invoked with valid arguments results in expected output. ## Using Subplot and this document The acceptance criteria and requirements are explained in prose and when they can be verified in an automated way, that is done using _test scenarios_. Both the prose and the scenarios are meant to be understood and agreed to by all stakeholders in the project. The [Subplot][] tool is used to render this document into human-readable form (HTML or PDF), and to generate a test program that executes the scenarios and checks they all pass. To achieve this, run the following commands: ~~~sh $ git clone https://gitlab.com/sequoia-pgp/sequoia-sq.git $ cd sequoia-sq $ subplot docgen sq-subplot.md -o sq-subplot.html $ subplot docgen sq-subplot.md -o sq-subplot.pdf $ cargo test ~~~ If you only care about generating and running tests, you only need to run `cargo test`. All the dependencies for that are automatically handled via `Cargo.toml`. To generate typeset documents (HTML and PDF), you need the following software installed: * [Subplot][], via cargo install or a Debian package (see its website) * Pandoc * Parts of TeX Live (for PDF) * Graphviz On a Debian system, that means the following packages: > `subplot pandoc pandoc-citeproc lmodern librsvg2-bin graphviz > texlive-latex-base texlive-latex-recommended > texlive-fonts-recommended plantuml` [Subplot]: https://subplot.liw.fi/ # Smoke test _Requirement: We must be able to invoke `sq` at all._ This scenario verifies that we can run `sq` in the simplest possible case: we ask the program for its version. If this works, then we know that the executable program exists, can be invoked, and at least some of its command line parsing code works. If this scenario doesn't work, then we can't expect anything else to work either. ~~~scenario given an installed sq when I run sq version then exit code is 0 then stderr matches regex ^sq \d+\.\d+\.\d+ ~~~ # Key management: `sq key` This chapter covers all key management functionality: the `sq key` subcommands. ## Key generation: `sq key generate` This section covers key generation with `sq`. Keys are somewhat complicated: it is possible to have keys for specify that they can only used for specific operations, or the time period when they are valid. Different cryptographic algorithms have different kinds of keys. We verify these by varying what kind keys we generate and that they look as expected, when inspected. ### Generate a key with defaults _Requirement: We must be able to generate new encryption keys and corresponding certificates._ This scenario generates a new key with `sq` using default settings and inspects it to see if it looks at least vaguely correct. Note that in this scenario we don't verify that the key works, other scenarios take care of that. Here we merely verify that the new key looks OK. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output key.pgp when I run sq --no-cert-store inspect key.pgp then stdout contains "Alice" then stdout contains "Expiration time: 20" then stdout contains "Key flags: certification" then stdout contains "Key flags: signing" then stdout contains "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate key without user identifiers _Requirement: We must be able to generate new encryption keys without any user identifiers._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp then file key.pgp contains "-----BEGIN PGP PRIVATE KEY BLOCK-----" ~~~ ### Generate key with more than one user identifier _Requirement: We must be able to generate new encryption keys with more than one user identifier._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --userid '' --output key.pgp then file key.pgp contains "Comment: Alice" then file key.pgp contains "Comment: " ~~~ ### Generate a key for certification only _Requirement: We must be able to generate a key that can only be used for certification, and can't be used for signing, encryption or authentication._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cannot-sign --cannot-authenticate --cannot-encrypt when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "Key flags: signing" then stdout doesn't contain "Key flags: authentication" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate a key for encryption only _Requirement: We must be able to generate a key that can only be used for encryption, and can't be used for signing or authentication._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cannot-sign --cannot-authenticate when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "Key flags: signing" then stdout doesn't contain "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate a key for storage encryption only _Requirement: We must be able to generate a key that can only be used for at-rest (storage) encryption._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --can-encrypt=storage when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "transport encryption" then stdout contains "Key flags: data-at-rest encryption" ~~~ ### Generate a key for transport encryption only _Requirement: We must be able to generate a key that can only be used for transport encryption._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --can-encrypt=transport when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: transport encryption" then stdout doesn't contain "data-at-rest encryption" ~~~ ### Generate a key for signing only _Requirement: We must be able to generate a key that can only be used for signing, and can't be used for encryption._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cannot-encrypt --cannot-authenticate when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: signing" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" then stdout doesn't contain "Key flags: authentication" ~~~ ### Generate a key for authentication only _Requirement: We must be able to generate a key that can only be used for authentication, and can't be used for encryption or signing._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --can-authenticate --cannot-sign --cannot-encrypt when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: authentication" then stdout doesn't contain "Key flags: signing" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" ~~~ ### Generate a key for encryption and authentication _Requirement: We must be able to generate a key that can only be used for encryption and authentication, and can't be used for signing._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cannot-sign when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" then stdout doesn't contain "Key flags: signing" ~~~ ### Generate a key for encryption and signing _Requirement: We must be able to generate a key that can only be used for encryption and signing, and can't be used for authentication._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cannot-authenticate when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: transport encryption, data-at-rest encryption" then stdout contains "Key flags: signing" then stdout doesn't contain "Key flags: authentication" ~~~ ### Generate a key for signing and authentication _Requirement: We must be able to generate a key that can only be used for signing and authentication, and can't be used for encryption._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cannot-encrypt when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout doesn't contain "Key flags: transport encryption, data-at-rest encryption" then stdout contains "Key flags: signing" then stdout contains "Key flags: authentication" ~~~ ### Generate a key for encryption, authentication and signing _Requirement: We must be able to generate a key that can be used for encryption, authentication and signing._ Note that `sq` always creates a key usable for certification. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store inspect key.pgp then stdout contains "Key flags: certification" then stdout contains "Key flags: authentication" then stdout contains "Key flags: transport encryption, data-at-rest encryption" then stdout contains "Key flags: signing" ~~~ ### Generate an elliptic curve key _Requirement: We must be able to generate an Curve25519 key_ This is currently the default key, but we check it separately in case the default ever changes. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cipher-suite=cv25519 when I run sq --no-cert-store inspect key.pgp then stdout contains "Public-key algo: EdDSA" then stdout contains "Public-key size: 256 bits" ~~~ ### Generate a three kilobit RSA key _Requirement: We must be able to generate a 3072-bit RSA key._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cipher-suite=rsa3k when I run sq --no-cert-store inspect key.pgp then stdout contains "Public-key algo: RSA" then stdout contains "Public-key size: 3072 bits" ~~~ ### Generate four kilobit RSA key _Requirement: We must be able to generate a 4096-bit RSA key._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --cipher-suite=rsa4k when I run sq --no-cert-store inspect key.pgp then stdout contains "Public-key algo: RSA" then stdout contains "Public-key size: 4096 bits" ~~~ ### Generate a key with revocation certificate _Requirement: We must be able to specify where the revocation certificate is store._ When `sq` generates a key, it also generates a revocation certificate. By default, this is written to a file next to the key file. However, we need to able to specify where it goes. This scenario tests various cases. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp then file key.pgp.rev contains "Comment: Revocation certificate for" when I run sq --no-cert-store key generate --output key2.pgp --rev-cert rev.pgp then file rev.pgp contains "Comment: Revocation certificate for" ~~~ ### Generate a key with default duration _Requirement: By default, generated key expire._ We generate a key with defaults, and check the key expires. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store inspect key.pgp then stdout contains "Expiration time: 20" ~~~ The check for expiration time assumes the scenario is run the 21st century, and will need to be amended in the 2090s or by time travellers running it before about the year 2000. ### Generate a key that expires at a given moment _Requirement: We must be able to generate a key that expires._ Note that the timestamp given to `--expire` is the first second when the key is no longer valid, not the last second it's valid. The inspect output is the last second of validity. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --expiry=2038-01-19T03:14:07+00:00 when I run sq --no-cert-store inspect key.pgp then stdout contains "Expiration time: 2038-01-19 03:14" when I run sq --no-cert-store inspect --time 2038-01-20T00:00:00+00:00 key.pgp then stdout contains "Invalid: The primary key is not live" ~~~ ### Generate a key with a given duration _Requirement: We must be able to generate a key that expires in a given time._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --expiry=1y when I run sq --no-cert-store inspect key.pgp then stdout contains "Expiration time: 20" ~~~ ### Generate a key without password _Requirement: We must be able to generate a that doesn't have a password._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store inspect key.pgp then stdout contains "Secret key: Unencrypted" ~~~ ### Generate a key with a password _Requirement: We must be able to generate a that does have a password._ Unfortunately, the `--with-password` option causes `sq` to read the password from the terminal, and that makes it hard to do in an automated test. Thus, this scenario isn't enabled, waiting for a way to feed `sq` a password as if the user typed it from a terminal. ~~~ given an installed sq when I run sq --no-cert-store key generate --output key.pgp --with-password when I run sq --no-cert-store inspect key.pgp then stdout contains "Secret key: Encrypted" ~~~ ### Update a key by adding User IDs _Requirement: We must be able to generate a key and add User IDs to it._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key userid add key.pgp "Juliet" "" --output new.pgp when I run sq --no-cert-store inspect new.pgp then stdout contains "UserID: Juliet" then stdout contains "UserID: " ~~~ ### Update a key by removing a User ID _Requirement: We must be able to generate a key with a User ID, and then strip the User ID._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid "" --output key.pgp when I run sq --no-cert-store key userid strip --userid "" --output new.pgp key.pgp when I run sq --no-cert-store inspect new.pgp then stdout doesn't contain "UserID:" ~~~ ## Certificate extraction: `sq key extract-cert` This section covers extraction of certificates from keys: the `sq key extract-certificate` subcommand and its variations. ### Extract certificate to the standard output _Requirement: We must be able to extract a certificate to standard output._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" ~~~ ### Extract certificate to a file _Requirement: We must be able to extract a certificate to a named file._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp --userid Alice when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store inspect cert.pgp then stdout contains "OpenPGP Certificate." then stdout contains "Alice" ~~~ ### Extract binary certificate to the standard output _Requirement: We must be able to extract a binary certificate to the standard output._ This scenario actually only verifies the output doesn't look like a textual certificate. It could certainly be improved. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp --binary then stdout doesn't contain "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout doesn't contain "-----END PGP PUBLIC KEY BLOCK-----" ~~~ ### Extract binary certificate from the standard input _Requirement: We must be able to extract a certificate from a key read from the standard input._ Unfortunately, Subplot does not currently have a way to redirect stding from a file. This scenario is inactive and here as a placeholder until Subplot learns a new trick. ~~~ given an installed sq when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert < key.pgp then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" ~~~ # Keyring management: `sq keyring` This chapter verifies that the various subcommands to manage keyring files work: subcommands of the `sq keyring` command. ## Joining keys into a keyring: `sq keyring merge` The scenarios in this section verify that various ways of joining keys into a keyring work. ### Join two keys into a textual keyring to stdout _Requirement: we can join two keys into a keyring, and have it written to stdout._ This is for secret keys, with the output going to stdout in text form. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring list ring.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### Join two keys into a textual keyring to a named file _Requirement: we can join two keys into a keyring, and have it written to a named file._ This is for secret keys, with the output going to a file in text form. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp then file ring.pgp contains "-----BEGIN PGP PRIVATE KEY BLOCK-----" then file ring.pgp contains "-----END PGP PRIVATE KEY BLOCK-----" when I run sq --no-cert-store inspect ring.pgp then stdout contains "Transferable Secret Key." then stdout contains "Alice" then stdout contains "Bob" ~~~ ### Join two keys into a binary keyring _Requirement: we can join two keys into a keyring in binary form._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp --binary when I try to run grep PGP ring.pgp then command fails when I run sq --no-cert-store inspect ring.pgp then stdout contains "Transferable Secret Key." then stdout contains "Alice" then stdout contains "Bob" ~~~ ### Join two certificates into a keyring _Requirement: we can join two certificates into a keyring._ This scenario writes the keyring to a named file. We assume the writing operation is independent of the types of items in the keyring, so we don't change writing to stdout separately. ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store keyring merge alice-cert.pgp bob-cert.pgp -o ring.pgp when I run cat ring.pgp then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" when I run sq --no-cert-store inspect ring.pgp then stdout doesn't contain "Transferable Secret Key." then stdout contains "OpenPGP Certificate." then stdout contains "Alice" then stdout contains "Bob" ~~~ ## Filter a keyring: `sq keyring filter` The scenarios in this section verify that various ways of filtering the contents of a keyring work: the `sq keyring filter` subcommand variants. ### We can extract only certificates to named file _Requirement: we can remove private keys from a keyring, leaving only certificates._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --to-cert ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "OpenPGP Certificate." then stdout doesn't contain "Transferable Secret Key." then stdout contains "Alice" then stdout contains "Bob" ~~~ ### We can filter to stdout _Requirement: we can get filter output to stdout instead of a named file._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --to-cert ring.pgp then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then stdout contains "-----END PGP PUBLIC KEY BLOCK-----" ~~~ ### We can filter with binary output _Requirement: we can get filter output in binary form._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --binary --to-cert ring.pgp then stdout doesn't contain "-----BEGIN PGP PUBLIC KEY BLOCK-----" ~~~ ### We can keep only matching certificates _Requirement: we can remove certificates that don't match filter criteria._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --userid Bob --output alice.pgp when I run sq --no-cert-store keyring filter --prune-certs --name Alice alice.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for specific user id _Requirement: we can extract only keys and certificates with a specific user id._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --userid Alice ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for any of several user ids _Requirement: we can extract only keys and certificates with any of specific user ids._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --userid Alice --userid Bob ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### We can filter for a name _Requirement: we can extract only keys and certificates with a name as part of a user ids._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid 'Alice ' --output alice.pgp when I run sq --no-cert-store key generate --userid 'Bob ' --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --name Alice ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for several names _Requirement: we can extract only keys and certificates with any of several names as part of the user id._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid 'Alice ' --output alice.pgp when I run sq --no-cert-store key generate --userid 'Bob ' --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --name Alice --name Bob ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### We can filter for a domain _Requirement: we can extract only keys and certificates with a name as part of a user ids._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid 'Alice ' --output alice.pgp when I run sq --no-cert-store key generate --userid 'Bob ' --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --domain example.com ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### We can filter for several domains _Requirement: we can extract only keys and certificates with any of several names as part of the user id._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid 'Alice ' --output alice.pgp when I run sq --no-cert-store key generate --userid 'Bob ' --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring filter --domain example.com --domain sequoia-pgp.org ring.pgp -o filtered.pgp when I run sq --no-cert-store inspect filtered.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ## Listing contents of a keyring: `sq keyring list` The scenarios in this section verify the contents of a keyring can be listed. ### Choose too-new output major version for keyring listing _Requirement: If we ask for an unsupported major output version, we get an error._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I try to run sq --output-version=9999 keyring list alice.pgp then command fails when I try to run env SQ_OUTPUT_VERSION=9999 sq keyring list alice.pgp then command fails ~~~ ### Choose too-new output minor version for keyring listing _Requirement: If we ask for an unsupported output minor version, we get an error._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I try to run sq --output-version=0.9999 keyring list alice.pgp then command fails ~~~ ### Choose too-new output patch version for keyring listing _Requirement: If we ask for an unsupported output patch version, we get an error._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I try to run sq --output-version=0.0.9999 keyring list alice.pgp then command fails ~~~ ### List keys in a keyring _Requirement: we can list the keys in a keyring._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring list ring.pgp then stdout contains "Alice" then stdout contains "Bob" ~~~ ### List, as JSON, keys in a keyring _Requirement: we can list the keys in a keyring in a JSON format._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --userid '' --output alice.pgp when I run sq --no-cert-store inspect alice.pgp then I remember the fingerprint as ALICE_FINGERPRINT when I run sq --no-cert-store keyring merge alice.pgp -o ring.pgp when I run sq --no-cert-store --output-format=json keyring list ring.pgp then stdout, as JSON, matches pattern keyring-list-pattern.json when I run env SQ_OUTPUT_FORMAT=json sq keyring list ring.pgp then stdout, as JSON, matches pattern keyring-list-pattern.json when I run env SQ_OUTPUT_FORMAT=human-readable sq --output-format=json keyring list ring.pgp then stdout, as JSON, matches pattern keyring-list-pattern.json ~~~ ~~~{#keyring-list-pattern.json .file .json .numberLines} { "sq_output_version": { "major": 0, "minor": 0, "patch": 0 }, "keys": [ { "fingerprint": "${ALICE_FINGERPRINT}", "primary_userid": "Alice", "userids": [""] } ] } ~~~ ### List keys in a key file _Requirement: we can list the keys in a key file._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store keyring list alice.pgp then stdout contains "Alice" then stdout doesn't contain "Bob" ~~~ ### List all user ids in a key file _Requirement: we can list all user ids._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --userid Bob --output alice.pgp when I run sq --no-cert-store keyring list alice.pgp --all-userids then stdout contains "Alice" then stdout contains "Bob" ~~~ ### List keys in keyring read from stdin _Requirement: we can list keys in a keyring that we read from stdin._ This isn't implemented yet, because Subplot needs to add support for redirecting stdin to come from a file first. ## Split a keyring: `sq keyring split` The scenarios in this section verify that splitting a keyring into individual files, one per key: the `sq keyring split` subcommand. Or rather, there will be such scenarios here when Subplot provides tools for dealing with randomly named files. Until then, this section is a placeholder. ~~~ given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store keyring merge alice.pgp bob.pgp -o ring.pgp when I run sq --no-cert-store keyring split ring.pgp then the resulting files match alice,pgp and bob.pgp ~~~ # Encryption and decryption: `sq encrypt` and `sq decrypt` This chapter has scenarios for verifying that encryption and decryption work. The overall approach is to do round trips: we encrypt, then decrypt, and is the result is identical to the input, all good. ## Encrypt to stdout as ASCII armored _Requirement: We must be able to encrypt a file using a certificate, with output going to stdout. We also verify that the encrypted output doesn't contain the message in cleartext, just in case. ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert -o cert.pgp key.pgp when I run sq --no-cert-store encrypt --recipient-file cert.pgp hello.txt then stdout contains "-----BEGIN PGP MESSAGE-----" then stdout doesn't contain "hello, world" ~~~ ## Encrypt to stdout as binary _Requirement: We must be able to encrypt a file using a certificate, with output going to stdout. We also verify that the encrypted output doesn't contain the message in cleartext, just in case. ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert -o cert.pgp key.pgp when I run sq --no-cert-store encrypt --binary --recipient-file cert.pgp hello.txt then stdout doesn't contain "-----BEGIN PGP MESSAGE-----" then stdout doesn't contain "hello, world" ~~~ ## Encrypt and decrypt using asymmetric encryption _Requirement: We must be able to encrypt a file using a certificate, and then decrypt it using the corresponding key._ This scenario creates a plain text file, generates a key, encrypts and then decrypts the file. The resulting output must be identical to the original plain text input file. This is a very simplistic scenario and does not even try to test harder cases (binary files, very large files, etc). ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert -o cert.pgp key.pgp when I run sq --no-cert-store encrypt -o x.pgp --recipient-file cert.pgp hello.txt when I run sq --no-cert-store decrypt -o output.txt --recipient-file key.pgp x.pgp then files hello.txt and output.txt match ~~~ ## Encrypt for multiple recipients _Requirement: We must be able to encrypt a message for multiple recipients at a time._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output alice.pgp when I run sq --no-cert-store key extract-cert -o alice-cert.pgp alice.pgp when I run sq --no-cert-store key generate --output bob.pgp when I run sq --no-cert-store key extract-cert -o bob-cert.pgp bob.pgp when I run sq --no-cert-store encrypt --recipient-file alice-cert.pgp --recipient-file bob-cert.pgp hello.txt -o x.pgp when I run sq --no-cert-store decrypt --recipient-file alice.pgp -o alice.txt x.pgp then files hello.txt and alice.txt match when I run sq --no-cert-store decrypt --recipient-file bob.pgp -o bob.txt x.pgp then files hello.txt and bob.txt match ~~~ ## Encrypt and sign at the same time _Requirement: We must be able to sign and encrypt a message at the same time._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output alice.pgp when I run sq --no-cert-store key extract-cert -o alice-cert.pgp alice.pgp when I run sq --no-cert-store encrypt --recipient-file alice-cert.pgp --signer-file alice.pgp hello.txt -o x.pgp when I run sq --no-cert-store decrypt --recipient-file alice.pgp -o alice.txt x.pgp --signer-file alice-cert.pgp then files hello.txt and alice.txt match ~~~ ## Detect bad signature when decrypting _Requirement: When decrypting a message, if a signature check fails, there should be no output._ ~~~scenario given an installed sq given file hello.txt given file empty when I run sq --no-cert-store key generate --output alice.pgp when I run sq --no-cert-store key extract-cert -o alice-cert.pgp alice.pgp when I run sq --no-cert-store key generate --output bob.pgp when I run sq --no-cert-store key extract-cert -o bob-cert.pgp bob.pgp when I run sq --no-cert-store encrypt --recipient-file alice-cert.pgp --signer-file alice.pgp hello.txt -o x.pgp when I try to run sq decrypt --recipient-file alice.pgp -o alice.txt x.pgp --signer-file bob-cert.pgp then exit code is 1 then files alice.txt and empty match ~~~ # Certify user identities: `sq pki certify` The scenarios in this chapter verify the certification functionality: the subcommand `sq certify` in its various variations. ## Certify an identity as ASCII armor _Requirement: We can certify a user identity on a key._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store inspect bob-cert.pgp then stdout doesn't contain "Certifications:" when I run sq --no-cert-store pki certify alice.pgp bob-cert.pgp Bob -o cert.pgp then file cert.pgp contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" then file cert.pgp contains "-----END PGP PUBLIC KEY BLOCK-----" when I run sq --no-cert-store inspect cert.pgp then stdout contains "Certifications: 1," ~~~ ## Certify an identity as binary _Requirement: We can certify a user identity on a key._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store inspect bob-cert.pgp then stdout doesn't contain "Certifications:" when I run sq --no-cert-store pki certify alice.pgp bob-cert.pgp Bob -o cert.pgp --binary when I run cat cert.pgp then stdout doesn't contain "-----BEGIN PGP PUBLIC KEY BLOCK-----" when I run sq --no-cert-store inspect cert.pgp then stdout contains "Certifications: 1," ~~~ ## Certify an identity matched by email address _Requirement: We can certify a user identity on a cert identified by email address._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid "" --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid "" --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store pki certify alice.pgp bob-cert.pgp --email bob@example.org -o cert.pgp when I run sq --no-cert-store inspect cert.pgp then stdout contains "Certifications: 1," ~~~ ## Certify multiple identities matched by email address _Requirement: We can certify multiple user identities on a cert identified by email address._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid "" --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid "" --userid "Bob " --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store pki certify alice.pgp bob-cert.pgp --email bob@example.org -o cert.pgp when I run sq --no-cert-store key userid strip --userid "" -o cert.0.pgp cert.pgp when I run sq --no-cert-store inspect cert.0.pgp then stdout contains "Certifications: 1," when I run sq --no-cert-store key userid strip --userid "Bob " -o cert.1.pgp cert.pgp when I run sq --no-cert-store inspect cert.1.pgp then stdout contains "Certifications: 1," ~~~ ## Certify an identity that is not self-signed _Requirement: We can certify a user identity on a cert, even if that user identity doesn't exist on that cert, and consequently has no self-signature._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store inspect bob-cert.pgp then stdout doesn't contain "Certifications:" when I run sq --no-cert-store pki certify --add-userid alice.pgp bob-cert.pgp "My friend Bob" -o cert.pgp when I run sq --no-cert-store inspect cert.pgp then stdout contains "My friend Bob" then stdout contains "Certifications: 1," ~~~ ## Certify an email identity that is not self-signed _Requirement: We can certify an email on a cert, even if that email address doesn't exist on that cert, and consequently has no self-signature._ ~~~scenario given an installed sq when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store pki certify --add-userid alice.pgp bob-cert.pgp --email "bob@example.org" -o cert.pgp when I run sq --no-cert-store inspect cert.pgp then stdout contains "" then stdout contains "Certifications: 1," ~~~ # Sign a document and verify the signature: `sq sign` and `sq verify` This chapter verifies that digital signatures work in `sq`. Like with encryption, the verification is based on round trips: we create a signature, and that it matches the signed data. We break this into a number simple cases. ## Create signature to stdout in ASCII armor _Requirement: We can create a signature and have it written to stdout in ASCII armor form._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store sign --signer-file key.pgp hello.txt then stdout contains "-----BEGIN PGP MESSAGE-----" then stdout contains "-----END PGP MESSAGE-----" ~~~ ## Create signature to stdout in binary _Requirement: We can create a signature and have it written to stdout in binary form._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store sign --signer-file key.pgp hello.txt --binary then stdout doesn't contain "-----BEGIN PGP MESSAGE-----" then stdout doesn't contain "-----END PGP MESSAGE-----" ~~~ ## Create signature to named file _Requirement: We can create a signature and have it written to a named file._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store sign --signer-file key.pgp hello.txt -o signed.txt then file signed.txt contains "-----BEGIN PGP MESSAGE-----" then file signed.txt contains "-----END PGP MESSAGE-----" ~~~ ## Signed file can be verified _Requirement: We can sign a file and verify the signature._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store sign --signer-file key.pgp hello.txt -o signed.txt when I run sq --no-cert-store verify --signer-file cert.pgp signed.txt then stdout contains "hello, world" ~~~ ## File is signed with all required keys _Requirement: We can verify that a file is signed by all required keys._ We verify this by signing a file twice, and verifying there are two signatures. We also verify that if there is only one signature, it's not enough, when we need two. ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store sign --signer-file alice.pgp hello.txt -o signed1.txt when I try to run sq verify --signer-file alice-cert.pgp --signer-file bob-cert.pgp --signatures=2 signed1.txt then exit code is 1 when I run sq --no-cert-store sign --append --signer-file bob.pgp signed1.txt -o signed2.txt when I run sq --no-cert-store verify --signer-file alice-cert.pgp --signer-file bob-cert.pgp --signatures=1 signed2.txt then stdout contains "hello, world" when I run sq --no-cert-store verify --signer-file alice-cert.pgp --signer-file bob-cert.pgp --signatures=2 signed2.txt then stdout contains "hello, world" ~~~ ## Signed file cannot be verified if it has been modified _Requirement: We can sign a file and verifying the signature fails if the signed file has been modified._ We modify the signed file by removing the third line of it. The file starts with a line containing "-----BEGIN PGP MESSAGE-----" and then an empty line, and the third line is actual data. If we delete that, the file by definition can't be valid anymore. ~~~scenario given an installed sq given file hello.txt given file sed-in-place when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store sign --signer-file key.pgp hello.txt -o signed.txt when I run bash sed-in-place 3d signed.txt when I try to run sq verify --signer-file cert.pgp signed.txt then command fails ~~~ ~~~{#sed-in-place .file .sh} #!/bin/sh set -eu tmp="$(mktemp)" trap 'rm -f "$tmp"' EXIT sed "$1" "$2" > "$tmp" cat "$tmp" > "$2" ~~~ ## Create cleartext signature _Requirement: We can create a signature such that the signed data is included in a readable form._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store sign --cleartext-signature --signer-file key.pgp hello.txt -o signed.txt then file signed.txt contains "-----BEGIN PGP SIGNED MESSAGE-----" then file signed.txt contains "hello, world" then file signed.txt contains "-----END PGP SIGNATURE-----" when I run sq --no-cert-store verify --signer-file cert.pgp signed.txt then stdout contains "hello, world" ~~~ ## Cleartext signature cannot be verified if it has been modified _Requirement: If a cleartext signature is modified, it can't be verified._ ~~~scenario given an installed sq given file hello.txt given file sed-in-place when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store sign --cleartext-signature --signer-file key.pgp hello.txt -o signed.txt when I run bash sed-in-place s/hello/HELLO/ signed.txt when I try to run sq verify --signer-file cert.pgp signed.txt then exit code is 1 ~~~ ## Create a detached signature _Requirement: We can create a signature that is doesn't include the data it signs._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store sign --detached --signer-file key.pgp hello.txt -o sig.txt then file sig.txt contains "-----BEGIN PGP SIGNATURE-----" then file sig.txt contains "-----END PGP SIGNATURE-----" when I run sq --no-cert-store verify --detached=sig.txt --signer-file=cert.pgp hello.txt then stdout doesn't contain "hello, world" then exit code is 0 ~~~ ## Detached signature cannot be verified if the data has been modified _Requirement: If the file that is signed using a detached signature is modified, the signature can't be verified._ ~~~scenario given an installed sq given file hello.txt given file sed-in-place when I run sq --no-cert-store key generate --output key.pgp when I run sq --no-cert-store key extract-cert key.pgp -o cert.pgp when I run sq --no-cert-store sign --detached --signer-file key.pgp hello.txt -o sig.txt when I run bash sed-in-place s/hello/HELLO/ hello.txt when I try to run sq verify --detached=sig.txt --signer-file=cert.pgp hello.txt then exit code is 1 ~~~ ## Append signature to already signed message _Requirement: We must be able to add a signature to an already signed message._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store sign --signer-file alice.pgp hello.txt -o signed1.txt when I run sq --no-cert-store sign --signer-file bob.pgp --append signed1.txt -o signed2.txt when I run sq --no-cert-store verify signed2.txt --signer-file alice-cert.pgp --signer-file bob-cert.pgp then stdout contains "hello, world" then stderr matches regex 2.good signatures ~~~ ## Merge signed files _Requirement: We must be able to merge signatures of a file signed twice separately._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store key generate --userid Alice --output alice.pgp when I run sq --no-cert-store key extract-cert alice.pgp -o alice-cert.pgp when I run sq --no-cert-store key generate --userid Bob --output bob.pgp when I run sq --no-cert-store key extract-cert bob.pgp -o bob-cert.pgp when I run sq --no-cert-store sign --signer-file alice.pgp hello.txt -o signed1.txt when I run sq --no-cert-store sign --signer-file bob.pgp hello.txt -o signed2.txt when I run sq --no-cert-store sign --merge=signed2.txt signed1.txt -o merged.txt when I run sq --no-cert-store verify merged.txt --signer-file alice-cert.pgp --signer-file bob-cert.pgp then stdout contains "hello, world" then stderr matches regex 2.good signatures ~~~ # ASCII Armor data representation: `sq toolbox armor` and `sq toolbox dearmor` The scenarios in this chapter verify that `sq` can convert data into the "ASCII Armor" representation and back. ## Convert data file to armored format to stdout _Requirement: We must be able to convert a file to armored format to stdout._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store toolbox armor hello.txt then stdout contains "-----BEGIN PGP ARMORED FILE-----" then stdout contains "-----END PGP ARMORED FILE-----" ~~~ ## Convert data file to armored format to file _Requirement: We must be able to convert a file to armored format to a named file._ ~~~scenario given an installed sq given file hello.txt given file hello.asc when I run sq --no-cert-store toolbox armor hello.txt -o hello.out then files hello.asc and hello.out match ~~~ ## Convert data file to armored format with desired label _Requirement: We must be able to convert a file to armored format with the label we choose._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store toolbox armor hello.txt --label auto then stdout contains "-----BEGIN PGP ARMORED FILE-----" when I run sq --no-cert-store toolbox armor hello.txt --label message then stdout contains "-----BEGIN PGP MESSAGE-----" when I run sq --no-cert-store toolbox armor hello.txt --label cert then stdout contains "-----BEGIN PGP PUBLIC KEY BLOCK-----" when I run sq --no-cert-store toolbox armor hello.txt --label key then stdout contains "-----BEGIN PGP PRIVATE KEY BLOCK-----" when I run sq --no-cert-store toolbox armor hello.txt --label sig then stdout contains "-----BEGIN PGP SIGNATURE-----" when I run sq --no-cert-store toolbox armor hello.txt --label file then stdout contains "-----BEGIN PGP ARMORED FILE-----" ~~~ ## Convert data file from armored format to stdout _Requirement: We must be able to convert a file from armored format to stdout._ ~~~scenario given an installed sq given file hello.asc when I run sq --no-cert-store toolbox dearmor hello.asc then stdout contains "hello, world" ~~~ ## Convert data file from armored format to file _Requirement: We must be able to convert a file from armored format to a named file._ ~~~scenario given an installed sq given file hello.txt given file hello.asc when I run sq --no-cert-store toolbox dearmor hello.asc -o hello.out then files hello.txt and hello.out match ~~~ ## Armor round trip _Requirement: We must be able to convert data to armored format and back._ ~~~scenario given an installed sq given file hello.txt when I run sq --no-cert-store toolbox armor hello.txt -o hello.tmp when I run sq --no-cert-store toolbox dearmor hello.tmp -o hello.out then files hello.txt and hello.out match ~~~ # Web key directory (WKD) support [Web Key Directory]: https://wiki.gnupg.org/WKD [Internet Draft 14 for WKD]: https://www.ietf.org/archive/id/draft-koch-openpgp-webkey-service-14.html [Web Key Directory][] (WKD) specifies how to locate a certificate for a given email address by constructing HTTPS URLs from the email address. It is specified in [Internet Draft 14 for WKD][]. The two URLs are called the "advanced" and "direct" URLs. They are the same, except the advanced one uses a subdomain, and an a subdirectory named after the domain. This allows the web server where the certificates are published to be operated separately from any other services for the parent domain. The advanced URL is the preferred URL. That is why `wkd wkd url` prints that, and the other URL is a longer command. ## Advanced WKD URL _Requirement: Output the advanced URL for an email address._ An advanced URL uses the "openpgpkey" subdomain of the domain in the email address, and a subdirectory named after the email domain. ~~~scenario given an installed sq when I run sq --no-cert-store network wkd url me@example.com then stdout contains "https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/s8y7oh5xrdpu9psba3i5ntk64ohouhga?l=me" when I run sq --no-cert-store --output-format=json network wkd url me@example.com then stdout, as JSON, matches pattern wkd.json ~~~ ~~~{#wkd.json .file .json .numberLines} { "sq_output_version": { "major": 0, "minor": 0, "patch": 0 }, "advanced_url": "https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/s8y7oh5xrdpu9psba3i5ntk64ohouhga?l=me", "direct_url": "https://example.com/.well-known/openpgpkey/hu/s8y7oh5xrdpu9psba3i5ntk64ohouhga?l=me" } ~~~ ## Direct WKD URL _Requirement: Output the direct URL for an email address._ The direct URL lacks the subdomain and subdirectory of an advanced one. ~~~scenario given an installed sq when I run sq --no-cert-store network wkd direct-url me@example.com then stdout contains "https://example.com/.well-known/openpgpkey/hu/s8y7oh5xrdpu9psba3i5ntk64ohouhga?l=me" when I run sq --no-cert-store --output-format=json network wkd url me@example.com then stdout, as JSON, matches pattern wkd.json ~~~ ## Email local part in original form in WKD URL _Requirement: The WKD URL has the local part of an email address as given in the input, just in case it matters to the server._ An advanced URL uses the "openpgpkey" subdomain of the domain in the email address, and a subdirectory named after the email domain. ~~~scenario given an installed sq when I run sq --no-cert-store network wkd url Joe.Doe@Example.ORG then stdout contains "https://openpgpkey.example.org/.well-known/openpgpkey/example.org/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=Joe.Doe" when I run sq --no-cert-store network wkd direct-url Joe.Doe@Example.ORG then stdout contains "https://example.org/.well-known/openpgpkey/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=Joe.Doe" ~~~ # Test data file We use this file as an input file in the tests. It is a very short file, and a text file, but this is enough for the current set of requirements and scenarios. ~~~{#hello.txt .file} hello, world ~~~ This is the same content, but in ASCII armored representation. ~~~{#hello.asc .file} -----BEGIN PGP ARMORED FILE----- aGVsbG8sIHdvcmxkCg== =FOuc -----END PGP ARMORED FILE----- ~~~ This is an empty file. ~~~{#empty .file add-newline=no} ~~~ sequoia-sq-0.33.0/sq.subplot000064400000000000000000000004311046102023000140310ustar 00000000000000title: "Sequoia-PGP sq" subtitle: "integration tests, requirements, acceptance criteria" authors: - "The Sequoia-PGP project" markdowns: - sq-subplot.md bindings: - subplot/sq-subplot.yaml - lib/files.yaml - lib/runcmd.yaml impls: rust: - subplot/sq-subplot.rs classes: - json sequoia-sq-0.33.0/src/cli/autocrypt.rs000064400000000000000000000112411046102023000157330ustar 00000000000000use clap::{ValueEnum, Args, Parser, Subcommand}; use super::types::ClapData; use super::types::FileOrStdin; use super::types::FileOrStdout; #[derive(Parser, Debug)] #[clap( name = "autocrypt", about = "Communicates certificates using Autocrypt", long_about = "Communicates certificates using Autocrypt Autocrypt is a standard for mail user agents to provide convenient end-to-end encryption of emails. This subcommand provides a limited way to produce and consume headers that are used by Autocrypt to communicate certificates between clients. See . ", subcommand_required = true, arg_required_else_help = true )] pub struct Command { #[clap(subcommand)] pub subcommand: Subcommands, } #[derive(Debug, Subcommand)] pub enum Subcommands { Import(ImportCommand), Decode(DecodeCommand), EncodeSender(EncodeSenderCommand), } #[derive(Debug, Args)] #[clap( about = "Imports Autocrypt-encoded certificates", long_about = "Imports Autocrypt-encoded certificates Given a mail containing autocrypt headers (or an key-gossip headers), this command extracts and imports the certificates encoded within it. ", after_help = "EXAMPLES: # Imports all certificates from a mail $ sq autocrypt import autocrypt.eml " )] pub struct ImportCommand { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, } #[derive(Debug, Args)] #[clap( about = "Reads Autocrypt-encoded certificates", long_about = "Reads Autocrypt-encoded certificates Given an autocrypt header (or an key-gossip header), this command extracts the certificate encoded within it. The converse operation is `sq autocrypt encode-sender`. ", after_help = "EXAMPLES: # Extract all certificates from a mail $ sq autocrypt decode autocrypt.eml " )] pub struct DecodeCommand { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap(short = 'B', long, help = "Emits binary data")] pub binary: bool, } //#[derive(Subcommand)] #[derive(Debug, Args)] #[clap( name = "encode-sender", about = "Encodes a certificate into an Autocrypt header", long_about = "Encodes a certificate into an Autocrypt header A certificate can be encoded and included in a header of an email message. This command encodes the certificate, adds the senders email address (which must match the one used in the `From` header), and the senders `prefer-encrypt` state (see the Autocrypt spec for more information). The converse operation is `sq autocrypt decode`. ", after_help = "EXAMPLES: # Encodes a certificate $ sq autocrypt encode-sender juliet.pgp # Encodes a certificate with an explicit sender address $ sq autocrypt encode-sender --email juliet@example.org juliet.pgp # Encodes a certificate while indicating the willingness to encrypt $ sq autocrypt encode-sender --prefer-encrypt mutual juliet.pgp " )] pub struct EncodeSenderCommand { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, // TODO the help message looks like "primary userid" might be the default // email. clarify #[clap( long = "email", value_name = "ADDRESS", help = "Sets the address [default: primary userid]" )] pub address: Option, #[clap( long = "prefer-encrypt", value_name = "PREFER-ENCRYPT", default_value_t = PreferEncryptArgs::NoPreference, help = "Sets the prefer-encrypt attribute", value_enum, )] pub prefer_encrypt: PreferEncryptArgs, } #[derive(ValueEnum, Debug, Clone)] pub enum PreferEncryptArgs { #[clap(name = "nopreference")] NoPreference, Mutual, } impl std::fmt::Display for PreferEncryptArgs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { PreferEncryptArgs::Mutual => write!(f, "mutual"), PreferEncryptArgs::NoPreference => write!(f, "nopreference"), } } } sequoia-sq-0.33.0/src/cli/cert/export.rs000064400000000000000000000066051046102023000161670ustar 00000000000000use clap::Parser; use sequoia_openpgp as openpgp; use openpgp::KeyHandle; #[derive(Parser, Debug)] #[clap( name = "export", about = "Exports certificates from the local certificate store", long_about = "Exports certificates from the local certificate store If multiple predicates are specified a certificate is returned if at least one of them matches. This does not check the authenticity of the certificates in anyway. Before using the certificates, be sure to validate and authenticate them. When matching on subkeys or User IDs, the component must have a valid self signature according to the policy. This is not the case when matching the certificate's key handle using `--cert` or when exporting all certificates. Fails if search criteria are specified and none of them matches any certificates. Note: this means if the certificate store is empty and no search criteria are specified, then this will return success.", after_help = "EXAMPLES: # Exports all certificates. $ sq cert export > all.pgp # Exports certificates with a matching User ID packet. The binding # signatures are checked, but the User IDs are not authenticated. # Note: this check is case sensitive. $ sq cert export --userid 'Alice ' # Exports certificates with a User ID containing the email address. # The binding signatures are checked, but the User IDs are not # authenticated. Note: this check is case insensitive. $ sq cert export --email 'alice@example.org' # Exports certificates where the certificate (i.e., the primary key) # has the specified Key ID. $ sq cert export --cert 1234567812345678 # Exports certificates where the primary key or a subkey matches the # specified Key ID. $ sq cert export --key 1234567812345678 # Exports certificates that contain a User ID with *either* (not # both!) email address. Note: this check is case insensitive. $ sq cert export --email alice@example.org --email bob@example.org ", )] pub struct Command { #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, #[clap( long = "cert", value_name = "FINGERPRINT|KEYID", help = "Returns certificates that \ have the specified fingerprint or key ID", )] pub cert: Vec, #[clap( long = "key", value_name = "FINGERPRINT|KEYID", help = "Returns certificates where the primary key or \ a subkey has the specified fingerprint or key ID", )] pub key: Vec, #[clap( long = "userid", value_name = "USERID", help = "Returns certificates that have a User ID that \ matches exactly, including case", )] pub userid: Vec, #[clap( long = "grep", value_name = "PATTERN", help = "Returns certificates that have a User ID that \ contains the string, case insensitively", )] pub grep: Vec, #[clap( long = "email", value_name = "EMAIL", help = "Returns certificates that have a User ID with \ the specified email address, case insensitively", )] pub email: Vec, #[clap( long = "domain", value_name = "DOMAIN", help = "Returns certificates that have a User ID with \ an email address from the specified domain", )] pub domain: Vec, } sequoia-sq-0.33.0/src/cli/cert/import.rs000064400000000000000000000007171046102023000161560ustar 00000000000000use std::path::PathBuf; use clap::Parser; #[derive(Parser, Debug)] #[clap( name = "import", about = "Imports certificates into the local certificate store", long_about = "Imports certificates into the local certificate store ", after_help = "EXAMPLES: # Imports a certificate. $ sq cert import < juliet.pgp ", )] pub struct Command { #[clap(value_name = "FILE", help = "Reads from FILE or stdin if omitted")] pub input: Vec, } sequoia-sq-0.33.0/src/cli/cert.rs000064400000000000000000000014611046102023000146410ustar 00000000000000//! Command-line parser for `sq cert`. use clap::{Parser, Subcommand}; pub mod export; pub mod import; #[derive(Parser, Debug)] #[clap( name = "cert", about = "Manages certificates", long_about = "Manages certificates We use the term \"certificate\", or \"cert\" for short, to refer to OpenPGP keys that do not contain secrets. This subcommand provides primitives to generate and otherwise manipulate certs. Conversely, we use the term \"key\" to refer to OpenPGP keys that do contain secrets. See `sq key` for operations on keys. ", subcommand_required = true, arg_required_else_help = true, )] pub struct Command { #[clap(subcommand)] pub subcommand: Subcommands, } #[derive(Debug, Subcommand)] pub enum Subcommands { Import(import::Command), Export(export::Command), } sequoia-sq-0.33.0/src/cli/decrypt.rs000064400000000000000000000070071046102023000153600ustar 00000000000000//! Command-line parser for `sq decrypt`. use std::path::PathBuf; use clap::Parser; use super::types::ClapData; use super::types::FileOrStdin; use super::types::FileOrStdout; use super::types::SessionKey; #[derive(Parser, Debug)] #[clap( name = "decrypt", about = "Decrypts a message", long_about = "Decrypts a message Decrypts a message using either supplied keys, or by prompting for a password. If message tampering is detected, an error is returned. See below for details. If certificates are supplied using the `--signer-cert` option, any signatures that are found are checked using these certificates. Verification is only successful if there is no bad signature, and the number of successfully verified signatures reaches the threshold configured with the `--signatures` parameter. If the signature verification fails, or if message tampering is detected, the program terminates with an exit status indicating failure. In addition to that, the last 25 MiB of the message are withheld, i.e. if the message is smaller than 25 MiB, no output is produced, and if it is larger, then the output will be truncated. The converse operation is `sq encrypt`. ", after_help = "EXAMPLES: # Decrypt a file using a secret key $ sq decrypt --recipient-file juliet.pgp ciphertext.pgp # Decrypt a file verifying signatures $ sq decrypt --recipient-file juliet.pgp --signer-file romeo.pgp \\ ciphertext.pgp # Decrypt a file using a password $ sq decrypt ciphertext.pgp ", )] // TODO use usize pub struct Command { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( short = 'n', long = "signatures", value_name = "N", help = "Sets the threshold of valid signatures to N", long_help = "Sets the threshold of valid signatures to N. \ The message will only be considered \ verified if this threshold is reached. \ [default: 1 if at least one signer cert file \ is given, 0 otherwise]", )] pub signatures: Option, #[clap( long = "signer-file", value_name = "CERT_FILE", help = "Verifies signatures using the certificates in CERT_FILE", )] pub sender_cert_file: Vec, #[clap( long = "recipient-file", value_name = "KEY_FILE", help = "Decrypts the message using the key in KEY_FILE", )] pub secret_key_file: Vec, #[clap( long = "private-key-store", value_name = "KEY_STORE", help = "Provides parameters for private key store", )] pub private_key_store: Option, #[clap( long = "dump-session-key", help = "Prints the session key to stderr", )] pub dump_session_key: bool, #[clap( long = "session-key", value_name = "SESSION-KEY", help = "Decrypts an encrypted message using SESSION-KEY", )] pub session_key: Vec, #[clap( long = "dump", help = "Prints a packet dump to stderr", )] pub dump: bool, #[clap( short = 'x', long = "hex", help = "Prints a hexdump (implies `--dump`)", )] pub hex: bool, } sequoia-sq-0.33.0/src/cli/encrypt.rs000064400000000000000000000146011046102023000153700ustar 00000000000000//! Command-line parser for `sq encrypt`. use std::path::PathBuf; use clap::ArgAction::Count; use clap::{ValueEnum, Parser}; use sequoia_openpgp as openpgp; use openpgp::KeyHandle; use super::types::ClapData; use super::types::EncryptPurpose; use super::types::MetadataTime; use super::types::FileOrStdin; use super::types::FileOrStdout; #[derive(Parser, Debug)] #[clap( name = "encrypt", about = "Encrypts a message", long_about = "Encrypts a message Encrypts a message for any number of recipients and with any number of passwords, optionally signing the message in the process. The converse operation is `sq decrypt`. `sq encrypt` respects the reference time set by the top-level `--time` argument. It uses the reference time when selecting encryption keys, and it sets the signature's creation time to the reference time. ", after_help = "EXAMPLES: # Encrypt a file using a certificate $ sq encrypt --recipient-file romeo.pgp message.txt # Encrypt a file creating a signature in the process $ sq encrypt --recipient-file romeo.pgp --signer-file juliet.pgp \\ message.txt # Encrypt a file using a password $ sq encrypt --symmetric message.txt ", )] pub struct Command { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, #[clap( long = "recipient-email", value_name = "EMAIL", help = "Encrypts to all certificates that can be authenticated \ for the specified email address", )] pub recipients_email: Vec, #[clap( long = "recipient-userid", value_name = "USERID", help = "Encrypts to all certificates that can be authenticated \ for the specified User ID", )] pub recipients_userid: Vec, #[clap( long = "recipient-cert", value_name = "FINGERPRINT|KEYID", help = "Encrypts to the named certificates", )] pub recipients_cert: Vec, #[clap( long = "recipient-file", value_name = "CERT_RING_FILE", help = "Encrypts to all certificates in CERT_RING_FILE", )] pub recipients_file: Vec, #[clap( help = "Sets the filename of the encrypted file as metadata", long, long_help = "Sets the filename of the encrypted file as metadata. \ Do note, that this metadata is not signed and as such relying on \ it - on sender or receiver side - is generally considered \ dangerous.", )] pub set_metadata_filename: bool, #[clap( default_value_t = MetadataTime::default(), help = "Sets time for encrypted file as metadata", long, long_help = format!( "Sets time for encrypted file as metadata. \ Allows setting TIME either as ISO 8601 formatted string or by \ providing custom keywords. \ With `{}`, the metadata is not set. \ With `{}`, the metadata is set to the file's creation \ timestamp. \ With `{}`, the metadata is set to the file's last \ modification timestamp. \ With `{}`, the metadata is set to the creation \ timestamp of the message for which the metadata is added. \ Do note, that this metadata is not signed and as such relying on \ it - on sender or receiver side - is generally considered \ dangerous.", MetadataTime::None, MetadataTime::FileCreation, MetadataTime::FileModification, MetadataTime::MessageCreation, ), value_name = "TIME", )] pub set_metadata_time: MetadataTime, #[clap( long = "signer-file", value_name = "KEY_FILE", help = "Signs the message using the key in KEY_FILE", )] pub signer_key_file: Vec, #[clap( long = "private-key-store", value_name = "KEY_STORE", help = "Provides parameters for private key store", )] pub private_key_store: Option, #[clap( short = 's', long = "symmetric", help = "Prompts to add a password to encrypt with", long_help = "Prompts to add a password to encrypt with. \ When using this option, the user is asked to provide a password, \ which is used to encrypt the message. \ This option can be provided more than once to provide more than \ one password. \ The encrypted data can afterwards be decrypted with either one of \ the recipient's keys, or one of the provided passwords.", action = Count, )] pub symmetric: u8, #[clap( long = "encrypt-for", value_name = "PURPOSE", default_value_t = EncryptPurpose::Universal, help = "Selects what kind of keys are considered for encryption.", long_help = "Selects what kind of keys are considered for \ encryption. 'transport' select subkeys marked \ as suitable for transport encryption, 'storage' \ selects those for encrypting data at rest, \ and 'universal' selects all encryption-capable \ subkeys.", value_enum, )] pub mode: EncryptPurpose, #[clap( long = "compression", value_name = "KIND", default_value_t = CompressionMode::None, help = "Selects compression scheme to use", value_enum, )] pub compression: CompressionMode, #[clap( long = "use-expired-subkey", help = "Falls back to expired encryption subkeys", long_help = "If a certificate has only expired \ encryption-capable subkeys, falls back \ to using the one that expired last", )] pub use_expired_subkey: bool, } #[derive(ValueEnum, Debug, Clone)] pub enum CompressionMode { None, #[cfg(all(unix, not(unix)))] // Bottom, but: `cfg` predicate key cannot be a literal Pad, Zip, Zlib, Bzip2 } sequoia-sq-0.33.0/src/cli/inspect.rs000064400000000000000000000031061046102023000153470ustar 00000000000000//! Command-line parser for `sq inspect`. use clap::Parser; use sequoia_openpgp as openpgp; use openpgp::KeyHandle; use super::types::ClapData; use super::types::FileOrStdin; #[derive(Parser, Debug)] #[clap( name = "inspect", about = "Inspects data, like file(1)", long_about = "Inspects data, like file(1) It is often difficult to tell from cursory inspection using cat(1) or file(1) what kind of OpenPGP one is looking at. This subcommand inspects the data and provides a meaningful human-readable description of it. `sq inspect` respects the reference time set by the top-level `--time` argument. It uses the reference time when determining what binding signatures are active. ", after_help = "EXAMPLES: # Inspects a certificate $ sq inspect juliet.pgp # Inspects a certificate ring $ sq inspect certs.pgp # Inspects a message $ sq inspect message.pgp # Inspects a detached signature $ sq inspect message.sig # Show the certificate as it looked on July 21, 2013 $ sq inspect --time 20130721 cert.pgp ", )] pub struct Command { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( long = "cert", value_name = "FINGERPRINT|KEYID", conflicts_with = "input", help = "Reads the specified certificate from the certificate store", )] pub cert: Vec, #[clap( long = "certifications", help = "Prints third-party certifications", )] pub certifications: bool, } sequoia-sq-0.33.0/src/cli/key.rs000064400000000000000000001160311046102023000144740ustar 00000000000000//! Command-line parser for `sq key`. use std::path::PathBuf; use clap::{ValueEnum, ArgGroup, Args, Parser, Subcommand}; use sequoia_openpgp as openpgp; use openpgp::cert::CipherSuite as SqCipherSuite; use openpgp::KeyHandle; use openpgp::types::ReasonForRevocation as OpenPGPRevocationReason; use crate::cli::KEY_VALIDITY_DURATION; use crate::cli::KEY_VALIDITY_IN_YEARS; use crate::cli::types::ClapData; use crate::cli::types::EncryptPurpose; use crate::cli::types::Expiry; use crate::cli::types::FileOrStdin; use crate::cli::types::FileOrStdout; use crate::cli::types::Time; /// The revocation reason for a certificate or subkey #[derive(ValueEnum, Clone, Debug)] pub enum RevocationReason { Compromised, Superseded, Retired, Unspecified } impl From for OpenPGPRevocationReason { fn from(rr: RevocationReason) -> Self { match rr { RevocationReason::Compromised => OpenPGPRevocationReason::KeyCompromised, RevocationReason::Superseded => OpenPGPRevocationReason::KeySuperseded, RevocationReason::Retired => OpenPGPRevocationReason::KeyRetired, RevocationReason::Unspecified => OpenPGPRevocationReason::Unspecified, } } } /// The revocation reason for a UserID #[derive(ValueEnum, Clone, Debug)] pub enum UseridRevocationReason { Retired, Unspecified } impl From for OpenPGPRevocationReason { fn from(rr: UseridRevocationReason) -> Self { match rr { UseridRevocationReason::Retired => OpenPGPRevocationReason::UIDRetired, UseridRevocationReason::Unspecified => OpenPGPRevocationReason::Unspecified, } } } #[derive(Parser, Debug)] #[clap( name = "key", about = "Manages keys", long_about = "Manages keys We use the term \"key\" to refer to OpenPGP keys that do contain secrets. This subcommand provides primitives to generate and otherwise manipulate keys. Conversely, we use the term \"certificate\", or \"cert\" for short, to refer to OpenPGP keys that do not contain secrets. See `sq keyring` for operations on certificates. ", subcommand_required = true, arg_required_else_help = true, )] pub struct Command { #[clap(subcommand)] pub subcommand: Subcommands, } #[derive(Debug, Subcommand)] pub enum Subcommands { Generate(GenerateCommand), Password(PasswordCommand), Revoke(RevokeCommand), #[clap(subcommand)] Userid(UseridCommand), #[clap(subcommand)] Subkey(SubkeyCommand), ExtractCert(ExtractCertCommand), AttestCertifications(AttestCertificationsCommand), Adopt(AdoptCommand), } #[derive(Debug, Args)] #[clap( about = "Generates a new key", long_about = format!( "Generates a new key Generating a key is the prerequisite to receiving encrypted messages and creating signatures. There are a few parameters to this process, but we provide reasonable defaults for most users. When generating a key, we also generate a revocation certificate. This can be used in case the key is superseded, lost, or compromised. It is a good idea to keep a copy of this in a safe place. After generating a key, use `sq key extract-cert` to get the certificate corresponding to the key. The key must be kept secure, while the certificate should be handed out to correspondents, e.g. by uploading it to a key server. By default a key expires after {} years. Using the `--expiry=` argument specific validity periods may be defined. It allows for providing a point in time for validity to end or a validity duration. `sq key generate` respects the reference time set by the top-level `--time` argument. It sets the creation time of the key, any subkeys, and the binding signatures to the reference time. ", KEY_VALIDITY_IN_YEARS, ), after_help = "EXAMPLES: # First, generate a key $ sq key generate --userid '' \\ --output juliet.key.pgp # Then, extract the certificate for distribution $ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp # Generate a key protecting it with a password $ sq key generate --userid '' --with-password # Generate a key with multiple userids $ sq key generate --userid '' \\ --userid 'Juliet Capulet' # Generate a key whose creation time is June 9, 2011 at midnight UTC $ sq key generate --time 20110609 --userid Noam \\ --output noam.pgp ", )] #[clap(group(ArgGroup::new("cap-sign").args(&["can_sign", "cannot_sign"])))] #[clap(group(ArgGroup::new("cap-authenticate").args(&["can_authenticate", "cannot_authenticate"])))] #[clap(group(ArgGroup::new("cap-encrypt").args(&["can_encrypt", "cannot_encrypt"])))] pub struct GenerateCommand { #[clap( short = 'u', long = "userid", value_name = "EMAIL", help = "Adds a userid to the key" )] pub userid: Vec, #[clap( short = 'c', long = "cipher-suite", value_name = "CIPHER-SUITE", default_value_t = CipherSuite::Cv25519, help = "Selects the cryptographic algorithms for the key", value_enum, )] pub cipher_suite: CipherSuite, #[clap( long = "with-password", help = "Protects the key with a password", )] pub with_password: bool, #[clap( long = "expiry", value_name = "EXPIRY", default_value_t = Expiry::Duration(KEY_VALIDITY_DURATION), help = "Defines EXPIRY for the key as ISO 8601 formatted string or \ custom duration.", long_help = "Defines EXPIRY for the key as ISO 8601 formatted string or \ custom duration. \ If an ISO 8601 formatted string is provided, the validity period \ reaches from the reference time (may be set using `--time`) to \ the provided time. \ Custom durations starting from the reference time may be set using \ `N[ymwds]`, for N years, months, weeks, days, or seconds. \ The special keyword `never` sets an unlimited expiry.", )] pub expiry: Expiry, #[clap( long = "can-sign", help ="Adds a signing-capable subkey (default)", )] pub can_sign: bool, #[clap( long = "cannot-sign", help = "Adds no signing-capable subkey", )] pub cannot_sign: bool, #[clap( long = "can-authenticate", help = "Adds an authentication-capable subkey (default)", )] pub can_authenticate: bool, #[clap( long = "cannot-authenticate", help = "Adds no authentication-capable subkey", )] pub cannot_authenticate: bool, #[clap( long = "can-encrypt", value_name = "PURPOSE", help = "Adds an encryption-capable subkey [default: universal]", long_help = "Adds an encryption-capable subkey. \ Encryption-capable subkeys can be marked as \ suitable for transport encryption, storage \ encryption, or both, i.e., universal. \ [default: universal]", value_enum, )] pub can_encrypt: Option, #[clap( long = "cannot-encrypt", help = "Adds no encryption-capable subkey", )] pub cannot_encrypt: bool, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( long = "rev-cert", value_name = "FILE or -", required_if_eq("output", "-"), help = "Writes the revocation certificate to FILE", long_help = "Writes the revocation certificate to FILE. \ mandatory if OUTFILE is `-`. \ [default: .rev]", )] pub rev_cert: Option } #[derive(ValueEnum, Clone, Debug)] pub enum CipherSuite { Rsa3k, Rsa4k, Cv25519 } impl CipherSuite { /// Return a matching `sequoia_openpgp::cert::CipherSuite` pub fn as_ciphersuite(&self) -> SqCipherSuite { match self { CipherSuite::Rsa3k => SqCipherSuite::RSA3k, CipherSuite::Rsa4k => SqCipherSuite::RSA4k, CipherSuite::Cv25519 => SqCipherSuite::Cv25519, } } } #[derive(Debug, Args)] #[clap( name = "password", about = "Changes password protecting secrets", long_about = "Changes password protecting secrets Secret key material in keys can be protected by a password. This subcommand changes or clears this encryption password. To emit the key with unencrypted secrets, either use `--clear` or supply a zero-length password when prompted for the new password. ", after_help = "EXAMPLES: # First, generate a key $ sq key generate --userid '' \\ --output juliet.key.pgp # Then, encrypt the secrets in the key with a password. $ sq key password < juliet.key.pgp > juliet.encrypted_key.pgp # And remove the password again. $ sq key password --clear < juliet.encrypted_key.pgp \\ > juliet.decrypted_key.pgp ", )] pub struct PasswordCommand { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, /// File containing password to decrypt key /// /// Note that the entire key file will be used as the password, including /// surrounding whitespace like for example a trailing newline #[clap(long)] pub old_password_file: Vec, /// File containing password to encrypt key /// /// Note that the entire key file will be used as the password, including /// surrounding whitespace like for example a trailing newline #[clap(long)] pub new_password_file: Option, #[clap( long = "clear", help = "Emit a key with unencrypted secrets", )] pub clear: bool, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, } #[derive(Debug, Args)] #[clap( about = "Revoke a certificate", long_about = "Revokes a certificate Creates a revocation certificate for the certificate. If `--revocation-file` is provided, then that key is used to create the signature. If that key is different from the certificate being revoked, this creates a third-party revocation. This is normally only useful if the owner of the certificate designated the key to be a designated revoker. If `--revocation-file` is not provided, then the certificate must include a certification-capable key. `sq key revoke` respects the reference time set by the top-level \ `--time` argument. When set, it uses the specified time instead of \ the current time, when determining what keys are valid, and it sets \ the revocation certificate's creation time to the reference time \ instead of the current time. ", )] pub struct RevokeCommand { #[clap( value_name = "FILE", long = "certificate-file", alias = "cert-file", help = "The certificate to revoke", long_help = "Reads the certificate to revoke from FILE or stdin, if omitted. It is \ an error for the file to contain more than one certificate.", )] pub input: Option, #[clap( long = "revocation-file", value_name = "KEY_FILE", help = "Signs the revocation certificate using the key in KEY_FILE", long_help = "Signs the revocation certificate using the key in KEY_FILE. If the key is \ different from the certificate, this creates a third-party revocation. If \ this option is not provided, and the certificate includes secret key material, \ then that key is used to sign the revocation certificate.", )] pub secret_key_file: Option, #[clap( long = "private-key-store", value_name = "KEY_STORE", help = "Provides parameters for private key store", )] pub private_key_store: Option, #[clap( value_name = "REASON", required = true, help = "The reason for the revocation", long_help = "The reason for the revocation. This must be either: `compromised`, `superseded`, `retired`, or `unspecified`: - `compromised` means that the secret key material may have been compromised. Prefer this value if you suspect that the secret key has been leaked. - `superseded` means that the owner of the certificate has replaced it with a new certificate. Prefer `compromised` if the secret key material has been compromised even if the certificate is also being replaced! You should include the fingerprint of the new certificate in the message. - `retired` means that this certificate should not be used anymore, and there is no replacement. This is appropriate when someone leaves an organisation. Prefer `compromised` if the secret key material has been compromised even if the certificate is also being retired! You should include how to contact the owner, or who to contact instead in the message. - `unspecified` means that none of the three other three reasons apply. OpenPGP implementations conservatively treat this type of revocation similar to a compromised key. If the reason happened in the past, you should specify that using the `--time` argument. This allows OpenPGP implementations to more accurately reason about objects whose validity depends on the validity of the certificate.", value_enum, )] pub reason: RevocationReason, #[clap( value_name = "MESSAGE", help = "A short, explanatory text", long_help = "A short, explanatory text that is shown to a viewer of the revocation \ certificate. It explains why the certificate has been revoked. For \ instance, if Alice has created a new key, she would generate a \ `superseded` revocation certificate for her old key, and might include \ the message `I've created a new certificate, FINGERPRINT, please use that in the future.`", )] pub message: String, #[clap( long, value_names = &["NAME", "VALUE"], number_of_values = 2, help = "Adds a notation to the certification.", long_help = "Adds a notation to the certification. \ A user-defined notation's name must be of the form \ `name@a.domain.you.control.org`. If the notation's name starts \ with a `!`, then the notation is marked as being critical. If a \ consumer of a signature doesn't understand a critical notation, \ then it will ignore the signature. The notation is marked as \ being human readable." )] pub notation: Vec, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, } #[derive(Debug, Args)] #[clap( name = "extract-cert", about = "Converts a key to a cert", long_about = "Converts a key to a cert After generating a key, use this command to get the certificate corresponding to the key. The key must be kept secure, while the certificate should be handed out to correspondents, e.g. by uploading it to a key server. ", after_help = "EXAMPLES: # First, generate a key $ sq key generate --userid '' \\ --output juliet.key.pgp # Then, extract the certificate for distribution $ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp ", )] pub struct ExtractCertCommand { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, } #[derive(Debug, Subcommand)] #[clap( name = "userid", about = "Manages User IDs", long_about = "Manages User IDs Add User IDs to, or strip User IDs from a key. ", subcommand_required = true, arg_required_else_help = true, )] pub enum UseridCommand { Add(UseridAddCommand), Revoke(UseridRevokeCommand), Strip(UseridStripCommand), } #[derive(Debug, Args)] #[clap( about = "Adds a User ID", long_about = "Adds a User ID A User ID can contain a name, like `Juliet` or an email address, like ``. Historically, a name and email address were often combined as a single User ID, like `Juliet `. `sq userid add` respects the reference time set by the top-level `--time` argument. It sets the creation time of the User ID's binding signature to the specified time. ", after_help = "EXAMPLES: # First, generate a key: $ sq key generate --userid '' \\ --output juliet.key.pgp # Then, add a User ID: $ sq key userid add --userid Juliet juliet.key.pgp \\ --output juliet-new.key.pgp # Or, add a User ID whose creation time is set to June 28, 2022 at # midnight UTC: $ sq key userid add --userid Juliet --creation-time 20210628 \\ juliet.key.pgp --output juliet-new.key.pgp ", )] pub struct UseridAddCommand { #[clap( help = FileOrStdin::HELP_REQUIRED, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( value_name = "USERID", required = true, help = "User ID to add", )] pub userid: Vec, #[clap( long = "private-key-store", value_name = "KEY_STORE", help = "Provides parameters for private key store", )] pub private_key_store: Option, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, } #[derive(Debug, Args)] #[clap( about = "Revoke a User ID", long_about = "Revokes a User ID Creates a revocation certificate for a User ID. If `--revocation-key` is provided, then that key is used to create \ the signature. If that key is different from the certificate being \ revoked, this creates a third-party revocation. This is normally only \ useful if the owner of the certificate designated the key to be a \ designated revoker. If `--revocation-key` is not provided, then the certificate must \ include a certification-capable key. `sq key userid revoke` respects the reference time set by the top-level \ `--time` argument. When set, it uses the specified time instead of \ the current time, when determining what keys are valid, and it sets \ the revocation certificate's creation time to the reference time \ instead of the current time. ",)] pub struct UseridRevokeCommand { #[clap( value_name = "CERT_FILE", long = "certificate-file", alias = "cert-file", help = "The certificate containing the User ID to revoke", long_help = "Reads the certificate to revoke from CERT_FILE or stdin, \ if omitted. It is an error for the file to contain more than one \ certificate." )] pub input: Option, #[clap( long = "revocation-file", value_name = "KEY_FILE", help = "Signs the revocation certificate using the key in KEY_FILE", long_help = "Signs the revocation certificate using the key in KEY_FILE. If the key is \ different from the certificate, this creates a third-party revocation. If \ this option is not provided, and the certificate includes secret key material, \ then that key is used to sign the revocation certificate.", )] pub secret_key_file: Option, #[clap( long = "private-key-store", value_name = "KEY_STORE", help = "Provides parameters for private key store", )] pub private_key_store: Option, #[clap( value_name = "USERID", help = "The User ID to revoke", long_help = "The User ID to revoke. By default, this must exactly match a \ self-signed User ID. Use `--force` to generate a revocation certificate \ for a User ID, which is not self signed." )] pub userid: String, #[clap( value_enum, value_name = "REASON", help = "The reason for the revocation", long_help = "The reason for the revocation. This must be either: `retired`, or `unspecified`: - `retired` means that this User ID is no longer valid. This is appropriate when someone leaves an organisation, and the organisation does not have their secret key material. For instance, if someone was part of Debian and retires, they would use this to indicate that a Debian-specific User ID is no longer valid. - `unspecified` means that a different reason applies. If the reason happened in the past, you should specify that using the \ `--time` argument. This allows OpenPGP implementations to more accurately reason about objects whose validity depends on the validity \ of a User ID." )] pub reason: UseridRevocationReason, #[clap( value_name = "MESSAGE", help = "A short, explanatory text", long_help = "A short, explanatory text that is shown to a viewer of the revocation \ certificate. It explains why the certificate has been revoked. For \ instance, if Alice has created a new key, she would generate a \ `superseded` revocation certificate for her old key, and might include \ the message `I've created a new certificate, FINGERPRINT, please use that in the future.`", )] pub message: String, #[clap( long, value_names = &["NAME", "VALUE"], number_of_values = 2, help = "Adds a notation to the certification.", long_help = "Adds a notation to the certification. \ A user-defined notation's name must be of the form \ `name@a.domain.you.control.org`. If the notation's name starts \ with a `!`, then the notation is marked as being critical. If a \ consumer of a signature doesn't understand a critical notation, \ then it will ignore the signature. The notation is marked as \ being human readable." )] pub notation: Vec, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, } #[derive(Debug, Args)] #[clap( about = "Strips a User ID", long_about = "Strips a User ID Note that this operation does not reliably remove User IDs from a certificate that has already been disseminated! (OpenPGP software typically appends new information it receives about a certificate to its local copy of that certificate. Systems that have obtained a copy of your certificate with the User ID that you are trying to strip will not drop that User ID from their copy.) In most cases, you will want to use the 'sq key userid revoke' operation instead. That issues a revocation for a User ID, which can be used to mark the User ID as invalidated. However, this operation can be useful in very specific cases, in particular: to remove a mistakenly added User ID before it has been uploaded to key servers or otherwise shared. Stripping a User ID may change how a certificate is interpreted. This is because information about the certificate like algorithm preferences, the primary key's key flags, etc. is stored in the User ID's binding signature. ", after_help = "EXAMPLES: # First, generate a key: $ sq key generate --userid '' \\ --output juliet.key.pgp # Then, strip a User ID: $ sq key userid strip --userid '' \\ --output juliet-new.key.pgp juliet.key.pgp ", )] pub struct UseridStripCommand { #[clap( default_value_t = FileOrStdin::default(), help = FileOrStdin::HELP_OPTIONAL, value_name = FileOrStdin::VALUE_NAME, )] pub input: FileOrStdin, #[clap( default_value_t = FileOrStdout::default(), help = FileOrStdout::HELP_OPTIONAL, long, short, value_name = FileOrStdout::VALUE_NAME, )] pub output: FileOrStdout, #[clap( value_name = "USERID", short, long, help = "User IDs to strip", long_help = "The User IDs to strip. Values must exactly match a \ User ID." )] pub userid: Vec, #[clap( short = 'B', long, help = "Emits binary data", )] pub binary: bool, } #[derive(Debug, Args)] #[clap( name = "adopt", about = "Binds keys from one certificate to another", long_about = "Binds keys from one certificate to another This command allows one to transfer primary keys and subkeys into an existing certificate. Say you want to transition to a new certificate, but have an authentication subkey on your current certificate. You want to keep the authentication subkey because it allows access to SSH servers and updating their configuration is not feasible. ", after_help = "EXAMPLES: # Adopt an subkey into the new cert $ sq key adopt --keyring juliet-old.pgp --key 0123456789ABCDEF \\ juliet-new.pgp ", )] pub struct AdoptCommand { #[clap( short = 'k', long = "key", value_name = "KEY", required(true), help = "Adds the key or subkey KEY to the TARGET-KEY", )] pub key: Vec, #[clap( long = "expire", value_name = "KEY-EXPIRATION-TIME", help = "Makes adopted subkeys expire at the given time", )] pub expire: Option