├── .gitignore ├── .editorconfig ├── appveyor.yml ├── Cargo.toml ├── .package ├── .travis.yml ├── CARETAKERS.md ├── README.md ├── certainly.1.ronn ├── LICENSE ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.yml] 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | global: 3 | PROJECT_NAME: certainly 4 | matrix: 5 | - TARGET: x86_64-pc-windows-msvc 6 | CHANNEL: stable 7 | 8 | # Not MSBuild 9 | build: false 10 | 11 | # Install Rust and Cargo 12 | # (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml) 13 | install: 14 | - curl -sSf -o rustup-init.exe https://win.rustup.rs/ 15 | - rustup-init.exe --default-host %TARGET% --default-toolchain %CHANNEL% -y 16 | - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin 17 | - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin 18 | - rustc -V 19 | - cargo -V 20 | 21 | test_script: 22 | - cargo test --verbose 23 | 24 | before_deploy: 25 | # Generate artifacts for release 26 | - cargo build --release 27 | - mkdir pack 28 | - copy target\release\certainly.exe pack 29 | - copy LICENSE pack\LICENSE.txt 30 | - cd pack 31 | - 7z a ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip * 32 | - appveyor PushArtifact ../%PROJECT_NAME%-%APPVEYOR_REPO_TAG_NAME%-%TARGET%.zip 33 | 34 | deploy: 35 | description: 'Automatically deployed release' 36 | artifact: /.*\.zip/ 37 | provider: GitHub 38 | auth_token: 39 | secure: jP1S47gz9OeAJArE2bpk5UhntrrMtLCVXEThEx+cUTvu48M1xsgF75aIFh4j8mAN 40 | on: 41 | appveyor_repo_tag: true 42 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # Uncomment to work on RSA (nightly only), to make the RSA keygen fast in debug 2 | # cargo-features = ["profile-overrides"] 3 | # [profile.dev.overrides.num-bigint-dig] 4 | # opt-level = 3 5 | 6 | [package] 7 | name = "certainly" 8 | version = "1.8.0" 9 | authors = ["Félix Saparelli "] 10 | description = "The easiest way to create self-signed certificates. Ever." 11 | license = "Artistic-2.0" 12 | edition = "2018" 13 | 14 | homepage = "https://github.com/passcod/certainly" 15 | repository = "https://github.com/passcod/certainly" 16 | keywords = ["ssl", "tls", "certificate", "self-signed"] 17 | categories = ["command-line-utilities", "development-tools"] 18 | readme = "README.md" 19 | 20 | [badges] 21 | appveyor = { repository = "passcod/certainly" } 22 | travis-ci = { repository = "passcod/certainly" } 23 | 24 | [profile.release] 25 | lto = true 26 | 27 | [dependencies] 28 | bit-vec = "0.6.1" 29 | chrono = "0.4.9" 30 | clap = "2.33.0" 31 | gethostname = "0.2.0" 32 | lazy_static = "1.4.0" 33 | nom = "5.0.1" 34 | num-bigint = "=0.2.3" 35 | num-bigint-dig = "=0.4.0" 36 | rand = "0.6.5" 37 | rcgen = { version = "0.8.5", features = ["pem", "x509-parser"] } 38 | ring = { version = "0.16.9" } 39 | rsa = "=0.1.3" 40 | rustls-connector = { version = "0.12.0", features = ["dangerous-configuration"] } 41 | time = "0.1.44" 42 | url = "2.1.0" 43 | x509-parser = "0.7.0" 44 | yasna = { version = "0.3.2", features = ["bit-vec", "num-bigint"] } 45 | -------------------------------------------------------------------------------- /.package: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | tag=$1 4 | target=$2 5 | 6 | if [[ -z "$tag" ]]; then 7 | echo Tag is needed 8 | exit 1 9 | fi 10 | 11 | if [[ -z "$target" ]]; then 12 | echo Target is needed 13 | exit 1 14 | fi 15 | 16 | 17 | cargo build --target $target --release 18 | 19 | build_dir=$(mktemp -d 2>/dev/null || mktemp -d -t tmp) 20 | out_dir=$(pwd) 21 | name="certainly-$tag-$target" 22 | mkdir "$build_dir/$name" 23 | 24 | cp target/$target/release/certainly "$build_dir/$name/" 25 | cp LICENSE "$build_dir/$name/" 26 | ronn --roff --pipe certainly.1.ronn > "$build_dir/$name/certainly.1" 27 | 28 | pushd $build_dir 29 | strip "$name/certainly" 30 | tar cvf "$out_dir/$name.tar" "$name" 31 | popd 32 | xz -f9 "$name.tar" 33 | 34 | if [[ "$target" == *-linux-gnu ]]; then 35 | mkdir -p "$build_dir/deb/$name" 36 | pushd "$build_dir/deb/$name" 37 | 38 | mkdir -p DEBIAN usr/bin usr/share/man/man1 39 | cp "../../$name/certainly" usr/bin/ 40 | cp "../../$name/certainly.1" usr/share/man/man1/ 41 | cat < DEBIAN/control 42 | Package: certainly 43 | Version: ${tag/v/} 44 | Architecture: amd64 45 | Maintainer: Félix Saparelli 46 | Installed-Size: $(du -d1 usr | tail -n1 | cut -d\t -f1) 47 | Homepage: https://github.com/passcod/certainly 48 | Description: Create self-signed certificates with ease. 49 | Creates a self-signed certficate and key with one or more domains associated, for web development use. 50 | CONTROL 51 | cd .. 52 | fakeroot dpkg -b "$name" 53 | mv "certainly-$tag-$target.deb" "$out_dir/" 54 | popd 55 | fi 56 | 57 | rm -rf "$build_dir" 58 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | cache: cargo 3 | dist: trusty 4 | sudo: false 5 | 6 | addons: 7 | apt: 8 | packages: 9 | - fakeroot 10 | 11 | env: 12 | global: 13 | - PROJECT_NAME=certainly 14 | 15 | matrix: 16 | fast_finish: true 17 | include: 18 | # Default test+release version 19 | - os: osx 20 | rust: stable 21 | env: TARGET=x86_64-apple-darwin 22 | - os: linux 23 | rust: stable 24 | env: TARGET=x86_64-unknown-linux-gnu 25 | 26 | # Extra targets for linux only 27 | #- os: linux 28 | # rust: stable 29 | # env: TARGET=i686-unknown-linux-musl 30 | #- os: linux 31 | # rust: stable 32 | # env: TARGET=x86_64-unknown-linux-musl 33 | 34 | before_script: 35 | - rustup target add $TARGET || echo ok 36 | - gem install ronn 37 | 38 | script: 39 | - cargo check --target $TARGET 40 | - cargo build --target $TARGET 41 | - cargo test --target $TARGET 42 | 43 | before_deploy: ./.package $TRAVIS_TAG $TARGET 44 | deploy: 45 | provider: releases 46 | api_key: 47 | secure: uVuIV+zn9iR7nWipZiKt85MOiTZ//vuXLAd2XA/iWv6v+EYAXi80zwb71yfHwPOwWz0w324ZuHDF88Bz+hmGuLChWLKc+8RXLHDsORvVs+oU20H4QfvcgPeUKW1PAzB4niqQ8LbiM6LELqR1f95oK88GHboiBueQ5d6mibUFLIr0OTgEspX4wavGj/pZjUQ8DeVO6Xksoa6ymvCbArmgSE+NIGt3hjGZR93spo8bZfPEguxKQPCoSxknofYZE7FfQY+s4cyzTapf5hXI59vyyFajVRwR8I9GVmasj35/pUA1Eru5WBt5DP7kVwgnRLAEhu6Qs/MuAclW3iCTMlzjdNNyxkRMfPuyL/e1qP2ExKteWuIdZcTxfZG0Yh64a59tE9BfiAQ1Rjvui0NwyL6+W7Dh/0a3Cx3tu6mh3thAXuigXBQS6vBllSccFaC0s2PuT9mYM95nis2JmvaRc9Z4aCyyr2RbXI+gdoC4ogZAz0JfGfIXI31UBX+L/2eIDkeoNBIchcL9vb9ezIAxF5DixE7rirfMb2KF6LBxybWMVprkS/LkQcpf97771D8IYf4wL15otAJzm4UT0qcCGz9VWvU/OWzPiRazbJrDGLxN2VudAaxVgWJizsIwUf4v65pPRDwdR1wQhRuW7Nfr9IkYwe60Zxqs6EXAKNU48PMEI3A= 48 | file_glob: true 49 | file: ${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.* 50 | skip_cleanup: true 51 | on: 52 | repo: passcod/certainly 53 | tags: true 54 | rust: stable 55 | -------------------------------------------------------------------------------- /CARETAKERS.md: -------------------------------------------------------------------------------- 1 | # Caretaker Maintainership 2 | 3 | _(If this file is included in a project, you can find the list of current caretakers at the bottom.)_ 4 | 5 | In a small classical open-source project, maintainers do a lot, and if maintainers don't have time to do a lot, usually the project stalls. 6 | Finding new maintainers is hard because few people actively want to take over all the responsibilities of a project. 7 | There must be a different way. 8 | 9 | With Caretaker Maintainership, "Maintainers" become "Caretakers". 10 | Caretakers' only mandatory responsibility is to grant Releasers commit and publish access to the project. 11 | Caretakers can of course still do other things as they wish. 12 | 13 | Releasers are one of three kinds of contributors to a Caretaker project: 14 | - Reporters are people who report bugs 15 | - Builders write code, docs, make art, proofread, etc, **and open pull requests** 16 | - Releasers do final polish, add to changelogs, etc as needed, and publish new versions. 17 | 18 | You can of course have multiple roles. 19 | A single-person project will have that person do all or almost all roles. 20 | You're also not restricted to just these roles, or to follow them precisely. 21 | Do whatever fits best! 22 | 23 | Someone who wishes to be a Releaser **must** open an issue or contact the Caretakers in some other way and ask, detailing what they want to do. 24 | That can be as limited as "merge this feature" or as open-ended as "work on the project during my free time". 25 | - If accepted, a Caretaker then gives enough rights or permissions to the new Releaser that they may cut new releases of the project on their own. 26 | - If the Releasership is for a limited purpose, the Releaser loses their rights (either relinquishes them on their own or is taken out of permissions by Caretakers) after they've done their bit. 27 | 28 | **Caretaker maintainership is not suitable for commercial, high-stakes, or security projects!** 29 | 30 | Also you may want to use one of the badges below on your readme and/or add the #caretaker tag to your github description so: 31 | - People who want to contribute to Caretaker projects can find them, and 32 | - People who want to *avoid using* Caretaker projects for whatever reason can do that. 33 | 34 | [![Uses Caretaker Maintainership](https://badgen.net/badge/Caretaker/Maintainership%20👥%20/purple)](https://gist.github.com/passcod/7332390db1813f9bccb07e5cf3a9649b) 35 | [![Uses Caretaker Maintainership](https://flat.badgen.net/badge/Caretaker/Maintainership%20👥%20/purple)](https://gist.github.com/passcod/7332390db1813f9bccb07e5cf3a9649b) 36 | 37 | ## Current Caretakers 38 | 39 | - Félix Saparelli, @passcod on github and twitter 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # certainly 2 | 3 | ***DEPRECATED: You should use [step](https://smallstep.com/cli/) instead, a much more powerful, maintained, supported, and yet just as easy to use, certificate utility.*** 4 | 5 | Handy simple tool for common certificate-related operations. 6 | 7 | ```bash 8 | $ certainly test.example.com test2.example.com foo.local 10.0.200.36 9 | Writing test.example.com.key 10 | Writing test.example.com.crt 11 | 12 | $ certainly --inspect test.example.com.crt 13 | [Local] C=ZZ, O=Certainly, OU=test.example.com from kaydel-ko, CN=test.example.com 14 | Issuer: C=ZZ, O=Certainly, OU=test.example.com from kaydel-ko, CN=test.example.com 15 | 16 | Created on: Sun Sep 15 01:30:14 2019 17 | Expires on: Sun Sep 15 01:30:14 2029 18 | 19 | Domains: 20 | DNS: test.example.com 21 | DNS: test2.example.com 22 | DNS: foo.local 23 | IPV4: 10.0.200.36 24 | 25 | To see more: $ openssl x509 -text -in test.example.com.crt 26 | 27 | $ certainly --inspect twitter.com 28 | [Remote] C=US, ST=California, L=San Francisco, O=Twitter, Inc., OU=syd2, CN=twitter.com 29 | Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA 30 | 31 | Chain: 32 | Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 High Assurance Server CA 33 | Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA 34 | 35 | Created on: Sun May 13 00:00:00 2019 36 | Expires on: Sun May 10 12:00:00 2020 37 | 38 | Domains: 39 | DNS: twitter.com 40 | DNS: www.twitter.com 41 | 42 | To see more: $ echo Q | openssl s_client twitter.com:443 43 | ``` 44 | 45 | 46 | ## Install 47 | 48 | ### Binary download (Windows, Linux, macOS) 49 | 50 | Binaries are available [through GitHub Releases](https://github.com/passcod/certainly/releases). 51 | 52 | ### From source 53 | 54 | With Cargo: `cargo install certainly` 55 | 56 | ### From package manager 57 | 58 | #### [Arch Linux (AUR)](https://aur.archlinux.org/packages/certainly-bin) 59 | 60 | yay -S certainly-bin 61 | 62 | #### Debian, Ubuntu (deb) 63 | 64 | Download the deb file from GitHub Releases. 65 | 66 | #### Others 67 | 68 | Accepting contributions for more! 69 | 70 | This project uses [Caretaker Maintainership](./CARETAKERS.md). 71 | 72 | 73 | ## Options 74 | 75 | - `--std` and `--reverse-std` will output both key and certificate to STDOUT instead of writing files. 76 | - `--double-std` will output the key to STDERR and the certificate to STDOUT instead, so redirection can be used to write or pipe files where needed efficiently. Take care of checking the key is actually formatted properly and not an error message though! 77 | 78 | - `--inspect` outputs terse information about the passed certificate file (or url) and exits. 79 | 80 | - `--make-ca` creates a key/certificate pair suitable for issuing instead. Use with `--ca`. 81 | - `--ca NAME` signs a certificate with a CA pair instead of self-signing. Provide only the common filename, without the `.crt` and `.key` extensions. 82 | 83 | - `--client` creates client certificates rather than server ones. 84 | - `--ecdsa` creates p256r1 ECDSA certificates (default). 85 | - `--ed25519` creates ED25519 certificates. 86 | - `--rsa` creates 4096-bit RSA certificates (**not for production use**). 87 | 88 | See [the man page](./certainly.1.ronn) for more. 89 | 90 | 91 | ## See also 92 | 93 | - [mkcert](https://github.com/FiloSottile/mkcert), a tool specifically for local-CA certificate management. 94 | 95 | 96 | ## Etc 97 | 98 | - Copyright © [Félix Saparelli](https://passcod.name). 99 | - Licensed under the [Artistic License 2.0](./LICENSE). 100 | -------------------------------------------------------------------------------- /certainly.1.ronn: -------------------------------------------------------------------------------- 1 | certainly(1) -- create self-signed certificates with ease 2 | ========================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | certainly [`--std` | `--reverse-std` | `--double-std`] [`--ecdsa` | `--ed25519` | `--rsa`] [`--ca` ] [`--client`] [...] 7 | 8 | certainly [`--std` | `--reverse-std` | `--double-std`] [`--ecdsa` | `--ed25519` | `--rsa`] `--make-ca` 9 | 10 | certainly --inspect 11 | 12 | ## DESCRIPTION 13 | 14 | Creates a self-signed certificate and key with one or more domains associated. 15 | 16 | By default, files named after the first domain given are written in the current directory, but flags can be passed to output to standard pipes instead. 17 | 18 | With the `--ca` option, issues a certificate signed by a "CA" instead. The CA certificate/key pair can be created with _certainly_ as well. 19 | 20 | The inspect option instead reads a certificate file (or fetches it from a remote site) and outputs terse information about it: whether it's self-signed, its dates, and the domains it covers. 21 | 22 | Files are written and read in PEM format. On Unix, file are written with 0600 permissions. 23 | 24 | By default, generates ECDSA keys on the P-256 curve. 25 | 26 | ## OPTIONS 27 | 28 | * : 29 | A domain to add to the certificate. The first such domain will also be the certificate's _common name_. IPv4 and v6 addresses are also supported. 30 | 31 | * `--std`: 32 | Outputs first the key then the certificate to STDOUT. 33 | 34 | * `--reverse-std`: 35 | Outputs first the certificated then the key to STDOUT. 36 | 37 | * `--double-std`: 38 | Outputs the key to STDERR, and the certificate to STDOUT. This is useful to write both files to a custom location efficiently, such as: `certainly --double-std domain.test > test.crt 2> test.key`. 39 | 40 | * `--client`: 41 | Creates a client certificate instead of a server certificate. 42 | 43 | * `--ecdsa`: 44 | Generates ECDSA keys (default). Use this option in scripts when you require an ECDSA key as the default may change. 45 | 46 | * `--ed25519`: 47 | Generates ED25519 keys. 48 | 49 | * `--rsa`: 50 | Generates RSA keys. Key length is 4096. This is slow and the RSA implementation has not been audited; do not use for production or security. 51 | 52 | * `--ca` : 53 | Uses the certificate/key pair _.crt_ and _.key_ to sign the created certificate instead of self-signing. 54 | 55 | * `--make-ca` : 56 | Creates a certificate/key pair suitable for issuing instead of a web certificate. 57 | 58 | * `--inspect` : 59 | Reads the (in PEM format), prints some information about it, and exits. Alternatively takes a URL or domain or IP address. 60 | 61 | ## EXAMPLES 62 | 63 | Create a self-signed certificate for test.domain: 64 | 65 | $ certainly test.domain 66 | Writing test.domain.key 67 | Writing test.domain.crt 68 | 69 | Create a self-signed certificate for several domains: 70 | 71 | $ certainly test.domain test.place test.pizza 72 | Writing test.domain.key 73 | Writing test.domain.crt 74 | 75 | Output a new key and certificate: 76 | 77 | $ certainly --std test.app 78 | -----BEGIN PRIVATE KEY----- 79 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg2yn3kvq3WzJv8F+V 80 | BxZ+HCo73JQ7ABUrDDvBpUpexlehRANCAAR4gwky7IoIAdKwd3jSs7/VfrR0AsN9 81 | LwYp0O988ZWGYhN+Dko7KuSrtYJ/kVBs+5iQnH2uK2OXKqpv5T8X/pUR 82 | -----END PRIVATE KEY----- 83 | -----BEGIN CERTIFICATE----- 84 | MIICPzCCAeWgAwIBAgIUPQ+Sy8RPt2gt5jW5wS6FRIydakkwCgYIKoZIzj0EAwQw 85 | QTELMAkGA1UEBhMCWloxCzAJBgNVBAgMAkFBMRIwEAYDVQQKDAlDZXJ0YWlubHkx 86 | ETAPBgNVBAMMCHRlc3QuYXBwMB4XDTE4MDkwNTIxMTM1N1oXDTI4MDkwMjIxMTM1 87 | N1owQTELMAkGA1UEBhMCWloxCzAJBgNVBAgMAkFBMRIwEAYDVQQKDAlDZXJ0YWlu 88 | bHkxETAPBgNVBAMMCHRlc3QuYXBwMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE 89 | eIMJMuyKCAHSsHd40rO/1X60dALDfS8GKdDvfPGVhmITfg5KOyrkq7WCf5FQbPuY 90 | kJx9ritjlyqqb+U/F/6VEaOBujCBtzAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIF 91 | 4DAdBgNVHQ4EFgQU2jmj7l5rSw0yVb/vlWAYkK/YBwkwZgYDVR0jBF8wXaFFpEMw 92 | QTELMAkGA1UEBhMCWloxCzAJBgNVBAgMAkFBMRIwEAYDVQQKDAlDZXJ0YWlubHkx 93 | ETAPBgNVBAMMCHRlc3QuYXBwghQ9D5LLxE+3aC3mNbnBLoVEjJ1qSTATBgNVHREE 94 | DDAKggh0ZXN0LmFwcDAKBggqhkjOPQQDBANIADBFAiBbaxLKxwnSWZy/3VzOOASs 95 | 9lz8YQWzc7NCESXzZTAHuAIhAOFKSelBXJEBsNLCtS86JNEvya+3XPWAL9R+O1jp 96 | WMna 97 | -----END CERTIFICATE----- 98 | 99 | Write a key and certificate to custom locations: 100 | 101 | $ certainly --double-std test.space 2> moon-key.pem > moon-cert.pem 102 | 103 | Show some information about a certificate: 104 | 105 | $ certainly --inspect test.ninja.crt 106 | [Local] C=ZZ, O=Certainly, OU=test.ninja from kaydel-ko, CN=test.ninja 107 | Issuer: C=ZZ, O=Certainly, OU=test.ninja from kaydel-ko, CN=test.ninja 108 | 109 | Created on: Sun Sep 15 01:15:29 2019 110 | Expires on: Sun Sep 15 01:15:29 2029 111 | 112 | Domains: 113 | DNS: test.ninja 114 | DNS: test.green 115 | EMAIL: test@red.link 116 | DNS: test.technology 117 | DNS: rofl.lmao.lol 118 | IPV4: 1.2.3.4 119 | 120 | To see more: $ openssl x509 -text -in test.ninja.crt 121 | 122 | Show some information about google's certificate: 123 | 124 | $ certainly --inspect google.com 125 | [Remote] C=US, ST=California, L=Mountain View, O=Google LLC, CN=*.google.com 126 | Issuer: C=US, O=Google Trust Services, CN=GTS CA 1O1 127 | 128 | Chain: 129 | Subject: C=US, O=Google Trust Services, CN=GTS CA 1O1 130 | Issuer: OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign 131 | 132 | Created on: Sun Aug 23 10:28:57 2019 133 | Expires on: Sun Nov 21 10:28:57 2019 134 | 135 | Domains: 136 | DNS: *.google.com 137 | DNS: *.android.com 138 | DNS: *.appengine.google.com 139 | DNS: *.cloud.google.com 140 | DNS: *.crowdsource.google.com 141 | DNS: *.g.co 142 | (... many more domains ...) 143 | 144 | To see more: $ echo Q | openssl s_client google.com:443 145 | 146 | Create a CA pair and sign a new certificate: 147 | 148 | $ certainly --make-ca ca.test 149 | Writing ca.test.key 150 | Writing ca.test.crt 151 | 152 | $ certainly --ca ca.test test.party 153 | Writing test.party.key 154 | Writing test.party.crt 155 | 156 | $ certainly --inspect test.party.crt 157 | [Local] C=ZZ, O=Certainly, OU=test.party from kaydel-ko, CN=test.party 158 | Issuer: C=ZZ, O=Certainly, OU=ca.test from kaydel-ko, CN=ca.test 159 | 160 | Created on: Sun Sep 15 01:20:44 2019 161 | Expires on: Sun Sep 15 01:20:44 2029 162 | 163 | Domains: 164 | DNS: test.party 165 | 166 | To see more: $ openssl x509 -text -in test.party.crt 167 | 168 | ## DETAILS 169 | 170 | Certificates are generated with a common subject of: 171 | 172 | * C (Country): `ZZ` 173 | 174 | * ST (State): `AA` 175 | 176 | * O (Organisation): `Certainly` 177 | 178 | They use elliptical curve cryptography using `prime256v1` hashed with `SHA-256` by default. 179 | 180 | This generates small files (easier to inspect and manipulate) and uses algorithms that are well supported by modern tools (browsers, servers, etc) while being up-to-date with security best practices. 181 | 182 | In some legacy cases, should you absolutely need to, the `--rsa` flag instead uses 4096-bit RSA keys. 183 | 184 | ED25519 keys are also available with the `--ed25519` flag, and produce even smaller keys, but such keys are not well supported by tools at time of writing. 185 | 186 | ## ENVIRONMENT VARIABLES 187 | 188 | The distinguished name details can be controlled using the following variables: 189 | 190 | * `CERTAINLY_C` 191 | * `CERTAINLY_O` 192 | * `CERTAINLY_OU` 193 | 194 | ## AUTHOR 195 | 196 | Félix Saparelli 197 | 198 | Licensed under the _Artistic License 2.0_. 199 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2018 Félix Saparelli 2 | Any action relating to this license may only be brought in New Zealand. 3 | 4 | 5 | The Artistic License 2.0 6 | 7 | Copyright (c) 2000-2006, The Perl Foundation. 8 | 9 | Everyone is permitted to copy and distribute verbatim copies of this license 10 | document, but changing it is not allowed. 11 | 12 | Preamble 13 | 14 | This license establishes the terms under which a given free software Package 15 | may be copied, modified, distributed, and/or redistributed. The intent is that 16 | the Copyright Holder maintains some artistic control over the development of 17 | that Package while still keeping the Package available as open source and free 18 | software. 19 | 20 | You are always permitted to make arrangements wholly outside of this license 21 | directly with the Copyright Holder of a given Package. If the terms of this 22 | license do not permit the full use that you propose to make of the Package, you 23 | should contact the Copyright Holder and seek a different licensing arrangement. 24 | 25 | Definitions 26 | 27 | "Copyright Holder" means the individual(s) or organization(s) named in the 28 | copyright notice for the entire Package. 29 | 30 | "Contributor" means any party that has contributed code or other material 31 | to the Package, in accordance with the Copyright Holder's procedures. 32 | 33 | "You" and "your" means any person who would like to copy, distribute, or 34 | modify the Package. 35 | 36 | "Package" means the collection of files distributed by the Copyright 37 | Holder, and derivatives of that collection and/or of those files. A given 38 | Package may consist of either the Standard Version, or a Modified Version. 39 | 40 | "Distribute" means providing a copy of the Package or making it accessible 41 | to anyone else, or in the case of a company or organization, to others 42 | outside of your company or organization. 43 | 44 | "Distributor Fee" means any fee that you charge for Distributing this 45 | Package or providing support for this Package to another party. It does 46 | not mean licensing fees. 47 | 48 | "Standard Version" refers to the Package if it has not been modified, or 49 | has been modified only in ways explicitly requested by the Copyright 50 | Holder. 51 | 52 | "Modified Version" means the Package, if it has been changed, and such 53 | changes were not explicitly requested by the Copyright Holder. 54 | 55 | "Original License" means this Artistic License as Distributed with the 56 | Standard Version of the Package, in its current version or as it may be 57 | modified by The Perl Foundation in the future. 58 | 59 | "Source" form means the source code, documentation source, and 60 | configuration files for the Package. 61 | 62 | "Compiled" form means the compiled bytecode, object code, binary, or any 63 | other form resulting from mechanical transformation or translation of the 64 | Source form. 65 | 66 | 67 | Permission for Use and Modification Without Distribution 68 | 69 | (1) You are permitted to use the Standard Version and create and use Modified 70 | Versions for any purpose without restriction, provided that you do not 71 | Distribute the Modified Version. 72 | 73 | 74 | Permissions for Redistribution of the Standard Version 75 | 76 | (2) You may Distribute verbatim copies of the Source form of the Standard 77 | Version of this Package in any medium without restriction, either gratis or for 78 | a Distributor Fee, provided that you duplicate all of the original copyright 79 | notices and associated disclaimers. At your discretion, such verbatim copies 80 | may or may not include a Compiled form of the Package. 81 | 82 | (3) You may apply any bug fixes, portability changes, and other modifications 83 | made available from the Copyright Holder. The resulting Package will still be 84 | considered the Standard Version, and as such will be subject to the Original 85 | License. 86 | 87 | 88 | Distribution of Modified Versions of the Package as Source 89 | 90 | (4) You may Distribute your Modified Version as Source (either gratis or for a 91 | Distributor Fee, and with or without a Compiled form of the Modified Version) 92 | provided that you clearly document how it differs from the Standard Version, 93 | including, but not limited to, documenting any non-standard features, 94 | executables, or modules, and provided that you do at least ONE of the 95 | following: 96 | 97 | (a) make the Modified Version available to the Copyright Holder of the 98 | Standard Version, under the Original License, so that the Copyright Holder 99 | may include your modifications in the Standard Version. 100 | 101 | (b) ensure that 102 | installation of your Modified Version does not prevent the user installing 103 | or running the Standard Version. In addition, the Modified Version must 104 | bear a name that is different from the name of the Standard Version. 105 | 106 | (c) allow anyone who receives a copy of the Modified Version to make the 107 | Source form of the Modified Version available to others under 108 | 109 | (i) the Original License or 110 | 111 | (ii) a license that permits the licensee to freely copy, modify and 112 | redistribute the Modified Version using the same licensing terms that 113 | apply to the copy that the licensee 114 | received, and requires that the Source form of the Modified Version, 115 | and of any works derived from it, be made freely available in that 116 | license fees are prohibited but Distributor Fees are allowed. 117 | 118 | 119 | Distribution of Compiled Forms of the Standard Version or Modified Versions 120 | without the Source 121 | 122 | (5) You may Distribute Compiled forms of the Standard Version without the 123 | Source, provided that you include complete instructions on how to get the 124 | Source of the Standard Version. Such instructions must be valid at the time of 125 | your distribution. If these instructions, at any time while you are carrying 126 | out such distribution, become invalid, you must provide new instructions on 127 | demand or cease further distribution. If you provide valid instructions or 128 | cease distribution within thirty days after you become aware that the 129 | instructions are invalid, then you do not forfeit any of your rights under this 130 | license. 131 | 132 | (6) You may Distribute a Modified Version in Compiled form without the Source, 133 | provided that you comply with Section 4 with respect to the Source of the 134 | Modified Version. 135 | 136 | 137 | Aggregating or Linking the Package 138 | 139 | (7) You may aggregate the Package (either the Standard Version or Modified 140 | Version) with other packages and Distribute the resulting aggregation provided 141 | that you do not charge a licensing fee for the Package. Distributor Fees are 142 | permitted, and licensing fees for other components in the aggregation are 143 | permitted. The terms of this license apply to the use and Distribution of the 144 | Standard or Modified Versions as included in the aggregation. 145 | 146 | (8) You are permitted to link Modified and Standard Versions with other works, 147 | to embed the Package in a larger work of your own, or to build stand-alone 148 | binary or bytecode versions of applications that include the Package, and 149 | Distribute the result without restriction, provided the result does not expose 150 | a direct interface to the Package. 151 | 152 | 153 | Items That are Not Considered Part of a Modified Version 154 | 155 | (9) Works (including, but not limited to, modules and scripts) that merely 156 | extend or make use of the Package, do not, by themselves, cause the Package to 157 | be a Modified Version. In addition, such works are not considered parts of the 158 | Package itself, and are not subject to the terms of this license. 159 | 160 | 161 | General Provisions 162 | 163 | (10) Any use, modification, and distribution of the Standard or Modified 164 | Versions is governed by this Artistic License. By using, modifying or 165 | distributing the Package, you accept this license. Do not use, modify, or 166 | distribute the Package, if you do not accept this license. 167 | 168 | (11) If your Modified Version has been derived from a Modified Version made by 169 | someone other than you, you are nevertheless required to ensure that your 170 | Modified Version complies with the requirements of this license. 171 | 172 | (12) This license does not grant you the right to use any trademark, service 173 | mark, tradename, or logo of the Copyright Holder. 174 | 175 | (13) This license includes the non-exclusive, worldwide, free-of-charge patent 176 | license to make, have made, use, offer to sell, sell, import and otherwise 177 | transfer the Package with respect to any patent claims licensable by the 178 | Copyright Holder that are necessarily infringed by the Package. If you 179 | institute patent litigation (including a cross-claim or counterclaim) against 180 | any party alleging that the Package constitutes direct or contributory patent 181 | infringement, then this Artistic License to you shall terminate on the date 182 | that such litigation is filed. 183 | 184 | (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER 185 | AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE 186 | IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 187 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. 188 | UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR 189 | ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY 190 | OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 191 | DAMAGE. 192 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::similar_names)] 2 | 3 | use chrono::{format::ParseError as ChronoParseError, Utc}; 4 | use clap::{App, Arg, ArgGroup}; 5 | use nom::Err as NomErr; 6 | use rcgen::{ 7 | Certificate, CertificateParams, CustomExtension, DistinguishedName, KeyPair, RcgenError, 8 | SignatureAlgorithm, 9 | }; 10 | use rsa::errors::Error as RsaError; 11 | use rustls_connector::{rustls, webpki, HandshakeError, RustlsConnector}; 12 | use std::fs::{File, OpenOptions}; 13 | use std::io::{Read, Write}; 14 | use std::net::TcpStream; 15 | use std::{io, path::PathBuf}; 16 | use time::Tm; 17 | use url::ParseError as UrlParseError; 18 | use x509_parser::{ 19 | error::{PEMError, X509Error}, 20 | parse_x509_der, 21 | pem::pem_to_der, 22 | X509Certificate, 23 | }; 24 | 25 | #[derive(Debug)] 26 | pub(crate) enum Ernum { 27 | Chrono(ChronoParseError), 28 | Io(io::Error), 29 | Rcgen(RcgenError), 30 | Tls(Box>), 31 | Url(UrlParseError), 32 | X509(NomErr), 33 | Pem(NomErr), 34 | Rsa(RsaError), 35 | Other(String), 36 | } 37 | 38 | impl From for Ernum { 39 | fn from(err: io::Error) -> Self { 40 | Ernum::Io(err) 41 | } 42 | } 43 | 44 | impl From for Ernum { 45 | fn from(err: RcgenError) -> Self { 46 | Ernum::Rcgen(err) 47 | } 48 | } 49 | 50 | impl From> for Ernum { 51 | fn from(err: HandshakeError) -> Self { 52 | Ernum::Tls(Box::new(err)) 53 | } 54 | } 55 | 56 | impl From for Ernum { 57 | fn from(err: ChronoParseError) -> Self { 58 | Ernum::Chrono(err) 59 | } 60 | } 61 | 62 | impl From> for Ernum { 63 | fn from(err: NomErr) -> Self { 64 | Ernum::X509(err) 65 | } 66 | } 67 | 68 | impl From> for Ernum { 69 | fn from(err: NomErr) -> Self { 70 | Ernum::Pem(err) 71 | } 72 | } 73 | 74 | impl From for Ernum { 75 | fn from(err: UrlParseError) -> Self { 76 | Ernum::Url(err) 77 | } 78 | } 79 | 80 | impl From for Ernum { 81 | fn from(err: RsaError) -> Self { 82 | Ernum::Rsa(err) 83 | } 84 | } 85 | 86 | impl From<&'static str> for Ernum { 87 | fn from(err: &str) -> Self { 88 | Ernum::Other(err.into()) 89 | } 90 | } 91 | 92 | const SOURCES: (&str, &str) = (include_str!("../Cargo.toml"), include_str!("main.rs")); 93 | 94 | fn main() -> Result<(), Ernum> { 95 | let args = App::new(env!("CARGO_PKG_NAME")) 96 | .version(env!("CARGO_PKG_VERSION")) 97 | .author(env!("CARGO_PKG_HOMEPAGE")) 98 | .about(env!("CARGO_PKG_DESCRIPTION")) 99 | .arg( 100 | Arg::with_name("source") 101 | .long("source") 102 | .help("Show the source!"), 103 | ) 104 | .arg( 105 | Arg::with_name("inspect") 106 | .long("inspect") 107 | .value_name("CERTIFICATE") 108 | .help("Show information about a certificate"), 109 | ) 110 | .arg( 111 | Arg::with_name("make-ca") 112 | .long("make-ca") 113 | .value_name("NAME") 114 | .help("Create a CA cert and key suitable for signing"), 115 | ) 116 | .arg( 117 | Arg::with_name("client") 118 | .long("client") 119 | .help("Create a client certificate instead of a server one"), 120 | ) 121 | .arg( 122 | Arg::with_name("ca") 123 | .long("ca") 124 | .value_name("NAME") 125 | .help("Issue a certificate using a CA cert and key"), 126 | ) 127 | .arg( 128 | Arg::with_name("std") 129 | .long("std") 130 | .help("Output to stdout instead of writing files"), 131 | ) 132 | .arg( 133 | Arg::with_name("reverse-std") 134 | .long("reverse-std") 135 | .help("Output to stdout instead of writing files, with the key last"), 136 | ) 137 | .arg( 138 | Arg::with_name("double-std") 139 | .long("double-std") 140 | .help("Output the key to stderr and the cert to stdout"), 141 | ) 142 | .arg( 143 | Arg::with_name("DOMAIN") 144 | .multiple(true) 145 | .help("Every domain or IP this certificate should support"), 146 | ) 147 | .arg( 148 | Arg::with_name("ecdsa") 149 | .long("ecdsa") 150 | .help("Create an ECDSA P256r1 key and certificate (default)"), 151 | ) 152 | .arg( 153 | Arg::with_name("ed25519") 154 | .long("ed25519") 155 | .help("Create an ED25519 key and certificate"), 156 | ) 157 | .arg( 158 | Arg::with_name("rsa") 159 | .long("rsa") 160 | .help("Create an RSA 4096-bit key and certificate"), 161 | ) 162 | .group(ArgGroup::with_name("algo").args(&["ecdsa", "ed25519", "rsa"])) 163 | .get_matches(); 164 | 165 | if args.is_present("source") { 166 | println!( 167 | "// Cargo.toml\n{}\n\n// src/main.rs\n{}", 168 | SOURCES.0, SOURCES.1 169 | ); 170 | 171 | return Ok(()); 172 | } 173 | 174 | if args.is_present("inspect") { 175 | return inspect(args.value_of("inspect").unwrap().into()); 176 | } 177 | 178 | if !(args.is_present("DOMAIN") || args.is_present("make-ca")) { 179 | eprintln!("{}", args.usage()); 180 | std::process::exit(2); 181 | } 182 | 183 | let algo = if args.is_present("rsa") { 184 | Algo::Rsa 185 | } else if args.is_present("ed25519") { 186 | Algo::Ed 187 | } else { 188 | Algo::Ec 189 | }; 190 | 191 | let (name, cert, ca) = if args.is_present("make-ca") { 192 | let name: &str = args.value_of("make-ca").unwrap(); 193 | let cert = makeca(name, algo)?; 194 | (name.into(), cert, None) 195 | } else { 196 | let doms: Vec<&str> = args.values_of("DOMAIN").unwrap().collect(); 197 | 198 | if args.is_present("ca") { 199 | let caname = args.value_of("ca").unwrap(); 200 | let cakey = load_key(format!("{}.key", caname).into())?; 201 | let cacrt = load_cert(format!("{}.crt", caname).into(), cakey)?; 202 | let (n, c) = create(&doms, Some(&cacrt), args.is_present("client"), algo)?; 203 | (n, c, Some(cacrt)) 204 | } else { 205 | let (n, c) = create(&doms, None, args.is_present("client"), algo)?; 206 | (n, c, None) 207 | } 208 | }; 209 | 210 | let key = cert.get_key_pair().serialize_pem(); 211 | let keyb = key.as_bytes(); 212 | let cert = if let Some(ref c) = ca { 213 | cert.serialize_pem_with_signer(c) 214 | } else { 215 | cert.serialize_pem() 216 | }?; 217 | let certb = cert.as_bytes(); 218 | 219 | if args.is_present("double-std") { 220 | io::stderr().write_all(keyb)?; 221 | io::stdout().write_all(certb)?; 222 | } else if args.is_present("reverse-std") { 223 | io::stdout().write_all(certb)?; 224 | io::stdout().write_all(keyb)?; 225 | } else if args.is_present("std") { 226 | io::stdout().write_all(keyb)?; 227 | io::stdout().write_all(certb)?; 228 | } else { 229 | #[cfg(unix)] 230 | use std::os::unix::fs::OpenOptionsExt; 231 | 232 | let keyname = format!("{}.key", name); 233 | let crtname = format!("{}.crt", name); 234 | 235 | let mut fs = OpenOptions::new(); 236 | fs.write(true).create(true).truncate(true); 237 | 238 | #[cfg(unix)] 239 | fs.mode(0o600); 240 | 241 | eprintln!("Writing {}", keyname); 242 | let mut keyfile = fs.open(keyname)?; 243 | keyfile.write_all(keyb)?; 244 | 245 | eprintln!("Writing {}", crtname); 246 | let mut crtfile = fs.open(crtname)?; 247 | crtfile.write_all(certb)?; 248 | } 249 | 250 | Ok(()) 251 | } 252 | 253 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 254 | enum Algo { 255 | Ec, 256 | Ed, 257 | Rsa, 258 | } 259 | 260 | const RSA_BITS: usize = 4096; 261 | const OID_RSA_ENCRYPTION: &[u64] = &[1, 2, 840, 113_549, 1, 1, 1]; 262 | 263 | impl Algo { 264 | fn rsa_key() -> Result { 265 | use num_bigint::{BigInt, BigUint}; 266 | use num_bigint_dig::{BigUint as BigUintDig, ModInverse}; 267 | use rand::rngs::OsRng; 268 | use rsa::{PublicKey, RSAPrivateKey}; 269 | use std::convert::TryFrom; 270 | 271 | let mut rng = OsRng::new().expect("no secure randomness available"); 272 | let key = RSAPrivateKey::new(&mut rng, RSA_BITS)?; 273 | 274 | let modulus = key.n(); 275 | let public_exponent = key.e(); 276 | let private_exponent = key.d(); 277 | let first_prime = &key.primes()[0]; 278 | let second_prime = &key.primes()[1]; 279 | let first_exponent = private_exponent % (first_prime - &BigUintDig::from(1_u8)); 280 | let second_exponent = private_exponent % (second_prime - &BigUintDig::from(1_u8)); 281 | let coefficient = second_prime.mod_inverse(first_prime).unwrap(); 282 | 283 | let modulus = BigUint::from_bytes_le(&modulus.to_bytes_le()); 284 | let public_exponent = BigUint::from_bytes_le(&public_exponent.to_bytes_le()); 285 | let private_exponent = BigUint::from_bytes_le(&private_exponent.to_bytes_le()); 286 | let first_prime = BigUint::from_bytes_le(&first_prime.to_bytes_le()); 287 | let second_prime = BigUint::from_bytes_le(&second_prime.to_bytes_le()); 288 | let first_exponent = BigUint::from_bytes_le(&first_exponent.to_bytes_le()); 289 | let second_exponent = BigUint::from_bytes_le(&second_exponent.to_bytes_le()); 290 | let coefficient = BigInt::from_signed_bytes_le(&coefficient.to_signed_bytes_le()); 291 | 292 | let keyder = yasna::construct_der(|writer| { 293 | writer.write_sequence(|writer| { 294 | writer.next().write_u8(0); 295 | writer.next().write_biguint(&modulus); 296 | writer.next().write_biguint(&public_exponent); 297 | writer.next().write_biguint(&private_exponent); 298 | writer.next().write_biguint(&first_prime); 299 | writer.next().write_biguint(&second_prime); 300 | writer.next().write_biguint(&first_exponent); 301 | writer.next().write_biguint(&second_exponent); 302 | writer.next().write_bigint(&coefficient); 303 | }) 304 | }); 305 | 306 | let pk8 = yasna::construct_der(|writer| { 307 | writer.write_sequence(|writer| { 308 | writer.next().write_u8(0); 309 | writer.next().write_sequence(|writer| { 310 | writer.next().write_oid(&OID_RSA_ENCRYPTION.to_vec().into()); 311 | writer.next().write_null(); 312 | }); 313 | writer.next().write_bytes(&keyder); 314 | }) 315 | }); 316 | 317 | KeyPair::try_from(pk8.as_slice()).map_err(Into::into) 318 | } 319 | 320 | pub fn key(self) -> Result { 321 | match self { 322 | Algo::Ec => KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256).map_err(Into::into), 323 | Algo::Ed => KeyPair::generate(&rcgen::PKCS_ED25519).map_err(Into::into), 324 | Algo::Rsa => Self::rsa_key(), 325 | } 326 | } 327 | 328 | pub fn rcgen(self) -> &'static SignatureAlgorithm { 329 | match self { 330 | Algo::Ec => &rcgen::PKCS_ECDSA_P256_SHA256, 331 | Algo::Ed => &rcgen::PKCS_ED25519, 332 | Algo::Rsa => &rcgen::PKCS_RSA_SHA256, 333 | } 334 | } 335 | } 336 | 337 | lazy_static::lazy_static! { 338 | static ref HOSTNAME: std::ffi::OsString = gethostname::gethostname(); 339 | } 340 | 341 | const OID_ORG_UNIT: &[u64] = &[2, 5, 4, 11]; 342 | 343 | fn distinguished(name: &str) -> DistinguishedName { 344 | use rcgen::DnType; 345 | let mut dn = DistinguishedName::new(); 346 | dn.push( 347 | DnType::CountryName, 348 | std::env::var("CERTAINLY_C").unwrap_or_else(|_| "ZZ".into()), 349 | ); 350 | dn.push( 351 | DnType::OrganizationName, 352 | std::env::var("CERTAINLY_O").unwrap_or_else(|_| "Certainly".into()), 353 | ); 354 | dn.push( 355 | DnType::from_oid(OID_ORG_UNIT), 356 | std::env::var("CERTAINLY_OU") 357 | .unwrap_or_else(|_| format!("{} from {}", name, HOSTNAME.to_string_lossy())), 358 | ); 359 | dn.push(DnType::CommonName, name); 360 | dn 361 | } 362 | 363 | fn base_cert(name: &str, algo: Algo) -> Result { 364 | use chrono::Datelike; 365 | use rand::Rng; 366 | 367 | let now = Utc::now(); 368 | let mut params = CertificateParams::default(); 369 | params.alg = algo.rcgen(); 370 | params.serial_number = Some(rand::thread_rng().gen()); 371 | params.not_after = now 372 | .with_year(now.year() + 10) 373 | .expect("Ten years in the future doesn't exist according to Chrono. Not a certainly bug."); 374 | params.not_before = now; 375 | params.distinguished_name = distinguished(name); 376 | params.key_pair = Some(algo.key()?); 377 | Ok(params) 378 | } 379 | 380 | const OID_KEY_USAGE: &[u64] = &[2, 5, 29, 15]; 381 | 382 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 383 | enum Usage { 384 | None, 385 | Ca, 386 | Cert, 387 | } 388 | 389 | const KEY_USAGE: &[Usage] = &[ 390 | Usage::Cert, // digitalSignature 391 | Usage::Cert, // nonRepudiation/contentCommitment 392 | Usage::Cert, // keyEncipherment 393 | Usage::None, 394 | Usage::None, 395 | Usage::Ca, // keyCertSign 396 | Usage::Ca, // cRLSign 397 | Usage::None, 398 | Usage::None, 399 | ]; 400 | 401 | fn key_usage(ca: bool) -> CustomExtension { 402 | let der = yasna::construct_der(|writer| { 403 | writer.write_bitvec( 404 | &KEY_USAGE 405 | .iter() 406 | .map(|u| *u == if ca { Usage::Ca } else { Usage::Cert }) 407 | .collect(), 408 | ); 409 | }); 410 | 411 | let mut key_usage = CustomExtension::from_oid_content(OID_KEY_USAGE, der); 412 | key_usage.set_criticality(true); 413 | key_usage 414 | } 415 | 416 | fn makeca(name: &str, algo: Algo) -> Result { 417 | use rcgen::{BasicConstraints, IsCa}; 418 | 419 | let mut params = base_cert(name, algo)?; 420 | params.is_ca = IsCa::Ca(BasicConstraints::Constrained(16)); 421 | params.custom_extensions.push(key_usage(true)); 422 | 423 | Certificate::from_params(params).map_err(Into::into) 424 | } 425 | 426 | const OID_BASIC: &[u64] = &[2, 5, 29, 19]; 427 | 428 | fn not_ca() -> CustomExtension { 429 | let der = yasna::construct_der(|writer| { 430 | writer.write_sequence(|writer| { 431 | writer.next().write_bool(false); 432 | }); 433 | }); 434 | 435 | CustomExtension::from_oid_content(OID_BASIC, der) 436 | } 437 | 438 | fn create( 439 | domains: &[&str], 440 | _ca: Option<&Certificate>, 441 | is_client: bool, 442 | algo: Algo, 443 | ) -> Result<(String, Certificate), Ernum> { 444 | use rcgen::{ExtendedKeyUsagePurpose, SanType}; 445 | use std::net::IpAddr; 446 | use std::str::FromStr; 447 | 448 | let name = domains[0]; 449 | let mut params = base_cert(name, algo)?; 450 | 451 | params.custom_extensions.push(not_ca()); 452 | params.custom_extensions.push(key_usage(false)); 453 | params.extended_key_usages.push(if is_client { 454 | ExtendedKeyUsagePurpose::ClientAuth 455 | } else { 456 | ExtendedKeyUsagePurpose::ServerAuth 457 | }); 458 | params.subject_alt_names = domains 459 | .iter() 460 | .map(|dom| { 461 | if let Ok(ip) = IpAddr::from_str(dom) { 462 | SanType::IpAddress(ip) 463 | } else { 464 | SanType::DnsName(dom.to_string()) 465 | } 466 | }) 467 | .collect(); 468 | 469 | Ok((name.into(), Certificate::from_params(params)?)) 470 | } 471 | 472 | fn load_cert(filepath: PathBuf, key: KeyPair) -> Result { 473 | let mut file = File::open(filepath)?; 474 | let mut buf = String::new(); 475 | file.read_to_string(&mut buf)?; 476 | 477 | let params = CertificateParams::from_ca_cert_pem(&buf, key)?; 478 | Certificate::from_params(params).map_err(Into::into) 479 | } 480 | 481 | fn load_key(filepath: PathBuf) -> Result { 482 | let mut file = File::open(filepath)?; 483 | let mut buf = String::new(); 484 | file.read_to_string(&mut buf)?; 485 | KeyPair::from_pem(&buf).map_err(Into::into) 486 | } 487 | 488 | pub struct NoCertificateVerification; 489 | 490 | impl rustls::ServerCertVerifier for NoCertificateVerification { 491 | fn verify_server_cert( 492 | &self, 493 | _roots: &rustls::RootCertStore, 494 | _presented_certs: &[rustls::Certificate], 495 | _dns_name: webpki::DNSNameRef<'_>, 496 | _ocsp: &[u8], 497 | ) -> Result { 498 | Ok(rustls::ServerCertVerified::assertion()) 499 | } 500 | } 501 | 502 | #[derive(Clone, Debug, Eq, PartialEq)] 503 | struct ParsedCert { 504 | issuer: String, 505 | subject: String, 506 | not_before: Tm, 507 | not_after: Tm, 508 | names: Vec, 509 | } 510 | 511 | #[derive(Clone, Debug, Eq, PartialEq)] 512 | enum GeneralName { 513 | Email(String), 514 | Dns(String), 515 | Ip(Vec), 516 | Uri(String), 517 | Unknown, 518 | } 519 | 520 | const OID_SUBJECT_ALT_NAME: &str = "2.5.29.17"; 521 | 522 | impl ParsedCert { 523 | fn parse(cert: X509Certificate<'_>) -> Self { 524 | let tbs = cert.tbs_certificate; 525 | 526 | let mut san = None; 527 | for ext in tbs.extensions { 528 | if ext.oid == OID_SUBJECT_ALT_NAME.parse().unwrap() { 529 | san = Some(ext.value); 530 | break; 531 | } 532 | } 533 | 534 | let names = san 535 | .and_then(|san| { 536 | yasna::parse_ber(san, |reader| { 537 | reader.collect_sequence_of(|reader| { 538 | let tagged = reader.read_tagged_der()?; 539 | let num = tagged.tag().tag_number; 540 | Ok(match num { 541 | 1 | 2 | 6 => { 542 | let val = std::str::from_utf8(tagged.value()).unwrap().into(); 543 | match num { 544 | 1 => GeneralName::Email(val), 545 | 2 => GeneralName::Dns(val), 546 | 6 => GeneralName::Uri(val), 547 | _ => unreachable!(), 548 | } 549 | } 550 | 7 => GeneralName::Ip(tagged.value().into()), 551 | _ => GeneralName::Unknown, 552 | }) 553 | }) 554 | }) 555 | .ok() 556 | }) 557 | .unwrap_or_default(); 558 | 559 | Self { 560 | issuer: tbs.issuer.to_string(), 561 | subject: tbs.subject.to_string(), 562 | not_before: tbs.validity.not_before, 563 | not_after: tbs.validity.not_after, 564 | names, 565 | } 566 | } 567 | 568 | pub fn load_local(filepath: PathBuf) -> Result { 569 | let mut file = File::open(filepath)?; 570 | let mut buf = Vec::new(); 571 | file.read_to_end(&mut buf)?; 572 | 573 | let (_, der) = pem_to_der(&buf)?; 574 | let (_, cert) = parse_x509_der(&der.contents)?; 575 | Ok(Self::parse(cert)) 576 | } 577 | 578 | pub fn load_remote(url: &str) -> Result, Ernum> { 579 | use rustls::Session; 580 | use std::sync::Arc; 581 | use url::Url; 582 | 583 | // parse url. try really hard 584 | let url = Url::parse(url) 585 | .or_else(|err| Url::parse(&format!("https://{}", url)).map_err(|_| err))?; 586 | 587 | // disable verification 588 | let mut config = rustls::ClientConfig::new(); 589 | config 590 | .dangerous() 591 | .set_certificate_verifier(Arc::new(NoCertificateVerification)); 592 | let connector: RustlsConnector = config.into(); 593 | 594 | // connect 595 | let stream = TcpStream::connect(url.socket_addrs(|| Some(443))?[0])?; 596 | let stream = connector.connect(url.host_str().unwrap(), stream)?; 597 | 598 | // get certs 599 | let chain = stream 600 | .sess 601 | .get_peer_certificates() 602 | .ok_or_else(|| Ernum::Other("no certificate in chain".into()))?; 603 | 604 | // decode certs 605 | let mut certs = Vec::with_capacity(chain.len()); 606 | for raw in chain { 607 | let (_, cert) = parse_x509_der(&raw.0)?; 608 | certs.push(Self::parse(cert)); 609 | } 610 | 611 | Ok(certs) 612 | } 613 | } 614 | 615 | fn inspect(filepath: PathBuf) -> Result<(), Ernum> { 616 | let mut is_remote = false; 617 | let maybe_url = filepath.clone(); 618 | let maybe_url = maybe_url.to_str().unwrap(); 619 | let mut certs = if filepath.starts_with("https://") { 620 | is_remote = true; 621 | ParsedCert::load_remote(maybe_url)? 622 | } else { 623 | match ParsedCert::load_local(filepath) { 624 | Ok(cert) => vec![cert], 625 | Err(filerr) => match ParsedCert::load_remote(maybe_url) { 626 | Ok(certs) => { 627 | is_remote = true; 628 | certs 629 | } 630 | Err(err) => { 631 | eprintln!("{:?}", filerr); 632 | return Err(err); 633 | } 634 | }, 635 | } 636 | }; 637 | 638 | let cert = certs.remove(0); 639 | let rest = certs; 640 | 641 | println!( 642 | "{} {}", 643 | if is_remote { "[Remote]" } else { "[Local] " }, 644 | cert.subject 645 | ); 646 | println!("Issuer: {}", cert.issuer); 647 | 648 | if !rest.is_empty() { 649 | println!("\nChain:"); 650 | } 651 | for c in &rest { 652 | println!(" Subject: {}\n Issuer: {}\n", c.subject, c.issuer); 653 | } 654 | 655 | if rest.is_empty() { 656 | println!(); 657 | } 658 | println!("Created on: {}", cert.not_before.asctime()); 659 | let expired = time::now() > cert.not_after; 660 | println!( 661 | "Expire{} on: {}", 662 | if expired { 'd' } else { 's' }, 663 | cert.not_after.asctime() 664 | ); 665 | 666 | if !cert.names.is_empty() { 667 | println!("\nDomains:"); 668 | } 669 | 670 | let mut others = 0; 671 | for name in cert.names { 672 | match name { 673 | GeneralName::Dns(dns) => println!(" DNS: {}", dns), 674 | GeneralName::Ip(ip) => { 675 | use std::convert::TryFrom; 676 | use std::net::{Ipv4Addr, Ipv6Addr}; 677 | 678 | let bytes: &[u8] = &ip; 679 | if let Ok(octets) = <[u8; 16]>::try_from(bytes) { 680 | println!(" IPV6: {}", Ipv6Addr::from(octets)); 681 | } else if let Ok(octets) = <[u8; 4]>::try_from(bytes) { 682 | println!(" IPV4: {}", Ipv4Addr::from(octets)); 683 | } 684 | } 685 | GeneralName::Email(mail) => println!(" EMAIL: {}", mail), 686 | GeneralName::Uri(uri) => println!(" URL: {}", uri), 687 | _ => { 688 | others += 1; 689 | } 690 | } 691 | } 692 | 693 | if others > 0 { 694 | println!(" ({} of other types)", others); 695 | } 696 | 697 | print!("\nTo see more: $ "); 698 | if is_remote { 699 | println!("echo Q | openssl s_client {}:443", maybe_url); 700 | } else { 701 | println!("openssl x509 -text -in {}", maybe_url); 702 | } 703 | 704 | Ok(()) 705 | } 706 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "addr2line" 5 | version = "0.13.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "gimli 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "adler" 13 | version = "0.2.3" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | 16 | [[package]] 17 | name = "aho-corasick" 18 | version = "0.7.13" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | dependencies = [ 21 | "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 22 | ] 23 | 24 | [[package]] 25 | name = "ansi_term" 26 | version = "0.11.0" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | dependencies = [ 29 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 30 | ] 31 | 32 | [[package]] 33 | name = "arrayvec" 34 | version = "0.5.1" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | 37 | [[package]] 38 | name = "atty" 39 | version = "0.2.14" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | dependencies = [ 42 | "hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 44 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 45 | ] 46 | 47 | [[package]] 48 | name = "autocfg" 49 | version = "0.1.7" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | 52 | [[package]] 53 | name = "autocfg" 54 | version = "1.0.1" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | 57 | [[package]] 58 | name = "backtrace" 59 | version = "0.3.50" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | dependencies = [ 62 | "addr2line 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", 63 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 64 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 65 | "miniz_oxide 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "object 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", 67 | "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 68 | ] 69 | 70 | [[package]] 71 | name = "base64" 72 | version = "0.11.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | 75 | [[package]] 76 | name = "base64" 77 | version = "0.12.3" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | 80 | [[package]] 81 | name = "bit-vec" 82 | version = "0.6.2" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | 85 | [[package]] 86 | name = "bitflags" 87 | version = "1.2.1" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | 90 | [[package]] 91 | name = "bumpalo" 92 | version = "3.4.0" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | 95 | [[package]] 96 | name = "byteorder" 97 | version = "1.3.4" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | 100 | [[package]] 101 | name = "cc" 102 | version = "1.0.59" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | 105 | [[package]] 106 | name = "certainly" 107 | version = "1.8.0" 108 | dependencies = [ 109 | "bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 110 | "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", 111 | "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)", 112 | "gethostname 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 113 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 114 | "nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 115 | "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 116 | "num-bigint-dig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 117 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 118 | "rcgen 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", 119 | "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)", 120 | "rsa 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 121 | "rustls-connector 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 122 | "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", 123 | "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 124 | "x509-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 125 | "yasna 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 126 | ] 127 | 128 | [[package]] 129 | name = "cfg-if" 130 | version = "0.1.10" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | 133 | [[package]] 134 | name = "chrono" 135 | version = "0.4.15" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | dependencies = [ 138 | "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", 139 | "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", 140 | "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", 141 | ] 142 | 143 | [[package]] 144 | name = "clap" 145 | version = "2.33.3" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | dependencies = [ 148 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 149 | "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", 150 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 151 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 152 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 153 | "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 154 | "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 155 | ] 156 | 157 | [[package]] 158 | name = "cloudabi" 159 | version = "0.0.3" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | dependencies = [ 162 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 163 | ] 164 | 165 | [[package]] 166 | name = "core-foundation" 167 | version = "0.7.0" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | dependencies = [ 170 | "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 171 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 172 | ] 173 | 174 | [[package]] 175 | name = "core-foundation-sys" 176 | version = "0.7.0" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | 179 | [[package]] 180 | name = "der-parser" 181 | version = "3.0.4" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | dependencies = [ 184 | "nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 185 | "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 186 | "rusticata-macros 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 187 | ] 188 | 189 | [[package]] 190 | name = "failure" 191 | version = "0.1.8" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | dependencies = [ 194 | "backtrace 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)", 195 | "failure_derive 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 196 | ] 197 | 198 | [[package]] 199 | name = "failure_derive" 200 | version = "0.1.8" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | dependencies = [ 203 | "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", 204 | "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 205 | "syn 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 206 | "synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", 207 | ] 208 | 209 | [[package]] 210 | name = "fuchsia-cprng" 211 | version = "0.1.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | 214 | [[package]] 215 | name = "gethostname" 216 | version = "0.2.1" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | dependencies = [ 219 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 220 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 221 | ] 222 | 223 | [[package]] 224 | name = "gimli" 225 | version = "0.22.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | 228 | [[package]] 229 | name = "hermit-abi" 230 | version = "0.1.15" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | dependencies = [ 233 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 234 | ] 235 | 236 | [[package]] 237 | name = "idna" 238 | version = "0.2.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | dependencies = [ 241 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 242 | "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 243 | "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 244 | ] 245 | 246 | [[package]] 247 | name = "js-sys" 248 | version = "0.3.44" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | dependencies = [ 251 | "wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 252 | ] 253 | 254 | [[package]] 255 | name = "lazy_static" 256 | version = "1.4.0" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | 259 | [[package]] 260 | name = "lexical-core" 261 | version = "0.7.4" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | dependencies = [ 264 | "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 265 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 266 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 267 | "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 268 | "static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 269 | ] 270 | 271 | [[package]] 272 | name = "libc" 273 | version = "0.2.76" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | 276 | [[package]] 277 | name = "log" 278 | version = "0.4.11" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | dependencies = [ 281 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 282 | ] 283 | 284 | [[package]] 285 | name = "matches" 286 | version = "0.1.8" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | 289 | [[package]] 290 | name = "maybe-uninit" 291 | version = "2.0.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | 294 | [[package]] 295 | name = "memchr" 296 | version = "2.3.3" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | 299 | [[package]] 300 | name = "miniz_oxide" 301 | version = "0.4.1" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | dependencies = [ 304 | "adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 305 | ] 306 | 307 | [[package]] 308 | name = "nom" 309 | version = "5.1.2" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | dependencies = [ 312 | "lexical-core 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", 313 | "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 314 | "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", 315 | ] 316 | 317 | [[package]] 318 | name = "num-bigint" 319 | version = "0.2.3" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | dependencies = [ 322 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 323 | "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", 324 | "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", 325 | ] 326 | 327 | [[package]] 328 | name = "num-bigint-dig" 329 | version = "0.4.0" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | dependencies = [ 332 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 333 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 334 | "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", 335 | "num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", 336 | "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", 337 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 338 | "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 339 | "zeroize 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 340 | ] 341 | 342 | [[package]] 343 | name = "num-integer" 344 | version = "0.1.43" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | dependencies = [ 347 | "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 348 | "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", 349 | ] 350 | 351 | [[package]] 352 | name = "num-iter" 353 | version = "0.1.41" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | dependencies = [ 356 | "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 357 | "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", 358 | "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", 359 | ] 360 | 361 | [[package]] 362 | name = "num-traits" 363 | version = "0.2.12" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | dependencies = [ 366 | "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 367 | ] 368 | 369 | [[package]] 370 | name = "object" 371 | version = "0.20.0" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | 374 | [[package]] 375 | name = "once_cell" 376 | version = "1.4.1" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | 379 | [[package]] 380 | name = "openssl-probe" 381 | version = "0.1.2" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | 384 | [[package]] 385 | name = "pem" 386 | version = "0.8.1" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | dependencies = [ 389 | "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 390 | "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 391 | "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 392 | ] 393 | 394 | [[package]] 395 | name = "percent-encoding" 396 | version = "2.1.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | 399 | [[package]] 400 | name = "proc-macro2" 401 | version = "0.4.30" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | dependencies = [ 404 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 405 | ] 406 | 407 | [[package]] 408 | name = "proc-macro2" 409 | version = "1.0.19" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | dependencies = [ 412 | "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 413 | ] 414 | 415 | [[package]] 416 | name = "quote" 417 | version = "0.6.13" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | dependencies = [ 420 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 421 | ] 422 | 423 | [[package]] 424 | name = "quote" 425 | version = "1.0.7" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | dependencies = [ 428 | "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", 429 | ] 430 | 431 | [[package]] 432 | name = "rand" 433 | version = "0.6.5" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | dependencies = [ 436 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 437 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 438 | "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 439 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 440 | "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 441 | "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 442 | "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 443 | "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 444 | "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 445 | "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 446 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 447 | ] 448 | 449 | [[package]] 450 | name = "rand_chacha" 451 | version = "0.1.1" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | dependencies = [ 454 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 455 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 456 | ] 457 | 458 | [[package]] 459 | name = "rand_core" 460 | version = "0.3.1" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | dependencies = [ 463 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 464 | ] 465 | 466 | [[package]] 467 | name = "rand_core" 468 | version = "0.4.2" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | 471 | [[package]] 472 | name = "rand_hc" 473 | version = "0.1.0" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | dependencies = [ 476 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 477 | ] 478 | 479 | [[package]] 480 | name = "rand_isaac" 481 | version = "0.1.1" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | dependencies = [ 484 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 485 | ] 486 | 487 | [[package]] 488 | name = "rand_jitter" 489 | version = "0.1.4" 490 | source = "registry+https://github.com/rust-lang/crates.io-index" 491 | dependencies = [ 492 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 493 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 494 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 495 | ] 496 | 497 | [[package]] 498 | name = "rand_os" 499 | version = "0.1.3" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | dependencies = [ 502 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 503 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 504 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 505 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 506 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 507 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 508 | ] 509 | 510 | [[package]] 511 | name = "rand_pcg" 512 | version = "0.1.2" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | dependencies = [ 515 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 516 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 517 | ] 518 | 519 | [[package]] 520 | name = "rand_xorshift" 521 | version = "0.1.1" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | dependencies = [ 524 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 525 | ] 526 | 527 | [[package]] 528 | name = "rcgen" 529 | version = "0.8.5" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | dependencies = [ 532 | "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", 533 | "pem 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 534 | "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)", 535 | "x509-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 536 | "yasna 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 537 | ] 538 | 539 | [[package]] 540 | name = "rdrand" 541 | version = "0.4.0" 542 | source = "registry+https://github.com/rust-lang/crates.io-index" 543 | dependencies = [ 544 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 545 | ] 546 | 547 | [[package]] 548 | name = "regex" 549 | version = "1.3.9" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | dependencies = [ 552 | "aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)", 553 | "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 554 | "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)", 555 | "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 556 | ] 557 | 558 | [[package]] 559 | name = "regex-syntax" 560 | version = "0.6.18" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | 563 | [[package]] 564 | name = "ring" 565 | version = "0.16.15" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | dependencies = [ 568 | "cc 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)", 569 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 570 | "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 571 | "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 572 | "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 573 | "web-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", 574 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 575 | ] 576 | 577 | [[package]] 578 | name = "rsa" 579 | version = "0.1.3" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | dependencies = [ 582 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 583 | "failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 584 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 585 | "num-bigint-dig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 586 | "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", 587 | "num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", 588 | "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", 589 | "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 590 | "subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 591 | "zeroize 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 592 | ] 593 | 594 | [[package]] 595 | name = "rustc-demangle" 596 | version = "0.1.16" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | 599 | [[package]] 600 | name = "rusticata-macros" 601 | version = "2.1.0" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | dependencies = [ 604 | "nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 605 | ] 606 | 607 | [[package]] 608 | name = "rustls" 609 | version = "0.18.1" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | dependencies = [ 612 | "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 613 | "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", 614 | "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)", 615 | "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 616 | "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", 617 | ] 618 | 619 | [[package]] 620 | name = "rustls-connector" 621 | version = "0.12.0" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | dependencies = [ 624 | "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", 625 | "rustls 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", 626 | "rustls-native-certs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 627 | "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)", 628 | ] 629 | 630 | [[package]] 631 | name = "rustls-native-certs" 632 | version = "0.4.0" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | dependencies = [ 635 | "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 636 | "rustls 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", 637 | "schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", 638 | "security-framework 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 639 | ] 640 | 641 | [[package]] 642 | name = "ryu" 643 | version = "1.0.5" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | 646 | [[package]] 647 | name = "schannel" 648 | version = "0.1.19" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | dependencies = [ 651 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 652 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 653 | ] 654 | 655 | [[package]] 656 | name = "sct" 657 | version = "0.6.0" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | dependencies = [ 660 | "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)", 661 | "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 662 | ] 663 | 664 | [[package]] 665 | name = "security-framework" 666 | version = "1.0.0" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | dependencies = [ 669 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 670 | "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 671 | "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 672 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 673 | "security-framework-sys 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 674 | ] 675 | 676 | [[package]] 677 | name = "security-framework-sys" 678 | version = "1.0.0" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | dependencies = [ 681 | "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 682 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 683 | ] 684 | 685 | [[package]] 686 | name = "smallvec" 687 | version = "0.6.13" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | dependencies = [ 690 | "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 691 | ] 692 | 693 | [[package]] 694 | name = "spin" 695 | version = "0.5.2" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | 698 | [[package]] 699 | name = "static_assertions" 700 | version = "1.1.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | 703 | [[package]] 704 | name = "strsim" 705 | version = "0.8.0" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | 708 | [[package]] 709 | name = "subtle" 710 | version = "2.2.3" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | 713 | [[package]] 714 | name = "syn" 715 | version = "0.15.44" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | dependencies = [ 718 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 719 | "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 720 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 721 | ] 722 | 723 | [[package]] 724 | name = "syn" 725 | version = "1.0.39" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | dependencies = [ 728 | "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", 729 | "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 730 | "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 731 | ] 732 | 733 | [[package]] 734 | name = "synstructure" 735 | version = "0.12.4" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | dependencies = [ 738 | "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", 739 | "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 740 | "syn 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 741 | "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 742 | ] 743 | 744 | [[package]] 745 | name = "textwrap" 746 | version = "0.11.0" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | dependencies = [ 749 | "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 750 | ] 751 | 752 | [[package]] 753 | name = "thread_local" 754 | version = "1.0.1" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | dependencies = [ 757 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 758 | ] 759 | 760 | [[package]] 761 | name = "time" 762 | version = "0.1.44" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | dependencies = [ 765 | "libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)", 766 | "wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", 767 | "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 768 | ] 769 | 770 | [[package]] 771 | name = "tinyvec" 772 | version = "0.3.4" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | 775 | [[package]] 776 | name = "unicode-bidi" 777 | version = "0.3.4" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | dependencies = [ 780 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 781 | ] 782 | 783 | [[package]] 784 | name = "unicode-normalization" 785 | version = "0.1.13" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | dependencies = [ 788 | "tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 789 | ] 790 | 791 | [[package]] 792 | name = "unicode-width" 793 | version = "0.1.8" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | 796 | [[package]] 797 | name = "unicode-xid" 798 | version = "0.1.0" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | 801 | [[package]] 802 | name = "unicode-xid" 803 | version = "0.2.1" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | 806 | [[package]] 807 | name = "untrusted" 808 | version = "0.7.1" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | 811 | [[package]] 812 | name = "url" 813 | version = "2.1.1" 814 | source = "registry+https://github.com/rust-lang/crates.io-index" 815 | dependencies = [ 816 | "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 817 | "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 818 | "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 819 | ] 820 | 821 | [[package]] 822 | name = "vec_map" 823 | version = "0.8.2" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | 826 | [[package]] 827 | name = "version_check" 828 | version = "0.9.2" 829 | source = "registry+https://github.com/rust-lang/crates.io-index" 830 | 831 | [[package]] 832 | name = "wasi" 833 | version = "0.10.0+wasi-snapshot-preview1" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | 836 | [[package]] 837 | name = "wasm-bindgen" 838 | version = "0.2.67" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | dependencies = [ 841 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 842 | "wasm-bindgen-macro 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 843 | ] 844 | 845 | [[package]] 846 | name = "wasm-bindgen-backend" 847 | version = "0.2.67" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | dependencies = [ 850 | "bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 851 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 852 | "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", 853 | "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", 854 | "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 855 | "syn 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 856 | "wasm-bindgen-shared 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 857 | ] 858 | 859 | [[package]] 860 | name = "wasm-bindgen-macro" 861 | version = "0.2.67" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | dependencies = [ 864 | "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 865 | "wasm-bindgen-macro-support 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 866 | ] 867 | 868 | [[package]] 869 | name = "wasm-bindgen-macro-support" 870 | version = "0.2.67" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | dependencies = [ 873 | "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", 874 | "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 875 | "syn 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", 876 | "wasm-bindgen-backend 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 877 | "wasm-bindgen-shared 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 878 | ] 879 | 880 | [[package]] 881 | name = "wasm-bindgen-shared" 882 | version = "0.2.67" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | 885 | [[package]] 886 | name = "web-sys" 887 | version = "0.3.44" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | dependencies = [ 890 | "js-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)", 891 | "wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", 892 | ] 893 | 894 | [[package]] 895 | name = "webpki" 896 | version = "0.21.3" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | dependencies = [ 899 | "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)", 900 | "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 901 | ] 902 | 903 | [[package]] 904 | name = "winapi" 905 | version = "0.3.9" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | dependencies = [ 908 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 909 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 910 | ] 911 | 912 | [[package]] 913 | name = "winapi-i686-pc-windows-gnu" 914 | version = "0.4.0" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | 917 | [[package]] 918 | name = "winapi-x86_64-pc-windows-gnu" 919 | version = "0.4.0" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | 922 | [[package]] 923 | name = "x509-parser" 924 | version = "0.7.0" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | dependencies = [ 927 | "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 928 | "der-parser 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 929 | "nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 930 | "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 931 | "rusticata-macros 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 932 | "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", 933 | ] 934 | 935 | [[package]] 936 | name = "yasna" 937 | version = "0.3.2" 938 | source = "registry+https://github.com/rust-lang/crates.io-index" 939 | dependencies = [ 940 | "bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 941 | "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)", 942 | "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 943 | ] 944 | 945 | [[package]] 946 | name = "zeroize" 947 | version = "0.6.0" 948 | source = "registry+https://github.com/rust-lang/crates.io-index" 949 | dependencies = [ 950 | "zeroize_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 951 | ] 952 | 953 | [[package]] 954 | name = "zeroize_derive" 955 | version = "0.1.0" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | dependencies = [ 958 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 959 | "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 960 | "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", 961 | ] 962 | 963 | [metadata] 964 | "checksum addr2line 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" 965 | "checksum adler 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" 966 | "checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" 967 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 968 | "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" 969 | "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 970 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 971 | "checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 972 | "checksum backtrace 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" 973 | "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" 974 | "checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" 975 | "checksum bit-vec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" 976 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 977 | "checksum bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" 978 | "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 979 | "checksum cc 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)" = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" 980 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 981 | "checksum chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b" 982 | "checksum clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" 983 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 984 | "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" 985 | "checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" 986 | "checksum der-parser 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f51f64dcdf1cdc550d21d73dc959726c7dbeeab4a01481d08084a7736956464e" 987 | "checksum failure 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 988 | "checksum failure_derive 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" 989 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 990 | "checksum gethostname 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" 991 | "checksum gimli 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" 992 | "checksum hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" 993 | "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" 994 | "checksum js-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "85a7e2c92a4804dd459b86c339278d0fe87cf93757fae222c3fa3ae75458bc73" 995 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 996 | "checksum lexical-core 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" 997 | "checksum libc 0.2.76 (registry+https://github.com/rust-lang/crates.io-index)" = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" 998 | "checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" 999 | "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1000 | "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 1001 | "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" 1002 | "checksum miniz_oxide 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722" 1003 | "checksum nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 1004 | "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" 1005 | "checksum num-bigint-dig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cd60678022301da54082fcc383647fc895cba2795f868c871d58d29c8922595" 1006 | "checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" 1007 | "checksum num-iter 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f" 1008 | "checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" 1009 | "checksum object 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" 1010 | "checksum once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" 1011 | "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" 1012 | "checksum pem 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59698ea79df9bf77104aefd39cc3ec990cb9693fb59c3b0a70ddf2646fdffb4b" 1013 | "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1014 | "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 1015 | "checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12" 1016 | "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" 1017 | "checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" 1018 | "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1019 | "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1020 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1021 | "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 1022 | "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" 1023 | "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" 1024 | "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" 1025 | "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" 1026 | "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" 1027 | "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" 1028 | "checksum rcgen 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4974f7e96ee51fa3c90c3022e02c3a7117e71cb2a84518a55e44360135200c25" 1029 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 1030 | "checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" 1031 | "checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" 1032 | "checksum ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)" = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4" 1033 | "checksum rsa 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6ad8d3632f6745bb671c8637e2aa44015537c5e384789d2ea3235739301ed1e0" 1034 | "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" 1035 | "checksum rusticata-macros 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8a9050636e8a1b487ba1fbe99114021cd7594dde3ce6ed95bfc1691e5b5367b" 1036 | "checksum rustls 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" 1037 | "checksum rustls-connector 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "498854dcb920e6fde17046164487977a6177d1ccc5ea58379edb910e9e60a251" 1038 | "checksum rustls-native-certs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "629d439a7672da82dd955498445e496ee2096fe2117b9f796558a43fdb9e59b8" 1039 | "checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1040 | "checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" 1041 | "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" 1042 | "checksum security-framework 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad502866817f0575705bd7be36e2b2535cc33262d493aa733a2ec862baa2bc2b" 1043 | "checksum security-framework-sys 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51ceb04988b17b6d1dcd555390fa822ca5637b4a14e1f5099f13d351bed4d6c7" 1044 | "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" 1045 | "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1046 | "checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1047 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 1048 | "checksum subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1" 1049 | "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" 1050 | "checksum syn 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9" 1051 | "checksum synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" 1052 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 1053 | "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" 1054 | "checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 1055 | "checksum tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" 1056 | "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1057 | "checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" 1058 | "checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" 1059 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 1060 | "checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" 1061 | "checksum untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 1062 | "checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" 1063 | "checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 1064 | "checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 1065 | "checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1066 | "checksum wasm-bindgen 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "f0563a9a4b071746dd5aedbc3a28c6fe9be4586fb3fbadb67c400d4f53c6b16c" 1067 | "checksum wasm-bindgen-backend 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "bc71e4c5efa60fb9e74160e89b93353bc24059999c0ae0fb03affc39770310b0" 1068 | "checksum wasm-bindgen-macro 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "97c57cefa5fa80e2ba15641578b44d36e7a64279bc5ed43c6dbaf329457a2ed2" 1069 | "checksum wasm-bindgen-macro-support 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "841a6d1c35c6f596ccea1f82504a192a60378f64b3bb0261904ad8f2f5657556" 1070 | "checksum wasm-bindgen-shared 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "93b162580e34310e5931c4b792560108b10fd14d64915d7fff8ff00180e70092" 1071 | "checksum web-sys 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "dda38f4e5ca63eda02c059d243aa25b5f35ab98451e518c51612cd0f1bd19a47" 1072 | "checksum webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae" 1073 | "checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1074 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1075 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1076 | "checksum x509-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dba437c45e779568868b2c46ed1d1c57c98d9f868e47c9bcbfe9114d4cbd97d" 1077 | "checksum yasna 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb" 1078 | "checksum zeroize 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e68403b858b6af538b11614e62dfe9ab2facba9f13a0cafb974855cfb495ec95" 1079 | "checksum zeroize_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3f07490820219949839d0027b965ffdd659d75be9220c00798762e36c6cd281" 1080 | --------------------------------------------------------------------------------