├── .github └── workflows │ ├── release.yaml │ └── test.yaml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── check-tls-cert.go ├── checker ├── certificate.go ├── certificate_common.go ├── certificate_test.go ├── certificatechain.go ├── certificatechain_test.go ├── certificatefiles.go ├── certificatefiles_test.go ├── certificatelist.go ├── certificatelist_test.go ├── checker.go ├── checker_test.go ├── fmt.go ├── fmt_test.go ├── hostname.go ├── hostname_test.go ├── keypair.go ├── keypair_test.go ├── ocsp_common.go ├── ocspresponder.go ├── ocspresponder_test.go ├── ocspstapling.go ├── ocspstapling_test.go ├── summary.go ├── summary_test.go ├── validity.go └── validity_test.go ├── cmd ├── file.go ├── net.go └── root.go ├── go.mod ├── go.sum ├── internal ├── file │ └── file.go └── net │ └── net.go ├── net ├── imaputil │ └── imap.go ├── pop3util │ └── pop3.go └── smtputil │ └── smtp.go ├── ocsputil ├── ocsp.go └── ocsp_test.go ├── scripts ├── PKI.md ├── bumpup.sh ├── gen-chain-cert.sh ├── gen-expired-cert.sh ├── gen-expired-ocsp-cert.sh ├── gen-not-yet-valid-cert.sh ├── gen-ocsp-cert.sh ├── gen-private-key.sh ├── gen-root-ca-cert.sh ├── gen-valid-cert.sh └── pkilib.sh ├── test └── testdata │ └── pki │ ├── cert │ ├── expired │ │ ├── .gitkeep │ │ ├── ca-intermediate-a-rsa-ocsp-responder.pem │ │ ├── ca-intermediate-a-rsa.pem │ │ ├── ca-intermediate-b-rsa.pem │ │ ├── ca-intermediate-ecdsa.pem │ │ ├── server-a-ecdsa.pem │ │ ├── server-a-ed25519.pem │ │ ├── server-a-ed488.pem │ │ ├── server-a-rsa.pem │ │ ├── server-b-ecdsa.pem │ │ ├── server-b-ed25519.pem │ │ ├── server-b-ed488.pem │ │ ├── server-b-rsa.pem │ │ ├── server-c-ecdsa.pem │ │ ├── server-c-ed25519.pem │ │ ├── server-c-ed488.pem │ │ └── server-c-rsa.pem │ ├── notyetvalid │ │ ├── .gitkeep │ │ ├── ca-intermediate-a-rsa.pem │ │ ├── ca-intermediate-b-rsa.pem │ │ ├── ca-intermediate-ecdsa.pem │ │ ├── server-a-ecdsa.pem │ │ ├── server-a-ed25519.pem │ │ ├── server-a-ed488.pem │ │ ├── server-a-rsa.pem │ │ ├── server-b-ecdsa.pem │ │ ├── server-b-ed25519.pem │ │ ├── server-b-ed488.pem │ │ ├── server-b-rsa.pem │ │ ├── server-c-ecdsa.pem │ │ ├── server-c-ed25519.pem │ │ ├── server-c-ed488.pem │ │ └── server-c-rsa.pem │ └── valid │ │ └── .gitkeep │ ├── chain │ └── .gitkeep │ ├── misc │ └── empty.pem │ ├── private │ ├── .gitkeep │ ├── ca-intermediate-a-rsa-ocsp-responder-traditional.pem │ ├── ca-intermediate-a-rsa-ocsp-responder.pem │ ├── ca-intermediate-a-rsa.pem │ ├── ca-intermediate-b-rsa.pem │ ├── ca-intermediate-ecdsa.pem │ ├── ca-root-g1-rsa.pem │ ├── ca-root-g2-ecdsa.pem │ ├── ca-root-g2-rsa.pem │ ├── misc-explanatory-text.pem │ ├── misc-no-eol.pem │ ├── password.txt │ ├── server-a-ecdsa-encrypted.pem │ ├── server-a-ecdsa-traditional-encrypted.pem │ ├── server-a-ecdsa-traditional.pem │ ├── server-a-ecdsa.der │ ├── server-a-ecdsa.pem │ ├── server-a-ed25519-encrypted.pem │ ├── server-a-ed25519.der │ ├── server-a-ed25519.pem │ ├── server-a-ed488-encrypted.pem │ ├── server-a-ed488.der │ ├── server-a-ed488.pem │ ├── server-a-rsa-encrypted.pem │ ├── server-a-rsa-traditional-encrypted.pem │ ├── server-a-rsa-traditional.pem │ ├── server-a-rsa.der │ ├── server-a-rsa.pem │ ├── server-b-ecdsa-traditional.pem │ ├── server-b-ecdsa.der │ ├── server-b-ecdsa.pem │ ├── server-b-ed25519.der │ ├── server-b-ed25519.pem │ ├── server-b-ed488.der │ ├── server-b-ed488.pem │ ├── server-b-rsa-traditional.pem │ ├── server-b-rsa.der │ ├── server-b-rsa.pem │ ├── server-c-ecdsa-traditional.pem │ ├── server-c-ecdsa.der │ ├── server-c-ecdsa.pem │ ├── server-c-ed25519.der │ ├── server-c-ed25519.pem │ ├── server-c-ed488.der │ ├── server-c-ed488.pem │ ├── server-c-rsa-traditional.pem │ ├── server-c-rsa.der │ └── server-c-rsa.pem │ └── root-ca │ ├── .gitkeep │ ├── ca-root-g1-rsa.pem │ ├── ca-root-g2-ecdsa-cross.pem │ ├── ca-root-g2-ecdsa.pem │ ├── ca-root-g2-rsa-cross.pem │ ├── ca-root-g2-rsa.pem │ └── ca-root.pem ├── version └── version.go └── x509util ├── certificate.go ├── certificate_test.go ├── dn.go ├── dn_test.go ├── pem.go ├── pem_test.go ├── privatekey.go ├── privatekey_test.go ├── publickey.go └── publickey_test.go /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Releases 2 | on: 3 | push: 4 | tags: 5 | - "v*" 6 | jobs: 7 | test: 8 | runs-on: ubuntu-latest 9 | name: Test 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v3 13 | 14 | - name: Setup go 15 | uses: actions/setup-go@v3 16 | with: 17 | go-version: "1.18.1" 18 | 19 | - name: Install dependency 20 | run: go get -t -v ./... 21 | 22 | - name: Test 23 | run: | 24 | bash scripts/gen-valid-cert.sh 25 | bash scripts/gen-chain-cert.sh 26 | bash scripts/gen-ocsp-cert.sh 27 | go test -v ./... 28 | 29 | release: 30 | name: Release 31 | needs: test 32 | runs-on: ubuntu-latest 33 | outputs: 34 | upload_url: ${{ steps.create_release.outputs.upload_url }} 35 | steps: 36 | - name: Checkout code 37 | uses: actions/checkout@v3 38 | 39 | - name: Setup go 40 | uses: actions/setup-go@v3 41 | with: 42 | go-version: "1.18.1" 43 | 44 | - name: Create Release 45 | id: create_release 46 | uses: actions/create-release@v1 47 | env: 48 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 49 | with: 50 | tag_name: ${{ github.ref }} 51 | release_name: Release ${{ github.ref }} 52 | draft: false 53 | prerelease: false 54 | 55 | release_binary: 56 | name: Release binary 57 | needs: release 58 | runs-on: ubuntu-latest 59 | strategy: 60 | matrix: 61 | os: 62 | [darwin_amd64, darwin_arm64, linux_amd64, linux_arm64, windows_amd64] 63 | include: 64 | - os: darwin_amd64 65 | goos: darwin 66 | arch: amd64 67 | - os: darwin_arm64 68 | goos: darwin 69 | arch: arm64 70 | - os: linux_amd64 71 | goos: linux 72 | arch: amd64 73 | - os: linux_arm64 74 | goos: linux 75 | arch: arm64 76 | - os: windows_amd64 77 | goos: windows 78 | arch: amd64 79 | outputs: 80 | version: ${{ steps.version.outputs.version }} 81 | steps: 82 | - name: Checkout code 83 | uses: actions/checkout@v3 84 | 85 | - name: Setup go 86 | uses: actions/setup-go@v3 87 | with: 88 | go-version: "1.18.1" 89 | 90 | - name: Prepare artifact 91 | run: | 92 | mkdir -p dist/check-tls-cert 93 | cp README.md dist/check-tls-cert/ 94 | 95 | - name: Build 96 | run: | 97 | go get -t -v ./... 98 | if [[ ${{ matrix.goos }} != "windows" ]]; then GOOS=${{ matrix.goos }} GOARCH=${{ matrix.arch }} go build -v -o dist/check-tls-cert/check-tls-cert .; fi 99 | if [[ ${{ matrix.goos }} == "windows" ]]; then GOOS=${{ matrix.goos }} GOARCH=${{ matrix.arch }} go build -v -o dist/check-tls-cert/check-tls-cert.exe .; fi 100 | 101 | - name: Version 102 | id: version 103 | run: echo "::set-output name=version::$(go run check-tls-cert.go --version | cut -d ' ' -f 3)" 104 | 105 | - name: Archive 106 | run: | 107 | cd dist 108 | mv check-tls-cert check-tls-cert-${VERSION} 109 | if [[ ${{ matrix.goos }} != "windows" ]]; then zip ../check-tls-cert.zip check-tls-cert-${VERSION}/check-tls-cert check-tls-cert-${VERSION}/README.md; fi 110 | if [[ ${{ matrix.goos }} == "windows" ]]; then zip ../check-tls-cert.zip check-tls-cert-${VERSION}/check-tls-cert.exe check-tls-cert-${VERSION}/README.md; fi 111 | tar -cJf ../check-tls-cert.tar.xz check-tls-cert-${VERSION} 112 | env: 113 | VERSION: ${{ steps.version.outputs.version }} 114 | 115 | - name: Upload Release Asset Zip 116 | id: upload-release-asset-zip 117 | uses: actions/upload-release-asset@v1 118 | env: 119 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 120 | with: 121 | upload_url: ${{ needs.release.outputs.upload_url }} 122 | asset_path: ./check-tls-cert.zip 123 | asset_name: check-tls-cert-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.arch }}.zip 124 | asset_content_type: application/zip 125 | 126 | - name: Upload Release Asset Tar 127 | id: upload-release-asset-tar 128 | uses: actions/upload-release-asset@v1 129 | env: 130 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 131 | with: 132 | upload_url: ${{ needs.release.outputs.upload_url }} 133 | asset_path: ./check-tls-cert.tar.xz 134 | asset_name: check-tls-cert-${{ steps.version.outputs.version }}-${{ matrix.goos }}-${{ matrix.arch }}.tar.xz 135 | asset_content_type: application/octet-stream 136 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | branches: 5 | - "**" 6 | tags-ignore: 7 | - "v*" 8 | pull_request: 9 | branches: 10 | - "**" 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | name: Test 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v3 18 | 19 | - name: Setup go 20 | uses: actions/setup-go@v3 21 | with: 22 | go-version: "1.18.1" 23 | 24 | - name: Install dependency 25 | run: go get -t -v ./... 26 | 27 | - name: Test 28 | run: | 29 | bash scripts/gen-valid-cert.sh 30 | bash scripts/gen-chain-cert.sh 31 | bash scripts/gen-ocsp-cert.sh 32 | go test -v ./... 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # https://raw.githubusercontent.com/github/gitignore/master/Go.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | ############################################################################# 20 | # build 21 | check-tls-cert 22 | dist/ 23 | 24 | # Certificates for test 25 | test/testdata/pki/cert/valid/*.pem 26 | test/testdata/pki/cert/valid/*.der 27 | test/testdata/pki/chain/*.pem 28 | 29 | # Coverage 30 | coverage.out 31 | coverage.html 32 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | ## 0.9.0 (2022-04-18) 4 | 5 | ### Feature 6 | 7 | - Add an option `--output-format` [#35] 8 | - Add support JSON format [#35] 9 | 10 | ## 0.8.0 (2022-04-08) 11 | 12 | ### Feature 13 | 14 | - Support go 1.18 [#32] 15 | - Support Windows [#32] 16 | - Added `no` as a value for an option --ocsp [#32] 17 | 18 | ## 0.7.0 (2022-01-25) 19 | 20 | ### Feature 21 | 22 | - Add an option --enable-ssl-cert-dir [#30] 23 | 24 | ### Fixed 25 | 26 | - Fix a bug that caused the certificate chain verification to fail if server certificates or intermediate certificates are placed in the system's certificate directory. [#30] 27 | 28 | ## 0.6.0 (2021-10-18) 29 | 30 | ### Feature 31 | 32 | - Add shell completion [#26] 33 | 34 | ### Fixed 35 | 36 | - Verify the certificate of the OCSP authorized responder [#28] 37 | 38 | ## 0.5.1 (2021-09-24) 39 | 40 | ### Fixed 41 | 42 | - If the post-encapsulation boundary in PEM file does not have EOL, an error will occur. 43 | 44 | ## 0.5.0 (2021-09-22) 45 | 46 | ### Feature 47 | 48 | - Add --tls-min-version option [#23] 49 | - Support go 1.17 [#22] 50 | 51 | ## 0.4.3 (2021-09-09) 52 | 53 | ### Fixed 54 | 55 | - If there is an empty line at the end of the PEM file, a panic will occur. [#20] 56 | 57 | ## 0.4.2 (2021-07-24) 58 | 59 | ### Fixed 60 | 61 | - Fix an OCSP-related issue [#19] 62 | 63 | ## 0.4.1 (2021-07-13) 64 | 65 | ### Fixed 66 | 67 | - Remove an unnecessary log output [#18] 68 | - Fix comments [#17] 69 | 70 | ## 0.4.0 (2021-07-13) 71 | 72 | - First public release 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, HEARTBEATS Corporation. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | * Neither the name of the HEARTBEATS Corporation nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAME := check-tls-cert 2 | 3 | .PHONY: all 4 | all: build 5 | 6 | .PHONY: deps 7 | deps: 8 | go get -v 9 | 10 | .PHONY: build 11 | build: deps 12 | go build check-tls-cert.go 13 | 14 | .PHONY: install 15 | install: deps 16 | go install check-tls-cert.go 17 | 18 | .PHONY: build-linux 19 | build-linux: 20 | GOOS=linux GOARCH=amd64 go build -o dist/linux_amd64/check-tls-cert check-tls-cert.go 21 | 22 | .PHONY: build-windows 23 | build-windows: 24 | GOOS=windows GOARCH=amd64 go build -o dist/windows_amd64/check-tls-cert.exe check-tls-cert.go 25 | 26 | .PHONY: clean 27 | clean: 28 | go clean 29 | 30 | .PHONY: tag 31 | tag: 32 | bash scripts/bumpup.sh 33 | 34 | .PHONY: test 35 | test: prepare-test-cert 36 | go test -v ./... 37 | 38 | .PHONY: coverage 39 | coverage: prepare-test-cert 40 | go test ./... -coverprofile=coverage.out 41 | go tool cover -func=coverage.out 42 | go tool cover -html=coverage.out -o coverage.html 43 | 44 | .PHONY: prepare-test-once 45 | prepare-test-once: 46 | bash scripts/gen-private-key.sh &>/dev/null 47 | bash scripts/gen-root-ca-cert.sh &>/dev/null 48 | bash scripts/gen-expired-cert.sh &>/dev/null 49 | bash scripts/gen-not-yet-valid-cert.sh &>/dev/null 50 | bash scripts/gen-expired-ocsp-cert.sh &>/dev/null 51 | 52 | prepare-test-cert: 53 | bash scripts/gen-valid-cert.sh &>/dev/null 54 | bash scripts/gen-chain-cert.sh &>/dev/null 55 | bash scripts/gen-ocsp-cert.sh &>/dev/null 56 | -------------------------------------------------------------------------------- /check-tls-cert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import "github.com/heartbeatsjp/check-tls-cert/cmd" 8 | 9 | func main() { 10 | cmd.Execute() 11 | } 12 | -------------------------------------------------------------------------------- /checker/certificate.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/x509" 9 | ) 10 | 11 | // CertificateChecker represents a certificate information. 12 | type CertificateChecker struct { 13 | name string 14 | status Status 15 | message string 16 | details *CertificateDetails 17 | } 18 | 19 | func NewCertificateChecker(cert *x509.Certificate) *CertificateChecker { 20 | const name = "Certificate" 21 | message := "the certificate information is as follows" 22 | 23 | details := NewCertificateDetails(cert) 24 | 25 | return &CertificateChecker{ 26 | name: name, 27 | status: INFO, 28 | message: message, 29 | details: details, 30 | } 31 | } 32 | 33 | func (c *CertificateChecker) Name() string { 34 | return c.name 35 | } 36 | 37 | func (c *CertificateChecker) Status() Status { 38 | return c.status 39 | } 40 | 41 | func (c *CertificateChecker) Message() string { 42 | return c.message 43 | } 44 | 45 | func (c *CertificateChecker) Details() interface{} { 46 | return c.details 47 | } 48 | 49 | func (c *CertificateChecker) PrintName() { 50 | printCheckerName(c) 51 | } 52 | 53 | func (c *CertificateChecker) PrintStatus() { 54 | printCheckerStatus(c) 55 | } 56 | 57 | func (c *CertificateChecker) PrintDetails() { 58 | printCertificate(4, c.details) 59 | } 60 | -------------------------------------------------------------------------------- /checker/certificatechain.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "bytes" 9 | "crypto/x509" 10 | 11 | "github.com/heartbeatsjp/check-tls-cert/x509util" 12 | ) 13 | 14 | // CertificateChainChecker represents wheather certificate chains are valid. 15 | type CertificateChainChecker struct { 16 | name string 17 | status Status 18 | message string 19 | details CertificateChainDetails 20 | } 21 | 22 | func NewCertificateChainChecker(certs []*x509.Certificate, rootCertPool *x509.CertPool) *CertificateChainChecker { 23 | const name = "Certificate Chains" 24 | 25 | var ( 26 | certInfoChains [][]CertificateInfo 27 | certChains [][]*x509.Certificate 28 | err error 29 | ) 30 | 31 | status := OK 32 | message := "the certificate chain is valid" 33 | 34 | serverCert := certs[0] 35 | var intermediateCerts []*x509.Certificate 36 | if len(certs) > 1 { 37 | intermediateCerts = certs[1:] 38 | } 39 | 40 | opts := x509.VerifyOptions{ 41 | Intermediates: x509util.GetIntermediateCertPool(intermediateCerts), 42 | Roots: rootCertPool, 43 | CurrentTime: currentTime, 44 | } 45 | 46 | certChains, err = serverCert.Verify(opts) 47 | if err != nil { 48 | // When Verify() fails, the status of each certificate is unknown. 49 | // So, it builds a certificate chain. 50 | certChains = x509util.BuildCertificateChains(certs, rootCertPool, currentTime) 51 | status = CRITICAL 52 | } 53 | 54 | for _, chain := range certChains { 55 | var certInfoChain []CertificateInfo 56 | n := len(chain) 57 | if n == 0 { 58 | continue 59 | } 60 | 61 | root := chain[n-1] 62 | if !bytes.Equal(root.RawIssuer, root.RawSubject) { 63 | // If the first certificate is not a root CA, add the root CA information. 64 | certInfo := CertificateInfo{ 65 | CommonName: root.Issuer.CommonName, 66 | Status: INFO, 67 | Message: "a valid root certificate cannot be found, or the certificate chain is broken", 68 | } 69 | certInfoChain = append(certInfoChain, certInfo) 70 | } 71 | 72 | var parent *x509.Certificate 73 | for i := 0; i < n; i++ { 74 | cert := chain[n-i-1] 75 | certInfo := NewCertificateInfo(cert, parent, true) 76 | certInfoChain = append(certInfoChain, certInfo) 77 | parent = cert 78 | } 79 | certInfoChains = append(certInfoChains, certInfoChain) 80 | } 81 | 82 | for _, certInfoChain := range certInfoChains { 83 | for _, certInfo := range certInfoChain { 84 | if certInfo.Status == ERROR { 85 | status = CRITICAL 86 | } 87 | } 88 | } 89 | 90 | if status == CRITICAL { 91 | message = "the certificate chain is invalid" 92 | if err != nil { 93 | message += " / " + err.Error() 94 | } 95 | } 96 | 97 | details := NewCertificateChainDetails(certInfoChains) 98 | 99 | return &CertificateChainChecker{ 100 | name: name, 101 | status: status, 102 | message: message, 103 | details: details, 104 | } 105 | } 106 | 107 | func (c *CertificateChainChecker) Name() string { 108 | return c.name 109 | } 110 | 111 | func (c *CertificateChainChecker) Status() Status { 112 | return c.status 113 | } 114 | 115 | func (c *CertificateChainChecker) Message() string { 116 | return c.message 117 | } 118 | 119 | func (c *CertificateChainChecker) Details() interface{} { 120 | return c.details 121 | } 122 | 123 | func (c *CertificateChainChecker) PrintName() { 124 | printCheckerName(c) 125 | } 126 | 127 | func (c *CertificateChainChecker) PrintStatus() { 128 | printCheckerStatus(c) 129 | } 130 | 131 | func (c *CertificateChainChecker) PrintDetails() { 132 | for _, chain := range c.details { 133 | indent := 4 134 | for _, certInfo := range chain { 135 | printIndentedLine(indent, "- %s: %s", certInfo.Status.ColorString(), certInfo.CommonName) 136 | printKeyValueIfExists(indent+4, "Subject ", certInfo.Subject) 137 | printKeyValueIfExists(indent+4, "Issuer ", certInfo.Issuer) 138 | printKeyValueIfExists(indent+4, "Expiration", certInfo.Expiration) 139 | printKeyValueIfExists(indent+4, "Message ", certInfo.Message) 140 | printKeyValueIfExists(indent+4, "Error ", certInfo.Error) 141 | indent = indent + 2 142 | } 143 | } 144 | } 145 | 146 | type CertificateChainDetails [][]CertificateInfo 147 | 148 | func NewCertificateChainDetails(c [][]CertificateInfo) CertificateChainDetails { 149 | return c 150 | } 151 | -------------------------------------------------------------------------------- /checker/certificatelist.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/x509" 9 | "strings" 10 | ) 11 | 12 | // CertificateListChecker represents wheather peer certificates are valid. 13 | type CertificateListChecker struct { 14 | name string 15 | status Status 16 | message string 17 | details CertificateListDetails 18 | } 19 | 20 | func NewCertificateListChecker(certs []*x509.Certificate) *CertificateListChecker { 21 | const name = "Peer Certificate List" 22 | 23 | n := len(certs) 24 | certInfoList := make([]CertificateInfo, n) 25 | 26 | var parent *x509.Certificate 27 | for i := 0; i < n; i++ { 28 | cert := certs[n-i-1] 29 | certInfo := NewCertificateInfo(cert, parent, false) 30 | certInfoList[n-i-1] = certInfo 31 | parent = cert 32 | } 33 | 34 | status := OK 35 | message := "certificates are valid" 36 | var messages []string 37 | 38 | for _, certInfo := range certInfoList { 39 | if certInfo.Status == ERROR { 40 | status = CRITICAL 41 | messages = append(messages, certInfo.Error) 42 | } 43 | } 44 | 45 | if len(messages) > 0 { 46 | message = strings.Join(messages, " / ") 47 | } 48 | 49 | if len(certInfoList) == 0 { 50 | status = CRITICAL 51 | message = "no certificate" 52 | } 53 | 54 | details := NewCertificateListDetails(certInfoList) 55 | 56 | return &CertificateListChecker{ 57 | name: name, 58 | status: status, 59 | message: message, 60 | details: details, 61 | } 62 | } 63 | 64 | func (c *CertificateListChecker) Name() string { 65 | return c.name 66 | } 67 | 68 | func (c *CertificateListChecker) Status() Status { 69 | return c.status 70 | } 71 | 72 | func (c *CertificateListChecker) Message() string { 73 | return c.message 74 | } 75 | 76 | func (c *CertificateListChecker) Details() interface{} { 77 | return c.details 78 | } 79 | 80 | func (c *CertificateListChecker) PrintName() { 81 | printCheckerName(c) 82 | } 83 | 84 | func (c *CertificateListChecker) PrintStatus() { 85 | printCheckerStatus(c) 86 | } 87 | 88 | func (c *CertificateListChecker) PrintDetails() { 89 | for _, certInfo := range c.details { 90 | printIndentedLine(4, "- %s: %s", certInfo.Status.ColorString(), certInfo.CommonName) 91 | printKeyValueIfExists(8, "Subject ", certInfo.Subject) 92 | printKeyValueIfExists(8, "Issuer ", certInfo.Issuer) 93 | printKeyValueIfExists(8, "Expiration", certInfo.Expiration) 94 | printKeyValueIfExists(8, "Message ", certInfo.Message) 95 | printKeyValueIfExists(8, "Error ", certInfo.Error) 96 | } 97 | } 98 | 99 | type CertificateListDetails []CertificateInfo 100 | 101 | func NewCertificateListDetails(list []CertificateInfo) CertificateListDetails { 102 | return list 103 | } 104 | -------------------------------------------------------------------------------- /checker/fmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "os" 11 | "strings" 12 | ) 13 | 14 | // output is an io.Writer. It's os.Stdout by default. 15 | var output io.Writer 16 | 17 | func init() { 18 | output = os.Stdout 19 | } 20 | 21 | // SetOutput sets the output. 22 | func SetOutput(w io.Writer) { 23 | output = w 24 | } 25 | 26 | // GetOutput gets the output. 27 | func GetOutput() io.Writer { 28 | return output 29 | } 30 | 31 | // Print formats using the default formats for its operands and writes to the specified output. 32 | // Spaces are added between operands when neither is a string. 33 | // It returns the number of bytes written and any write error encountered. 34 | func Print(a ...interface{}) (n int, err error) { 35 | return fmt.Fprint(output, a...) 36 | } 37 | 38 | // Printf formats according to a format specifier and writes to the specified output. 39 | // It returns the number of bytes written and any write error encountered. 40 | func Printf(format string, a ...interface{}) (n int, err error) { 41 | return fmt.Fprintf(output, format, a...) 42 | } 43 | 44 | // Println formats using the default formats for its operands and writes to the specified output. 45 | // Spaces are always added between operands and a newline is appended. 46 | // It returns the number of bytes written and any write error encountered. 47 | func Println(a ...interface{}) (n int, err error) { 48 | return fmt.Fprintln(output, a...) 49 | } 50 | 51 | // printIndentedLine writes an indented line. 52 | func printIndentedLine(indent int, format string, a ...interface{}) { 53 | var indentString = strings.Repeat(" ", indent) 54 | Print(indentString) 55 | Printf(format, a...) 56 | Print("\n") 57 | } 58 | 59 | // printKeyValueIfExists writes the line like `key: value` if a value exists. 60 | func printKeyValueIfExists(indent int, key, value string) { 61 | if value == "" { 62 | return 63 | } 64 | var indentString = strings.Repeat(" ", indent) 65 | Print(indentString) 66 | Print(key) 67 | Print(": ") 68 | Print(value) 69 | Print("\n") 70 | } 71 | 72 | // printKeyValueIfExists writes the line like `key:\n value\n...` if values exists. 73 | func printKeyValuesIfExists(indent int, key string, values []string) { 74 | if values == nil { 75 | return 76 | } 77 | var indentString = strings.Repeat(" ", indent) 78 | Print(indentString) 79 | Print(key) 80 | Print(":\n") 81 | for _, value := range values { 82 | Print(indentString) 83 | Print(" ") 84 | Print(value) 85 | Print("\n") 86 | } 87 | } 88 | 89 | // printKey writes the line like `key:`. 90 | func printKey(indent int, key string) { 91 | var indentString = strings.Repeat(" ", indent) 92 | Print(indentString) 93 | Print(key) 94 | Print(":\n") 95 | } 96 | -------------------------------------------------------------------------------- /checker/fmt_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker_test 6 | 7 | import ( 8 | "os" 9 | "strings" 10 | "testing" 11 | 12 | "github.com/heartbeatsjp/check-tls-cert/checker" 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | func TestOutput(t *testing.T) { 17 | assert := assert.New(t) 18 | 19 | checker.SetOutput(os.Stdout) 20 | assert.Equal(os.Stdout, checker.GetOutput()) 21 | } 22 | 23 | func TestPrint(t *testing.T) { 24 | assert := assert.New(t) 25 | w := strings.Builder{} 26 | checker.SetOutput(&w) 27 | 28 | checker.Print("TEST") 29 | assert.Equal("TEST", w.String()) 30 | } 31 | 32 | func TestPrintf(t *testing.T) { 33 | assert := assert.New(t) 34 | w := strings.Builder{} 35 | checker.SetOutput(&w) 36 | 37 | checker.Printf("TEST") 38 | assert.Equal("TEST", w.String()) 39 | } 40 | 41 | func TestPrintln(t *testing.T) { 42 | assert := assert.New(t) 43 | w := strings.Builder{} 44 | checker.SetOutput(&w) 45 | 46 | checker.Println("TEST") 47 | assert.Equal("TEST\n", w.String()) 48 | } 49 | -------------------------------------------------------------------------------- /checker/hostname.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/x509" 9 | "fmt" 10 | ) 11 | 12 | // HostnameChecker represents whether a hostname is valid for a certificate. 13 | type HostnameChecker struct { 14 | name string 15 | status Status 16 | message string 17 | details *HostnameDetails 18 | } 19 | 20 | func NewHostnameChecker(hostname string, cert *x509.Certificate) *HostnameChecker { 21 | const name = "Hostname" 22 | 23 | var ( 24 | status Status 25 | message string 26 | ) 27 | 28 | err := cert.VerifyHostname(hostname) 29 | if err != nil { 30 | status = CRITICAL 31 | message = fmt.Sprintf("the hostname '%s' is invalid for the certificate / %s", hostname, err.Error()) 32 | } else { 33 | status = OK 34 | message = fmt.Sprintf("the hostname '%s' is valid for the certificate", hostname) 35 | } 36 | 37 | details := NewHostnameDetails(cert) 38 | 39 | return &HostnameChecker{ 40 | name: name, 41 | status: status, 42 | message: message, 43 | details: details, 44 | } 45 | } 46 | 47 | func (c *HostnameChecker) Name() string { 48 | return c.name 49 | } 50 | 51 | func (c *HostnameChecker) Status() Status { 52 | return c.status 53 | } 54 | 55 | func (c *HostnameChecker) Message() string { 56 | return c.message 57 | } 58 | 59 | func (c *HostnameChecker) Details() interface{} { 60 | return c.details 61 | } 62 | 63 | func (c *HostnameChecker) PrintName() { 64 | printCheckerName(c) 65 | } 66 | 67 | func (c *HostnameChecker) PrintStatus() { 68 | printCheckerStatus(c) 69 | } 70 | 71 | func (c *HostnameChecker) PrintDetails() { 72 | printKeyValueIfExists(4, "Common Name", c.details.CommonName) 73 | if len(c.details.SubjectAltName) > 0 { 74 | printSubjectAltName(4, c.details.SubjectAltName) 75 | } 76 | } 77 | 78 | type HostnameDetails struct { 79 | CommonName string `json:"commonName"` 80 | SubjectAltName []subjectAltName `json:"subjectAltName,omitempty"` 81 | } 82 | 83 | func NewHostnameDetails(cert *x509.Certificate) *HostnameDetails { 84 | return &HostnameDetails{ 85 | CommonName: cert.Subject.CommonName, 86 | SubjectAltName: getSubjectAltNames(cert), 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /checker/hostname_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker_test 6 | 7 | import ( 8 | "strings" 9 | "testing" 10 | "time" 11 | 12 | "github.com/heartbeatsjp/check-tls-cert/checker" 13 | "github.com/heartbeatsjp/check-tls-cert/x509util" 14 | "github.com/stretchr/testify/assert" 15 | ) 16 | 17 | func TestNewHostnameChecker(t *testing.T) { 18 | var ( 19 | c checker.Checker 20 | ) 21 | assert := assert.New(t) 22 | w := strings.Builder{} 23 | checker.SetOutput(&w) 24 | checker.SetVerbose(2) 25 | checker.SetDNType(x509util.StrictDN) 26 | checker.SetCurrentTime(time.Now()) 27 | 28 | // Subject: CN=server-a.test 29 | certFile := "../test/testdata/pki/cert/valid/server-a-rsa.pem" 30 | certs, _ := x509util.ParseCertificateFiles(certFile) 31 | cert := certs[0] 32 | 33 | // empty hostname 34 | // 35 | // CRITICAL: the hostname '' is invalid for the certificate 36 | // Common Name: server-a.test 37 | // Subject Alternative Name: 38 | // DNS: server-a.test 39 | // DNS: www.server-a.test 40 | c = checker.NewHostnameChecker("", cert) 41 | 42 | w.Reset() 43 | c.PrintStatus() 44 | assert.EqualValues(checker.CRITICAL, c.Status()) 45 | assert.Contains(c.Message(), "the hostname '' is invalid for the certificate") 46 | assert.Contains(w.String(), "CRITICAL: the hostname '' is invalid for the certificate") 47 | 48 | w.Reset() 49 | c.PrintDetails() 50 | assert.Contains(w.String(), ` Common Name: server-a.test 51 | Subject Alternative Name: 52 | DNS: server-a.test 53 | DNS: www.server-a.test`) 54 | 55 | // invalid hostname 56 | // 57 | // CRITICAL: the hostname 'server-b.test' is invalid for the certificate / x509: certificate is valid for server-a.test, www.server-a.test, not server-b.test 58 | // Common Name: server-a.test 59 | // Subject Alternative Name: 60 | // DNS: server-a.test 61 | // DNS: www.server-a.test 62 | c = checker.NewHostnameChecker("server-b.test", cert) 63 | 64 | w.Reset() 65 | c.PrintStatus() 66 | assert.EqualValues(checker.CRITICAL, c.Status()) 67 | assert.Contains(c.Message(), "the hostname 'server-b.test' is invalid for the certificate") 68 | assert.Contains(w.String(), "CRITICAL: the hostname 'server-b.test' is invalid for the certificate") 69 | 70 | w.Reset() 71 | c.PrintDetails() 72 | assert.Contains(w.String(), ` Common Name: server-a.test 73 | Subject Alternative Name: 74 | DNS: server-a.test 75 | DNS: www.server-a.test`) 76 | 77 | // valid hostname 78 | // 79 | // OK: the hostname 'server-a.test' is valid for the certificate 80 | // Common Name: server-a.test 81 | // Subject Alternative Name: 82 | // DNS: server-a.test 83 | // DNS: www.server-a.test 84 | c = checker.NewHostnameChecker("server-a.test", cert) 85 | 86 | w.Reset() 87 | c.PrintStatus() 88 | assert.EqualValues(checker.OK, c.Status()) 89 | assert.EqualValues("the hostname 'server-a.test' is valid for the certificate", c.Message()) 90 | assert.Contains(w.String(), "OK: the hostname 'server-a.test' is valid for the certificate") 91 | 92 | w.Reset() 93 | c.PrintDetails() 94 | assert.Contains(w.String(), ` Common Name: server-a.test 95 | Subject Alternative Name: 96 | DNS: server-a.test 97 | DNS: www.server-a.test`) 98 | 99 | } 100 | 101 | func TestHostnameChecker(t *testing.T) { 102 | assert := assert.New(t) 103 | w := strings.Builder{} 104 | checker.SetOutput(&w) 105 | checker.SetVerbose(2) 106 | checker.SetDNType(x509util.StrictDN) 107 | checker.SetCurrentTime(time.Now()) 108 | 109 | cert, _ := x509util.ParseCertificateFile("../test/testdata/pki/cert/valid/server-a-rsa.pem") 110 | c := checker.NewHostnameChecker("server-a.test", cert) 111 | assert.Equal("Hostname", c.Name()) 112 | assert.Equal(checker.OK, c.Status()) 113 | assert.Equal("the hostname 'server-a.test' is valid for the certificate", c.Message()) 114 | assert.Equal("server-a.test", c.Details().(*checker.HostnameDetails).CommonName) 115 | 116 | c.PrintName() 117 | assert.Equal("[Hostname]\n", w.String()) 118 | 119 | w.Reset() 120 | c.PrintStatus() 121 | assert.Equal("OK: the hostname 'server-a.test' is valid for the certificate\n", w.String()) 122 | 123 | w.Reset() 124 | c.PrintDetails() 125 | assert.Contains(w.String(), ` Common Name: server-a.test 126 | Subject Alternative Name: 127 | DNS: server-a.test 128 | DNS: www.server-a.test`) 129 | } 130 | -------------------------------------------------------------------------------- /checker/keypair.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/ecdsa" 9 | "crypto/ed25519" 10 | "crypto/rsa" 11 | "crypto/x509" 12 | 13 | "github.com/heartbeatsjp/check-tls-cert/x509util" 14 | ) 15 | 16 | // KeyPairChecker represents wheather a private key is paired with a certificate. 17 | type KeyPairChecker struct { 18 | name string 19 | status Status 20 | message string 21 | details *KeyPairDetails 22 | } 23 | 24 | func NewKeyPairChecker(pubKeyInfoInPrivKey, pubKeyInfo x509util.PublicKeyInfo) *KeyPairChecker { 25 | const name = "Private Key/Certificate Pair" 26 | 27 | status := OK 28 | message := "the private key is paired with the certificate" 29 | 30 | if pubKeyInfoInPrivKey.PublicKeyAlgorithm != pubKeyInfo.PublicKeyAlgorithm { 31 | status = CRITICAL 32 | message = "the public key algorithm does not match between the private Key and the certificate" 33 | } else { 34 | isValid := false 35 | 36 | switch pubKeyInfoInPrivKey.PublicKeyAlgorithm { 37 | case x509.RSA: 38 | pubKeyInPrivKey := pubKeyInfoInPrivKey.Key.(*rsa.PublicKey) 39 | if pubKeyInPrivKey.Equal(pubKeyInfo.Key) { 40 | isValid = true 41 | } 42 | case x509.ECDSA: 43 | pubKeyInfoInPrivKey := pubKeyInfoInPrivKey.Key.(*ecdsa.PublicKey) 44 | if pubKeyInfoInPrivKey.Equal(pubKeyInfo.Key) { 45 | isValid = true 46 | } 47 | case x509.Ed25519: 48 | pubKeyInPrivKey := pubKeyInfoInPrivKey.Key.(ed25519.PublicKey) 49 | if pubKeyInPrivKey.Equal(pubKeyInfo.Key) { 50 | isValid = true 51 | } 52 | default: 53 | } 54 | 55 | if !isValid { 56 | status = CRITICAL 57 | message = "the private key is not paired with a certificate" 58 | } 59 | } 60 | 61 | details := NewKeyPairDetails(pubKeyInfoInPrivKey, pubKeyInfo) 62 | 63 | return &KeyPairChecker{ 64 | name: name, 65 | status: status, 66 | message: message, 67 | details: details, 68 | } 69 | } 70 | 71 | func (c *KeyPairChecker) Name() string { 72 | return c.name 73 | } 74 | 75 | func (c *KeyPairChecker) Status() Status { 76 | return c.status 77 | } 78 | 79 | func (c *KeyPairChecker) Message() string { 80 | return c.message 81 | } 82 | 83 | func (c *KeyPairChecker) Details() interface{} { 84 | return c.details 85 | } 86 | 87 | func (c *KeyPairChecker) PrintName() { 88 | printCheckerName(c) 89 | } 90 | 91 | func (c *KeyPairChecker) PrintStatus() { 92 | printCheckerStatus(c) 93 | } 94 | 95 | func (c *KeyPairChecker) PrintDetails() { 96 | printIndentedLine(4, "%s:", c.details.PrivateKey.Name) 97 | printPublicKey(4, c.details.PrivateKey) 98 | 99 | printIndentedLine(4, "%s:", c.details.Certificate.Name) 100 | printPublicKey(4, c.details.Certificate) 101 | 102 | printIndentedLine(4, "") 103 | if verbose == 1 { 104 | printIndentedLine(4, "To get the full public key, use the '-vv' option.") 105 | } 106 | if verbose >= 2 { 107 | printIndentedLine(4, "The public key information can be obtained with the following command:") 108 | printIndentedLine(4, " openssl pkey -in PRIVATE_KEY.pem -noout -text_pub") 109 | printIndentedLine(4, " openssl x509 -in CERTIFICATE.pem -noout -pubkey | openssl pkey -pubin -text_pub -noout") 110 | printIndentedLine(4, " openssl x509 -in CERTIFICATE.pem -noout -text") 111 | } 112 | } 113 | 114 | type KeyPairDetails struct { 115 | PrivateKey *publicKeyInfo `json:"privateKey"` 116 | Certificate *publicKeyInfo `json:"certificate"` 117 | } 118 | 119 | func NewKeyPairDetails(pubKeyInfoInPrivKey, pubKeyInfo x509util.PublicKeyInfo) *KeyPairDetails { 120 | omit := true 121 | if verbose > 1 { 122 | omit = false 123 | } 124 | return &KeyPairDetails{ 125 | PrivateKey: getPublicKeyInfo(pubKeyInfoInPrivKey, omit), 126 | Certificate: getPublicKeyInfo(pubKeyInfo, omit), 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /checker/ocspresponder.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/x509" 9 | 10 | "github.com/heartbeatsjp/check-tls-cert/ocsputil" 11 | ) 12 | 13 | // OCSPResponderChecker represents wheather the response from OCSP Responder is valie. 14 | type OCSPResponderChecker struct { 15 | name string 16 | status Status 17 | message string 18 | details *OCSPResponseDetails 19 | } 20 | 21 | func NewOCSPResponderChecker(targetCert *x509.Certificate, issuer *x509.Certificate, intermediateCerts []*x509.Certificate, rootCertPool *x509.CertPool) *OCSPResponderChecker { 22 | const name = "OCSP Responder" 23 | 24 | var responseInfo *OCSPResponseInfo 25 | 26 | var ( 27 | status Status 28 | message string 29 | ) 30 | 31 | ocspServer, ocspResponse, err := ocsputil.GetOCSPResponse(targetCert, issuer) 32 | if ocspResponse != nil { 33 | if issuer != nil { 34 | responseInfo = NewOCSPResponseInfo(ocspResponse, targetCert, issuer, intermediateCerts, rootCertPool) 35 | status = responseInfo.Status 36 | message = responseInfo.Message 37 | } else { 38 | status = CRITICAL 39 | message = "ocsp: no issuer certificate sent" 40 | responseInfo.ResponseStatus = ocsputil.NoResponseStatus 41 | } 42 | } else if err != nil { 43 | status = INFO 44 | message = "ocsp: " + err.Error() 45 | responseInfo.ResponseStatus = ocsputil.NoResponseStatus 46 | } else { 47 | status = INFO 48 | message = "ocsp: no valid OCSP responders" 49 | responseInfo.ResponseStatus = ocsputil.NoResponseStatus 50 | } 51 | 52 | responseInfo.Server = ocspServer 53 | 54 | details := NewOCSPResponseData(responseInfo) 55 | 56 | return &OCSPResponderChecker{ 57 | name: name, 58 | status: status, 59 | message: message, 60 | details: details, 61 | } 62 | } 63 | 64 | func (c *OCSPResponderChecker) Name() string { 65 | return c.name 66 | } 67 | 68 | func (c *OCSPResponderChecker) Status() Status { 69 | return c.status 70 | } 71 | 72 | func (c *OCSPResponderChecker) Message() string { 73 | return c.message 74 | } 75 | 76 | func (c *OCSPResponderChecker) Details() interface{} { 77 | return c.details 78 | } 79 | 80 | func (c *OCSPResponderChecker) PrintName() { 81 | printCheckerName(c) 82 | } 83 | 84 | func (c *OCSPResponderChecker) PrintStatus() { 85 | printCheckerStatus(c) 86 | } 87 | 88 | func (c *OCSPResponderChecker) PrintDetails() { 89 | printOCSPResponse(c.details) 90 | } 91 | -------------------------------------------------------------------------------- /checker/ocspresponder_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker_test 6 | 7 | import ( 8 | "crypto/tls" 9 | "net" 10 | "strings" 11 | "testing" 12 | "time" 13 | 14 | "github.com/heartbeatsjp/check-tls-cert/checker" 15 | "github.com/heartbeatsjp/check-tls-cert/x509util" 16 | "github.com/stretchr/testify/assert" 17 | ) 18 | 19 | func TestNewOCSPResponderChecker(t *testing.T) { 20 | var ( 21 | c checker.Checker 22 | ) 23 | assert := assert.New(t) 24 | w := strings.Builder{} 25 | checker.SetOutput(&w) 26 | checker.SetVerbose(2) 27 | checker.SetDNType(x509util.StrictDN) 28 | checker.SetCurrentTime(time.Now()) 29 | 30 | hostname := "www.google.com" 31 | tlsConfig := tls.Config{ 32 | ServerName: hostname, 33 | InsecureSkipVerify: true, 34 | SessionTicketsDisabled: true, 35 | } 36 | 37 | dialer := net.Dialer{Timeout: time.Second * time.Duration(5)} 38 | conn, _ := tls.DialWithDialer(&dialer, "tcp4", hostname+":443", &tlsConfig) 39 | defer conn.Close() 40 | connectionState := conn.ConnectionState() 41 | certs := connectionState.PeerCertificates 42 | targetCert := certs[0] 43 | issuer := certs[1] 44 | intermediateCerts := certs[2:] 45 | 46 | // Response status: good 47 | // OK: certificate is valid 48 | // OCSP Responder: ... 49 | // OCSP Response Data: 50 | // OCSP Response Status: success (0x0) 51 | // Cert Status: good 52 | // Produced At: 2021-06-28 06:39:00 +0000 UTC 53 | // This Update: 2021-06-27 06:39:22 +0000 UTC 54 | // Next Update: 2021-06-29 06:39:22 +0000 UTC 55 | // Certificate: 56 | // Issuer : CN=Intermediate CA A RSA 57 | // Subject: CN=Intermediate CA A RSA OCSP Responder 58 | // Validity: 59 | // Not Before: 2021-06-28 06:23:10 +0000 UTC 60 | // Not After : 2022-06-28 06:23:10 +0000 UTC 61 | // Subject Public Key Info: 62 | // Public Key Algorithm: RSA 63 | // RSA Public-Key: (2048 bit) 64 | // Modulus: 65 | // 00:fe:6b:e6:fc:5a:21:e3:34:74:24:cc:73:fb:d4: 66 | // ...(omitted) 67 | // Exponent: 65537 (0x10001) 68 | c = checker.NewOCSPResponderChecker(targetCert, issuer, intermediateCerts, nil) 69 | assert.Equal(checker.OK, c.Status()) 70 | assert.Equal("certificate is valid", c.Message()) 71 | 72 | w.Reset() 73 | c.PrintStatus() 74 | assert.Equal(w.String(), "OK: certificate is valid\n") 75 | 76 | w.Reset() 77 | c.PrintDetails() 78 | assert.Contains(w.String(), ` OCSP Responder:`) 79 | assert.Contains(w.String(), ` OCSP Response Data: 80 | OCSP Response Status: successful (0x0) 81 | Cert Status: good 82 | `) 83 | 84 | } 85 | 86 | func TestOCSPResponderChecker(t *testing.T) { 87 | assert := assert.New(t) 88 | w := strings.Builder{} 89 | checker.SetOutput(&w) 90 | checker.SetVerbose(2) 91 | checker.SetDNType(x509util.StrictDN) 92 | checker.SetCurrentTime(time.Now()) 93 | 94 | hostname := "www.google.com" 95 | tlsConfig := tls.Config{ 96 | ServerName: hostname, 97 | InsecureSkipVerify: true, 98 | SessionTicketsDisabled: true, 99 | } 100 | 101 | dialer := net.Dialer{Timeout: time.Second * time.Duration(5)} 102 | conn, _ := tls.DialWithDialer(&dialer, "tcp4", hostname+":443", &tlsConfig) 103 | defer conn.Close() 104 | connectionState := conn.ConnectionState() 105 | certs := connectionState.PeerCertificates 106 | targetCert := certs[0] 107 | issuer := certs[1] 108 | intermediateCerts := certs[2:] 109 | 110 | c := checker.NewOCSPResponderChecker(targetCert, issuer, intermediateCerts, nil) 111 | assert.Equal("OCSP Responder", c.Name()) 112 | assert.Equal(checker.OK, c.Status()) 113 | assert.Equal("certificate is valid", c.Message()) 114 | assert.Equal("good", c.Details().(*checker.OCSPResponseDetails).OCSPResponseData.CertStatus) 115 | 116 | c.PrintName() 117 | assert.Equal("[OCSP Responder]\n", w.String()) 118 | 119 | w.Reset() 120 | c.PrintStatus() 121 | assert.Equal("OK: certificate is valid\n", w.String()) 122 | 123 | w.Reset() 124 | c.PrintDetails() 125 | assert.Contains(w.String(), ` OCSP Response Data: 126 | OCSP Response Status: successful (0x0) 127 | Cert Status: good 128 | `) 129 | } 130 | -------------------------------------------------------------------------------- /checker/ocspstapling.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/x509" 9 | 10 | "github.com/heartbeatsjp/check-tls-cert/ocsputil" 11 | ) 12 | 13 | // OCSPStaplingChecker represents wheather the response from OCSP Stapling is valid. 14 | type OCSPStaplingChecker struct { 15 | name string 16 | status Status 17 | message string 18 | details *OCSPResponseDetails 19 | } 20 | 21 | // NewOCSPStaplingChecker returns a new OCSPStaplingChecker. 22 | func NewOCSPStaplingChecker(ocspResponse []byte, issuer *x509.Certificate, intermediateCerts []*x509.Certificate, rootCertPool *x509.CertPool, allowNonReponse bool) *OCSPStaplingChecker { 23 | const name = "OCSP Stapling" 24 | 25 | var ( 26 | status Status 27 | message string 28 | responseInfo *OCSPResponseInfo 29 | ) 30 | 31 | if len(ocspResponse) > 0 { 32 | if issuer != nil { 33 | responseInfo = NewOCSPResponseInfo(ocspResponse, nil, issuer, intermediateCerts, rootCertPool) 34 | status = responseInfo.Status 35 | message = responseInfo.Message 36 | } else { 37 | responseInfo = &OCSPResponseInfo{ 38 | ResponseStatus: ocsputil.NoResponseStatus, 39 | } 40 | status = CRITICAL 41 | message = "ocsp: no issuer certificate sent" 42 | } 43 | } else { 44 | if allowNonReponse { 45 | status = INFO 46 | message = "no response sent" 47 | } else { 48 | status = WARNING 49 | message = "ocsp: no response sent" 50 | } 51 | responseInfo = &OCSPResponseInfo{ 52 | ResponseStatus: ocsputil.NoResponseStatus, 53 | } 54 | } 55 | 56 | details := NewOCSPResponseData(responseInfo) 57 | 58 | return &OCSPStaplingChecker{ 59 | name: name, 60 | status: status, 61 | message: message, 62 | details: details, 63 | } 64 | } 65 | 66 | func (c *OCSPStaplingChecker) Name() string { 67 | return c.name 68 | } 69 | 70 | func (c *OCSPStaplingChecker) Status() Status { 71 | return c.status 72 | } 73 | 74 | func (c *OCSPStaplingChecker) Message() string { 75 | return c.message 76 | } 77 | 78 | func (c *OCSPStaplingChecker) Details() interface{} { 79 | return c.details 80 | } 81 | 82 | func (c *OCSPStaplingChecker) PrintName() { 83 | printCheckerName(c) 84 | } 85 | 86 | func (c *OCSPStaplingChecker) PrintStatus() { 87 | printCheckerStatus(c) 88 | } 89 | 90 | func (c *OCSPStaplingChecker) PrintDetails() { 91 | printOCSPResponse(c.details) 92 | } 93 | -------------------------------------------------------------------------------- /checker/summary.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "strings" 9 | ) 10 | 11 | type Summary struct { 12 | name string 13 | status Status 14 | message string 15 | } 16 | 17 | func NewSummary(list []Checker) *Summary { 18 | const name = "Summary" 19 | 20 | var messages []string 21 | 22 | status := OK 23 | message := "all checks have been passed" 24 | 25 | for _, c := range list { 26 | switch c.Status() { 27 | case CRITICAL: 28 | if status != CRITICAL && status != UNKNOWN { 29 | status = c.Status() 30 | } 31 | messages = append(messages, c.Message()) 32 | case WARNING: 33 | if status != WARNING && status != CRITICAL && status != UNKNOWN { 34 | status = c.Status() 35 | } 36 | messages = append(messages, c.Message()) 37 | case UNKNOWN: 38 | status = c.Status() 39 | messages = append(messages, c.Message()) 40 | default: 41 | } 42 | } 43 | 44 | if status != OK { 45 | message = strings.Join(messages, " / ") 46 | } 47 | 48 | return &Summary{ 49 | name: name, 50 | status: status, 51 | message: message, 52 | } 53 | } 54 | 55 | func NewErrorSummary(err error) *Summary { 56 | const name = "Summary" 57 | 58 | return &Summary{ 59 | name: name, 60 | status: UNKNOWN, 61 | message: err.Error(), 62 | } 63 | } 64 | 65 | func (s *Summary) Name() string { 66 | return s.name 67 | } 68 | 69 | func (s *Summary) Status() Status { 70 | return s.status 71 | } 72 | 73 | func (s *Summary) Message() string { 74 | return s.message 75 | } 76 | 77 | func (s *Summary) Details() interface{} { 78 | return nil 79 | } 80 | 81 | func (s *Summary) PrintName() { 82 | printCheckerName(s) 83 | } 84 | 85 | func (s *Summary) PrintStatus() { 86 | printCheckerStatus(s) 87 | } 88 | 89 | func (s *Summary) PrintDetails() { 90 | // print nothing 91 | } 92 | -------------------------------------------------------------------------------- /checker/summary_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker_test 6 | 7 | import ( 8 | "errors" 9 | "strings" 10 | "testing" 11 | "time" 12 | 13 | "github.com/heartbeatsjp/check-tls-cert/checker" 14 | "github.com/heartbeatsjp/check-tls-cert/x509util" 15 | "github.com/stretchr/testify/assert" 16 | ) 17 | 18 | func TestNewSummary(t *testing.T) { 19 | var ( 20 | checkerList []checker.Checker 21 | c checker.Checker 22 | summary *checker.Summary 23 | ) 24 | assert := assert.New(t) 25 | w := strings.Builder{} 26 | checker.SetOutput(&w) 27 | checker.SetVerbose(2) 28 | checker.SetDNType(x509util.StrictDN) 29 | checker.SetCurrentTime(time.Now()) 30 | 31 | // This certificate will expire in 365 days. 32 | certFile := "../test/testdata/pki/cert/valid/server-a-rsa.pem" 33 | certs, _ := x509util.ParseCertificateFiles(certFile) 34 | cert := certs[0] 35 | 36 | // OK: the certificate will expire in 365 days on 2022-06-22 16:10:14 +0900 37 | checkerList = []checker.Checker{} 38 | c = checker.NewValidityChecker(cert, 0, 0) 39 | checkerList = append(checkerList, c) 40 | summary = checker.NewSummary(checkerList) 41 | assert.Equal(checker.OK, summary.Status()) 42 | assert.Equal("all checks have been passed", summary.Message()) 43 | 44 | w.Reset() 45 | summary.PrintStatus() 46 | assert.Equal("OK: all checks have been passed\n", w.String()) 47 | 48 | // WARNING: the certificate will expire in 365 days on 2022-06-22 16:10:14 +0900 49 | checkerList = []checker.Checker{} 50 | c = checker.NewValidityChecker(cert, 366, 364) 51 | checkerList = append(checkerList, c) 52 | summary = checker.NewSummary(checkerList) 53 | assert.Equal(checker.WARNING, summary.Status()) 54 | assert.Contains(summary.Message(), "the certificate will expire in ") 55 | 56 | w.Reset() 57 | summary.PrintStatus() 58 | assert.Contains(w.String(), "WARNING: the certificate will expire ") 59 | 60 | // CRITICAL: the certificate will expire in 365 days on 2022-06-22 16:10:14 +0900 61 | checkerList = []checker.Checker{} 62 | c = checker.NewValidityChecker(cert, 368, 366) 63 | checkerList = append(checkerList, c) 64 | summary = checker.NewSummary(checkerList) 65 | assert.Equal(checker.CRITICAL, summary.Status()) 66 | assert.Contains(summary.Message(), "the certificate will expire in ") 67 | 68 | w.Reset() 69 | summary.PrintStatus() 70 | assert.Contains(w.String(), "CRITICAL: the certificate will expire ") 71 | } 72 | 73 | func TestNewErrorSummary(t *testing.T) { 74 | assert := assert.New(t) 75 | w := strings.Builder{} 76 | checker.SetOutput(&w) 77 | checker.SetVerbose(2) 78 | checker.SetDNType(x509util.StrictDN) 79 | checker.SetCurrentTime(time.Now()) 80 | 81 | summary := checker.NewErrorSummary(errors.New("error message")) 82 | assert.Equal(checker.UNKNOWN, summary.Status()) 83 | assert.Equal("error message", summary.Message()) 84 | 85 | w.Reset() 86 | summary.PrintStatus() 87 | assert.Equal("UNKNOWN: error message\n", w.String()) 88 | } 89 | 90 | func TestSummary(t *testing.T) { 91 | var ( 92 | checkerList []checker.Checker 93 | c checker.Checker 94 | ) 95 | assert := assert.New(t) 96 | w := strings.Builder{} 97 | checker.SetOutput(&w) 98 | checker.SetVerbose(2) 99 | checker.SetDNType(x509util.StrictDN) 100 | checker.SetCurrentTime(time.Now()) 101 | 102 | certFile := "../test/testdata/pki/cert/valid/server-a-rsa.pem" 103 | certs, _ := x509util.ParseCertificateFiles(certFile) 104 | cert := certs[0] 105 | 106 | c = checker.NewValidityChecker(cert, 0, 0) 107 | checkerList = append(checkerList, c) 108 | 109 | summary := checker.NewSummary(checkerList) 110 | assert.Equal("Summary", summary.Name()) 111 | assert.Equal(checker.OK, summary.Status()) 112 | assert.Equal("all checks have been passed", summary.Message()) 113 | assert.Nil(summary.Details()) 114 | 115 | w.Reset() 116 | summary.PrintName() 117 | assert.Equal("[Summary]\n", w.String()) 118 | 119 | w.Reset() 120 | summary.PrintStatus() 121 | assert.Equal("OK: all checks have been passed\n", w.String()) 122 | 123 | w.Reset() 124 | summary.PrintDetails() 125 | assert.Equal("", w.String()) 126 | } 127 | -------------------------------------------------------------------------------- /checker/validity.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package checker 6 | 7 | import ( 8 | "crypto/x509" 9 | 10 | "github.com/heartbeatsjp/check-tls-cert/x509util" 11 | ) 12 | 13 | const timeFormat = "2006-01-02 15:04:05 -0700" 14 | 15 | // ValidityChecker represents wheather the validity of a certificate is valid. 16 | type ValidityChecker struct { 17 | name string 18 | status Status 19 | message string 20 | details *ValidityDetails 21 | } 22 | 23 | // NewValidityChecker returns a new ValidityChecker. 24 | func NewValidityChecker(cert *x509.Certificate, warning int, critical int) *ValidityChecker { 25 | const name = "Validity" 26 | 27 | var ( 28 | status Status 29 | message string 30 | err error 31 | ) 32 | 33 | //lint:ignore SA4006 It was detected by mistake. 34 | if message, err = x509util.VerifyValidity(cert, critical, currentTime); err != nil { 35 | status = CRITICAL 36 | message = err.Error() 37 | } else if message, err = x509util.VerifyValidity(cert, warning, currentTime); err != nil { 38 | status = WARNING 39 | message = err.Error() 40 | } else { 41 | status = OK 42 | } 43 | 44 | details := NewValidityDetails(cert) 45 | 46 | return &ValidityChecker{ 47 | name: name, 48 | status: status, 49 | message: message, 50 | details: details, 51 | } 52 | } 53 | 54 | func (c *ValidityChecker) Name() string { 55 | return c.name 56 | } 57 | 58 | func (c *ValidityChecker) Status() Status { 59 | return c.status 60 | } 61 | 62 | func (c *ValidityChecker) Message() string { 63 | return c.message 64 | } 65 | 66 | func (c *ValidityChecker) Details() interface{} { 67 | return c.details 68 | } 69 | 70 | func (c *ValidityChecker) PrintName() { 71 | printCheckerName(c) 72 | } 73 | 74 | func (c *ValidityChecker) PrintStatus() { 75 | printCheckerStatus(c) 76 | } 77 | 78 | func (c *ValidityChecker) PrintDetails() { 79 | printKeyValueIfExists(4, "Not Before", c.details.NotBefore) 80 | printKeyValueIfExists(4, "Not After ", c.details.NotAfter) 81 | } 82 | 83 | // ValidityDetails is the validity of a certificate. 84 | type ValidityDetails struct { 85 | NotBefore string `json:"notBefore"` 86 | NotAfter string `json:"notAfter"` 87 | } 88 | 89 | // NewValidityDetails returns a new ValidityDetails. 90 | func NewValidityDetails(cert *x509.Certificate) *ValidityDetails { 91 | return &ValidityDetails{ 92 | NotBefore: cert.NotBefore.Local().Format(timeFormat), 93 | NotAfter: cert.NotAfter.Local().Format(timeFormat), 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /cmd/file.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmd 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | 11 | "github.com/heartbeatsjp/check-tls-cert/checker" 12 | filecmd "github.com/heartbeatsjp/check-tls-cert/internal/file" 13 | "github.com/mitchellh/go-homedir" 14 | "github.com/spf13/cobra" 15 | ) 16 | 17 | var ( 18 | keyFile string 19 | certFile string 20 | chainFile string 21 | caFile string 22 | passwordFile string 23 | fileCmdOptions filecmd.FileCommandOptions 24 | 25 | fileCmd = &cobra.Command{ 26 | Use: "file", 27 | Short: "Checks TLS certificate files.", 28 | PreRunE: func(cmd *cobra.Command, args []string) error { 29 | keyFile, _ = homedir.Expand(keyFile) 30 | certFile, _ = homedir.Expand(certFile) 31 | chainFile, _ = homedir.Expand(chainFile) 32 | passwordFile, _ = homedir.Expand(passwordFile) 33 | 34 | fileCmdOptions = filecmd.FileCommandOptions{ 35 | Hostname: hostname, 36 | KeyFile: keyFile, 37 | CertFile: certFile, 38 | ChainFile: chainFile, 39 | CAFile: caFile, 40 | PasswordFile: passwordFile, 41 | Warning: warning, 42 | Critical: critical, 43 | RootFile: rootFile, 44 | EnableSSLCertDir: enableSSLCertDir, 45 | OutputFormat: outputFormat, 46 | } 47 | 48 | return nil 49 | }, 50 | RunE: func(cmd *cobra.Command, args []string) error { 51 | code, err := filecmd.Run(fileCmdOptions) 52 | if err != nil { 53 | switch outputFormat { 54 | case checker.JSONFormat: 55 | r := checker.NewResult(checker.NewErrorSummary(err), nil) 56 | r.PrintJSON() 57 | os.Exit(checker.UNKNOWN.Code()) 58 | default: 59 | fmt.Printf("Error: %s\n", err.Error()) 60 | os.Exit(checker.UNKNOWN.Code()) 61 | } 62 | return err 63 | } 64 | os.Exit(code) 65 | return nil 66 | }, 67 | } 68 | ) 69 | 70 | func init() { 71 | fileCmd.Flags().StringVarP(&hostname, "hostname", "H", "", "`hostname` for verifying certificate. (required)") 72 | fileCmd.MarkFlagRequired("hostname") 73 | fileCmd.Flags().StringVarP(&keyFile, "key-file", "k", "", "private key `file`. (required)") 74 | fileCmd.MarkFlagRequired("key-file") 75 | fileCmd.Flags().StringVarP(&certFile, "cert-file", "f", "", "certificates `file`. It includes a server certificate and intermediate certificates. (required)") 76 | fileCmd.MarkFlagRequired("cert-file") 77 | fileCmd.Flags().StringVarP(&chainFile, "chain-file", "C", "", "certificate chain `file`. It includes intermediate certificates. Used for the SSLCertificateChainFile directive in old Apache HTTP Server.") 78 | fileCmd.Flags().StringVar(&caFile, "ca-file", "", "trusted CA certificates `file`. It includes intermediate certificates and a root certificate. Used for the ssl_trusted_certificate directive in nginx and the SSLCACertificateFile directive in Apache HTTP Server.") 79 | fileCmd.Flags().StringVarP(&passwordFile, "password-file", "P", "", "password `file` for the private key file if the private key file is encrypted. If it is not specified, you will be prompted to enter the password.") 80 | fileCmd.Flags().IntVarP(&warning, "warning", "w", 28, "warning threshold in `days` before expiration date") 81 | fileCmd.Flags().IntVarP(&critical, "critical", "c", 14, "critical threshold in `days` before expiration date") 82 | fileCmd.Flags().SortFlags = false 83 | 84 | rootCmd.AddCommand(fileCmd) 85 | } 86 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cmd 6 | 7 | import ( 8 | "errors" 9 | "os" 10 | "strings" 11 | "time" 12 | 13 | "github.com/heartbeatsjp/check-tls-cert/checker" 14 | "github.com/heartbeatsjp/check-tls-cert/version" 15 | "github.com/heartbeatsjp/check-tls-cert/x509util" 16 | "github.com/mitchellh/go-homedir" 17 | "github.com/spf13/cobra" 18 | ) 19 | 20 | var ( 21 | hostname string 22 | warning int 23 | critical int 24 | rootFile string 25 | enableSSLCertDir bool 26 | dnTypeStr string 27 | dnType x509util.DNType 28 | verbose int 29 | outputFormatStr string 30 | outputFormat checker.OutputFormat 31 | timestamp string 32 | currentTime time.Time 33 | 34 | rootCmd = &cobra.Command{ 35 | Use: "check-tls-cert", 36 | Short: "check-tls-cert is a TLS certificate checker", 37 | Version: version.Version, 38 | PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 39 | var err error 40 | 41 | rootFile, _ = homedir.Expand(rootFile) 42 | 43 | checker.SetVerbose(verbose) 44 | 45 | if dnType, err = parseDNType(dnTypeStr); err != nil { 46 | return err 47 | } 48 | checker.SetDNType(dnType) 49 | 50 | if outputFormat, err = parseOutputFormat(outputFormatStr); err != nil { 51 | return err 52 | } 53 | 54 | if currentTime, err = parseTimestamp(timestamp); err != nil { 55 | return err 56 | } 57 | checker.SetCurrentTime(currentTime) 58 | 59 | return nil 60 | }, 61 | RunE: func(cmd *cobra.Command, args []string) error { 62 | cmd.Help() 63 | return nil 64 | }, 65 | } 66 | ) 67 | 68 | // Execute the `check-tls-cert` command. 69 | func Execute() { 70 | if err := rootCmd.Execute(); err != nil { 71 | os.Exit(checker.UNKNOWN.Code()) 72 | } 73 | } 74 | 75 | func init() { 76 | cobra.EnableCommandSorting = false 77 | rootCmd.PersistentFlags().StringVar(&rootFile, "root-file", "", "root certificate `file` (default system root certificate file)") 78 | rootCmd.PersistentFlags().BoolVar(&enableSSLCertDir, "enable-ssl-cert-dir", false, "enable system default certificate directories or environment variable SSL_CERT_DIR") 79 | rootCmd.PersistentFlags().StringVar(&dnTypeStr, "dn-type", "loose", "Distinguished Name type. 'strict' (RFC 4514), 'loose' (with space), or 'openssl'") 80 | rootCmd.PersistentFlags().CountVarP(&verbose, "verbose", "v", "verbose mode. Multiple -v options increase the verbosity. The maximum is 3.") 81 | rootCmd.PersistentFlags().StringVarP(&outputFormatStr, "output-format", "O", "default", "output format. 'default' or 'json'") 82 | 83 | // The option `--timestamp`` is used for debugging. 84 | rootCmd.PersistentFlags().StringVar(×tamp, "timestamp", "", "timestamp. This format is '2006-01-02T15:04:05+07:00'. (default a current time)") 85 | rootCmd.PersistentFlags().MarkHidden("timestamp") 86 | 87 | rootCmd.Flags().SortFlags = false 88 | rootCmd.PersistentFlags().SortFlags = false 89 | } 90 | 91 | func parseDNType(dnType string) (x509util.DNType, error) { 92 | var t x509util.DNType 93 | switch strings.ToLower(dnType) { 94 | case "strict": 95 | t = x509util.StrictDN 96 | case "loose": 97 | t = x509util.LooseDN 98 | case "openssl": 99 | t = x509util.OpenSSLDN 100 | default: 101 | return 0, errors.New("unknown Distinguished Name Type in '--dn-type' option") 102 | } 103 | return t, nil 104 | } 105 | 106 | func parseOutputFormat(outputFormatStr string) (f checker.OutputFormat, err error) { 107 | switch strings.ToLower(outputFormatStr) { 108 | case "default": 109 | f = checker.DefaultFormat 110 | case "json": 111 | f = checker.JSONFormat 112 | default: 113 | return checker.DefaultFormat, errors.New("unknown Output Format in '--output-format' option") 114 | } 115 | return f, nil 116 | } 117 | 118 | func parseTimestamp(timestampStr string) (time.Time, error) { 119 | if timestampStr == "" { 120 | return time.Now(), nil 121 | } 122 | timestamp, err := time.Parse(time.RFC3339, timestampStr) 123 | if err != nil { 124 | return time.Now(), errors.New("invalid format in '--timestamp' option") 125 | } 126 | return timestamp, nil 127 | } 128 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/heartbeatsjp/check-tls-cert 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/mattn/go-colorable v0.1.12 7 | github.com/mitchellh/go-homedir v1.1.0 8 | github.com/spf13/cobra v1.4.0 9 | github.com/stretchr/testify v1.7.1 10 | github.com/ttkzw/go-color v0.1.3 11 | github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a 12 | golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 13 | golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect 14 | golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 15 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 16 | ) 17 | 18 | require ( 19 | github.com/davecgh/go-spew v1.1.1 // indirect 20 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 21 | github.com/mattn/go-isatty v0.0.14 // indirect 22 | github.com/pmezard/go-difflib v1.0.0 // indirect 23 | github.com/spf13/pflag v1.0.5 // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 2 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 6 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 7 | github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= 8 | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 9 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 10 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 11 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 12 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 13 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 15 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 16 | github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= 17 | github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= 18 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 19 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 20 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 21 | github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= 22 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 23 | github.com/ttkzw/go-color v0.1.3 h1:+Yo/AEPpM6dVMowieDfYeAd/OOlBGNeMV6nUYcBp7zA= 24 | github.com/ttkzw/go-color v0.1.3/go.mod h1:B7bKeU+T3xeJIVrVdiq37kRNLdrzIpDwOABGU9q1tmg= 25 | github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= 26 | github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= 27 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 28 | golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 29 | golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= 30 | golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 31 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 32 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 33 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 34 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 35 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 36 | golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= 37 | golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8= 39 | golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 40 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 41 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 42 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 43 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 44 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 45 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 46 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 47 | -------------------------------------------------------------------------------- /internal/file/file.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package file 6 | 7 | import ( 8 | "crypto/x509" 9 | "errors" 10 | 11 | "github.com/heartbeatsjp/check-tls-cert/checker" 12 | "github.com/heartbeatsjp/check-tls-cert/x509util" 13 | "github.com/mattn/go-colorable" 14 | ) 15 | 16 | type FileCommandOptions struct { 17 | Hostname string 18 | KeyFile string 19 | CertFile string 20 | ChainFile string 21 | CAFile string 22 | PasswordFile string 23 | Warning int 24 | Critical int 25 | RootFile string 26 | EnableSSLCertDir bool 27 | OutputFormat checker.OutputFormat 28 | } 29 | 30 | // Run checks certificates. 31 | func Run(opts FileCommandOptions) (int, error) { 32 | var ( 33 | rootCerts []*x509.Certificate 34 | rootCertPool *x509.CertPool 35 | password []byte 36 | err error 37 | ) 38 | 39 | checker.SetOutput(colorable.NewColorableStdout()) 40 | 41 | if opts.RootFile != "" { 42 | rootCerts, err = x509util.ParseCertificateFiles(opts.RootFile) 43 | if err != nil { 44 | return checker.UNKNOWN.Code(), err 45 | } 46 | } 47 | 48 | rootCertPool, err = x509util.GetRootCertPool(rootCerts, opts.EnableSSLCertDir) 49 | if err != nil { 50 | return checker.UNKNOWN.Code(), err 51 | } 52 | 53 | certs, err := x509util.ParseCertificateFiles(opts.CertFile, opts.ChainFile) 54 | if err != nil { 55 | return checker.UNKNOWN.Code(), err 56 | } 57 | 58 | if len(certs) == 0 { 59 | return checker.UNKNOWN.Code(), errors.New("no valid certificates") 60 | } 61 | serverCert := certs[0] 62 | 63 | if len(opts.PasswordFile) > 0 { 64 | password, err = x509util.ReadPasswordFile(opts.PasswordFile) 65 | if err != nil { 66 | return checker.UNKNOWN.Code(), err 67 | } 68 | } 69 | 70 | privKeyInfo, err := x509util.ParsePrivateKeyFile(opts.KeyFile, password) 71 | if err != nil { 72 | return checker.UNKNOWN.Code(), err 73 | } 74 | 75 | pubKeyInfoInPrivKey, err := x509util.ExtractPublicKeyFromPrivateKey(privKeyInfo) 76 | if err != nil { 77 | return checker.UNKNOWN.Code(), err 78 | } 79 | 80 | pubKeyInfo, err := x509util.ExtractPublicKeyFromCertificate(serverCert) 81 | if err != nil { 82 | return checker.UNKNOWN.Code(), err 83 | } 84 | 85 | if opts.CAFile != "" { 86 | _, err = x509util.ParseCertificateFiles(opts.CAFile) 87 | if err != nil { 88 | return checker.UNKNOWN.Code(), err 89 | } 90 | } 91 | 92 | var checkerList []checker.Checker 93 | checkerList = append(checkerList, checker.NewCertificateChecker(serverCert)) 94 | checkerList = append(checkerList, checker.NewCertificateFilesChecker(opts.CertFile, opts.ChainFile, opts.CAFile, opts.RootFile)) 95 | checkerList = append(checkerList, checker.NewKeyPairChecker(pubKeyInfoInPrivKey, pubKeyInfo)) 96 | checkerList = append(checkerList, checker.NewHostnameChecker(opts.Hostname, serverCert)) 97 | checkerList = append(checkerList, checker.NewValidityChecker(serverCert, opts.Warning, opts.Critical)) 98 | checkerList = append(checkerList, checker.NewCertificateChainChecker(certs, rootCertPool)) 99 | 100 | summary := checker.NewSummary(checkerList) 101 | result := checker.NewResult(summary, checkerList) 102 | switch opts.OutputFormat { 103 | case checker.JSONFormat: 104 | result.PrintJSON() 105 | default: 106 | result.Print() 107 | } 108 | return summary.Status().Code(), nil 109 | } 110 | -------------------------------------------------------------------------------- /net/pop3util/pop3.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010, 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This package is a modification of the net.smtp package. 6 | // See also: 7 | // https://golang.org/src/net/smtp/smtp.go 8 | 9 | package pop3util 10 | 11 | import ( 12 | "crypto/tls" 13 | "errors" 14 | "fmt" 15 | "net" 16 | "net/textproto" 17 | "strings" 18 | "time" 19 | ) 20 | 21 | // A Client represents a client connection to a POP3 server. 22 | type Client struct { 23 | // Text is the textproto.Conn used by the Client. It is exported to allow for 24 | // clients to add extensions. 25 | Text *textproto.Conn 26 | // keep a reference to the connection so it can be used to create a TLS 27 | // connection later 28 | conn net.Conn 29 | // whether the Client is using TLS 30 | tls bool 31 | // map of supported capabilities 32 | capability map[string]string 33 | } 34 | 35 | // Dial returns a new Client connected to a POP3 server at addr. 36 | // The addr must include a port, as in "mail.example.com:110". 37 | func Dial(network string, addr string, timeout time.Duration) (*Client, error) { 38 | dialer := net.Dialer{ 39 | Timeout: timeout, 40 | } 41 | conn, err := dialer.Dial(network, addr) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return NewClient(conn) 46 | } 47 | 48 | // NewClient returns a new Client using an existing connection. 49 | func NewClient(conn net.Conn) (*Client, error) { 50 | text := textproto.NewConn(conn) 51 | _, err := text.ReadLine() 52 | if err != nil { 53 | text.Close() 54 | return nil, err 55 | } 56 | c := &Client{Text: text, conn: conn} 57 | _, c.tls = conn.(*tls.Conn) 58 | return c, nil 59 | } 60 | 61 | // Close closes the connection. 62 | func (c *Client) Close() error { 63 | return c.Text.Close() 64 | } 65 | 66 | // cmd is a convenience function that sends a command and returns the response 67 | func (c *Client) cmd(wantResponse bool, format string, args ...interface{}) (string, error) { 68 | id, err := c.Text.Cmd(format, args...) 69 | if err != nil { 70 | return "", err 71 | } 72 | c.Text.StartResponse(id) 73 | defer c.Text.EndResponse(id) 74 | msg, err := c.readResponse(wantResponse) 75 | return msg, err 76 | } 77 | 78 | func (c *Client) readResponse(wantResponse bool) (message string, err error) { 79 | line, err := c.Text.ReadLine() 80 | if err != nil { 81 | return "", err 82 | } 83 | resp := strings.SplitN(line, " ", 2) 84 | if resp[0] != "+OK" { 85 | message = "command error" 86 | if len(resp) == 2 { 87 | message = resp[1] 88 | } 89 | return "", fmt.Errorf("pop3: %s", message) 90 | } 91 | 92 | if !wantResponse { 93 | return message, nil 94 | } 95 | 96 | for { 97 | moreMessage, err := c.Text.ReadLine() 98 | if err != nil { 99 | return "", err 100 | } 101 | if moreMessage == "." { 102 | break 103 | } 104 | message += "\n" + moreMessage 105 | } 106 | 107 | return 108 | } 109 | 110 | // Capa sends the CAPA command to the server. 111 | func (c *Client) Capa() error { 112 | msg, err := c.cmd(true, "CAPA") 113 | if err != nil { 114 | return err 115 | } 116 | ext := make(map[string]string) 117 | extList := strings.Split(msg, "\n") 118 | if len(extList) > 1 { 119 | extList = extList[1:] 120 | for _, line := range extList { 121 | if line == "." { 122 | break 123 | } 124 | args := strings.SplitN(line, " ", 2) 125 | if len(args) > 1 { 126 | ext[args[0]] = args[1] 127 | } else { 128 | ext[args[0]] = "" 129 | } 130 | } 131 | } 132 | c.capability = ext 133 | return err 134 | } 135 | 136 | // StartTLS sends the STARTTLS command and encrypts all further communication. 137 | // Only servers that advertise the STARTTLS extension support this function. 138 | func (c *Client) StartTLS(config *tls.Config) error { 139 | if err := c.Capa(); err != nil { 140 | return err 141 | } 142 | _, ok := c.capability["STLS"] 143 | if !ok { 144 | return errors.New("pop3: STLS command not supported") 145 | } 146 | _, err := c.cmd(false, "STLS") 147 | if err != nil { 148 | return err 149 | } 150 | c.conn = tls.Client(c.conn, config) 151 | c.Text = textproto.NewConn(c.conn) 152 | c.tls = true 153 | return c.Capa() 154 | } 155 | 156 | // TLSConnectionState returns the client's TLS connection state. 157 | // The return values are their zero values if StartTLS did 158 | // not succeed. 159 | func (c *Client) TLSConnectionState() (state tls.ConnectionState, ok bool) { 160 | tc, ok := c.conn.(*tls.Conn) 161 | if !ok { 162 | return 163 | } 164 | return tc.ConnectionState(), true 165 | } 166 | 167 | // Quit sends the QUIT command and closes the connection to the server. 168 | func (c *Client) Quit() error { 169 | _, err := c.cmd(false, "QUIT") 170 | if err != nil { 171 | return err 172 | } 173 | return c.Text.Close() 174 | } 175 | -------------------------------------------------------------------------------- /scripts/PKI.md: -------------------------------------------------------------------------------- 1 | # PKI Diagram 2 | 3 | - Root CA G1 RSA (an old-generation root CA) 4 | - Root CA G2 RSA (cross-signing) 5 | - Root CA G2 ECDSA (cross-signing) 6 | - Root CA G2 RSA 7 | - Intermediate CA A RSA 8 | - server-a.test (RSA) 9 | - server-a.test (ECDSA) 10 | - server-a.test (Ed25519) 11 | - server-a.test (Ed448) (Not supported by check-tls-cert) 12 | - Intermediate CA B RSA 13 | - server-b.test (RSA) 14 | - server-b.test (ECDSA) 15 | - server-b.test (Ed25519) 16 | - server-b.test (Ed448) (Not supported by check-tls-cert) 17 | - Root CA G2 ECDSA 18 | - Intermediate CA ECDSA 19 | - server-c.test (RSA) 20 | - server-c.test (ECDSA) 21 | - server-c.test (Ed25519) 22 | - server-c.test (Ed448) (Not supported by check-tls-cert) 23 | 24 | -------------------------------------------------------------------------------- /scripts/bumpup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | gobump up -w version/ 4 | if [[ $? -ne 0 ]]; then 5 | echo "Aborted" 6 | exit 7 | fi 8 | 9 | git add version/version.go 10 | version=v$(gobump show -r version) 11 | git commit -m "Release ${version}" 12 | git tag -a ${version} -m "Release ${version}" 13 | git push origin ${version} 14 | git push 15 | exit 16 | -------------------------------------------------------------------------------- /scripts/gen-chain-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | VALID_CERT_DIR=test/testdata/pki/cert/valid 9 | CHAIN_CERT_DIR=test/testdata/pki/chain 10 | 11 | 12 | # Certificate Chain 13 | cat ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 14 | > ${CHAIN_CERT_DIR}/chain-a-rsa.pem 15 | 16 | cat ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 17 | ${CA_CERT_DIR}/ca-root-g2-rsa-cross.pem \ 18 | > ${CHAIN_CERT_DIR}/chain-a-rsa-cross.pem 19 | 20 | cat ${CA_CERT_DIR}/ca-root-g2-rsa-cross.pem \ 21 | ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 22 | > ${CHAIN_CERT_DIR}/invalid-chain-a-rsa-cross.pem 23 | 24 | # Full chain 25 | cat ${VALID_CERT_DIR}/server-a-rsa.pem \ 26 | ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 27 | > ${CHAIN_CERT_DIR}/fullchain-a-rsa.pem 28 | 29 | cat ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 30 | ${VALID_CERT_DIR}/server-a-rsa.pem \ 31 | > ${CHAIN_CERT_DIR}/invalid-fullchain-a-rsa.pem 32 | 33 | cat ${VALID_CERT_DIR}/server-a-rsa.pem \ 34 | ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 35 | ${CA_CERT_DIR}/ca-root-g2-rsa-cross.pem \ 36 | > ${CHAIN_CERT_DIR}/fullchain-a-rsa-cross.pem 37 | 38 | cat ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 39 | ${CA_CERT_DIR}/ca-root-g2-rsa-cross.pem \ 40 | ${VALID_CERT_DIR}/server-a-rsa.pem \ 41 | > ${CHAIN_CERT_DIR}/fullchain-a-rsa-cross.pem 42 | 43 | # Trusted Certificates 44 | cat ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 45 | ${CA_CERT_DIR}/ca-root-g2-rsa.pem \ 46 | > ${CHAIN_CERT_DIR}/ca.pem 47 | 48 | cat ${CA_CERT_DIR}/ca-root-g2-rsa.pem \ 49 | ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 50 | > ${CHAIN_CERT_DIR}/invalid-ca.pem 51 | 52 | # Mixed file 53 | cat ${VALID_CERT_DIR}/server-a-rsa.pem \ 54 | ${VALID_CERT_DIR}/ca-intermediate-a-rsa.pem \ 55 | ${PRIVATE_KEY_DIR}/server-a-rsa.pem \ 56 | > ${CHAIN_CERT_DIR}/fullchain-a-rsa-private-key.pem 57 | -------------------------------------------------------------------------------- /scripts/gen-expired-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | CERT_DIR=test/testdata/pki/cert/expired 9 | 10 | source scripts/pkilib.sh 11 | 12 | gen_intermediate_ca_cert() { 13 | local issuer_name=$1 14 | local name=$2 15 | local subject=$3 16 | local days=$4 17 | local startdate=$5 18 | 19 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 20 | ca_cert_file=$(_lookup_file ${CA_CERT_DIR} ${CERT_DIR} ${issuer_name}.pem) 21 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 22 | csr_file=${CERT_DIR}/${name}.csr 23 | cert_file=${CERT_DIR}/${name}.pem 24 | 25 | _gen_intermediate_ca_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} "${subject}" ${days} ${startdate} 26 | } 27 | 28 | gen_server_cert() { 29 | local issuer_name=$1 30 | local name=$2 31 | local domainname=$3 32 | local days=$4 33 | local startdate=$5 34 | 35 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 36 | ca_cert_file=${CERT_DIR}/${issuer_name}.pem 37 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 38 | csr_file=${CERT_DIR}/${name}.csr 39 | cert_file=${CERT_DIR}/${name}.pem 40 | 41 | _gen_server_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} ${domainname} ${days} ${startdate} 42 | } 43 | 44 | 45 | # Intermediate CA A RSA Certificate 46 | gen_intermediate_ca_cert ca-root-g2-rsa ca-intermediate-a-rsa "/CN=Intermediate CA A RSA" 1826 '2015-01-01' 47 | 48 | # server-a.test (RSA) 49 | gen_server_cert ca-intermediate-a-rsa server-a-rsa "server-a.test" 365 '2019-01-01' 50 | 51 | # server-a.test (ECDSA) 52 | gen_server_cert ca-intermediate-a-rsa server-a-ecdsa "server-a.test" 365 '2019-01-01' 53 | 54 | # server-a.test (Ed25519) 55 | gen_server_cert ca-intermediate-a-rsa server-a-ed25519 "server-a.test" 365 '2019-01-01' 56 | 57 | # server-a.test (Ed488) 58 | gen_server_cert ca-intermediate-a-rsa server-a-ed488 "server-a.test" 365 '2019-01-01' 59 | 60 | 61 | # Intermediate CA B RSA Certificate 62 | gen_intermediate_ca_cert ca-root-g2-rsa ca-intermediate-b-rsa "/CN=Intermediate CA B RSA" 1826 '2015-01-01' 63 | 64 | # server-b.test (RSA) 65 | gen_server_cert ca-intermediate-b-rsa server-b-rsa "server-b.test" 365 '2019-01-01' 66 | 67 | # server-b.test (ECDSA) 68 | gen_server_cert ca-intermediate-b-rsa server-b-ecdsa "server-b.test" 365 '2019-01-01' 69 | 70 | # server-b.test (Ed25519) 71 | gen_server_cert ca-intermediate-b-rsa server-b-ed25519 "server-b.test" 365 '2019-01-01' 72 | 73 | # server-b.test (Ed488) 74 | gen_server_cert ca-intermediate-b-rsa server-b-ed488 "server-b.test" 365 '2019-01-01' 75 | 76 | 77 | # Intermediate CA ECDSA Certificate 78 | gen_intermediate_ca_cert ca-root-g2-ecdsa ca-intermediate-ecdsa "/CN=Intermediate CA ECDSA" 1826 '2015-01-01' 79 | 80 | # server-c.test (RSA) 81 | gen_server_cert ca-intermediate-ecdsa server-c-rsa "server-c.test" 365 '2019-01-01' 82 | 83 | # server-c.test (ECDSA) 84 | gen_server_cert ca-intermediate-ecdsa server-c-ecdsa "server-c.test" 365 '2019-01-01' 85 | 86 | # server-c.test (Ed25519) 87 | gen_server_cert ca-intermediate-ecdsa server-c-ed25519 "server-c.test" 365 '2019-01-01' 88 | 89 | # server-c.test (Ed488) 90 | gen_server_cert ca-intermediate-ecdsa server-c-ed488 "server-c.test" 365 '2019-01-01' 91 | 92 | -------------------------------------------------------------------------------- /scripts/gen-expired-ocsp-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | CERT_DIR=test/testdata/pki/cert/expired 9 | 10 | source scripts/pkilib.sh 11 | 12 | gen_ocsp_responder_cert() { 13 | local issuer_name=$1 14 | local name=$2 15 | local subject=$3 16 | local days=$4 17 | local startdate=$5 18 | 19 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 20 | ca_cert_file=$(_lookup_file ${CA_CERT_DIR} ${CERT_DIR} ${issuer_name}.pem) 21 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 22 | csr_file=${CERT_DIR}/${name}.csr 23 | cert_file=${CERT_DIR}/${name}.pem 24 | 25 | _gen_ocsp_responder_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} "${subject}" ${days} ${startdate} 26 | } 27 | 28 | # Intermediate CA A RSA OCSP Responder Certificate 29 | gen_ocsp_responder_cert ca-intermediate-a-rsa ca-intermediate-a-rsa-ocsp-responder "/CN=Intermediate CA A RSA OCSP Responder" 365 '2019-01-01' 30 | -------------------------------------------------------------------------------- /scripts/gen-not-yet-valid-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | CERT_DIR=test/testdata/pki/cert/notyetvalid 9 | 10 | source scripts/pkilib.sh 11 | 12 | gen_intermediate_ca_cert() { 13 | local issuer_name=$1 14 | local name=$2 15 | local subject=$3 16 | local days=$4 17 | local startdate=$5 18 | 19 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 20 | ca_cert_file=$(_lookup_file ${CA_CERT_DIR} ${CERT_DIR} ${issuer_name}.pem) 21 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 22 | csr_file=${CERT_DIR}/${name}.csr 23 | cert_file=${CERT_DIR}/${name}.pem 24 | 25 | _gen_intermediate_ca_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} "${subject}" ${days} ${startdate} 26 | } 27 | 28 | gen_server_cert() { 29 | local issuer_name=$1 30 | local name=$2 31 | local domainname=$3 32 | local days=$4 33 | local startdate=$5 34 | 35 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 36 | ca_cert_file=${CERT_DIR}/${issuer_name}.pem 37 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 38 | csr_file=${CERT_DIR}/${name}.csr 39 | cert_file=${CERT_DIR}/${name}.pem 40 | 41 | _gen_server_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} ${domainname} ${days} ${startdate} 42 | } 43 | 44 | 45 | # Intermediate CA A RSA Certificate 46 | gen_intermediate_ca_cert ca-root-g2-rsa ca-intermediate-a-rsa "/CN=Intermediate CA A RSA" 1826 '2035-01-01' 47 | 48 | # server-a.test (RSA) 49 | gen_server_cert ca-intermediate-a-rsa server-a-rsa "server-a.test" 365 '2035-01-01' 50 | 51 | # server-a.test (ECDSA) 52 | gen_server_cert ca-intermediate-a-rsa server-a-ecdsa "server-a.test" 365 '2035-01-01' 53 | 54 | # server-a.test (Ed25519) 55 | gen_server_cert ca-intermediate-a-rsa server-a-ed25519 "server-a.test" 365 '2035-01-01' 56 | 57 | # server-a.test (Ed488) 58 | gen_server_cert ca-intermediate-a-rsa server-a-ed488 "server-a.test" 365 '2035-01-01' 59 | 60 | 61 | # Intermediate CA B RSA Certificate 62 | gen_intermediate_ca_cert ca-root-g2-rsa ca-intermediate-b-rsa "/CN=Intermediate CA B RSA" 1826 '2035-01-01' 63 | 64 | # server-b.test (RSA) 65 | gen_server_cert ca-intermediate-b-rsa server-b-rsa "server-b.test" 365 '2035-01-01' 66 | 67 | # server-b.test (ECDSA) 68 | gen_server_cert ca-intermediate-b-rsa server-b-ecdsa "server-b.test" 365 '2035-01-01' 69 | 70 | # server-b.test (Ed25519) 71 | gen_server_cert ca-intermediate-b-rsa server-b-ed25519 "server-b.test" 365 '2035-01-01' 72 | 73 | # server-b.test (Ed488) 74 | gen_server_cert ca-intermediate-b-rsa server-b-ed488 "server-b.test" 365 '2035-01-01' 75 | 76 | 77 | # Intermediate CA ECDSA Certificate 78 | gen_intermediate_ca_cert ca-root-g2-ecdsa ca-intermediate-ecdsa "/CN=Intermediate CA ECDSA" 1826 '2035-01-01' 79 | 80 | # server-c.test (RSA) 81 | gen_server_cert ca-intermediate-ecdsa server-c-rsa "server-c.test" 365 '2035-01-01' 82 | 83 | # server-c.test (ECDSA) 84 | gen_server_cert ca-intermediate-ecdsa server-c-ecdsa "server-c.test" 365 '2035-01-01' 85 | 86 | # server-c.test (Ed25519) 87 | gen_server_cert ca-intermediate-ecdsa server-c-ed25519 "server-c.test" 365 '2035-01-01' 88 | 89 | # server-c.test (Ed488) 90 | gen_server_cert ca-intermediate-ecdsa server-c-ed488 "server-c.test" 365 '2035-01-01' 91 | 92 | -------------------------------------------------------------------------------- /scripts/gen-ocsp-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | CERT_DIR=test/testdata/pki/cert/valid 9 | 10 | source scripts/pkilib.sh 11 | 12 | gen_ocsp_responder_cert() { 13 | local issuer_name=$1 14 | local name=$2 15 | local subject=$3 16 | local days=$4 17 | 18 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 19 | ca_cert_file=$(_lookup_file ${CA_CERT_DIR} ${CERT_DIR} ${issuer_name}.pem) 20 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 21 | csr_file=${CERT_DIR}/${name}.csr 22 | cert_file=${CERT_DIR}/${name}.pem 23 | 24 | _gen_ocsp_responder_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} "${subject}" ${days} 25 | } 26 | 27 | # Intermediate CA A RSA OCSP Responder Certificate 28 | gen_ocsp_responder_cert ca-intermediate-a-rsa ca-intermediate-a-rsa-ocsp-responder "/CN=Intermediate CA A RSA OCSP Responder" 365 29 | -------------------------------------------------------------------------------- /scripts/gen-private-key.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | 8 | source scripts/pkilib.sh 9 | 10 | gen_ca_private_key() { 11 | local name=$1 12 | local algo=$2 13 | 14 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 15 | 16 | _gen_ca_private_key ${key_file} ${algo} 17 | } 18 | 19 | gen_server_private_key() { 20 | local name=$1 21 | local algo=$2 22 | local cipher=$3 23 | local pass_file=$4 24 | 25 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 26 | if [[ -n ${pass_file} ]]; then 27 | pass_file=${PRIVATE_KEY_DIR}/${pass_file} 28 | fi 29 | 30 | _gen_server_private_key ${key_file} ${algo} ${cipher} ${pass_file} 31 | } 32 | 33 | 34 | # Root CA G1 RSA Private Key 35 | gen_ca_private_key ca-root-g1-rsa rsa 36 | 37 | # Root CA G2 RSA Private Key 38 | gen_ca_private_key ca-root-g2-rsa rsa 39 | 40 | # Root CA G2 ECDSA Private Key 41 | gen_ca_private_key ca-root-g2-ecdsa ecdsa 42 | 43 | 44 | # Intermediate CA A RSA Private Key 45 | gen_ca_private_key ca-intermediate-a-rsa rsa 46 | 47 | # Intermediate CA B RSA Private Key 48 | gen_ca_private_key ca-intermediate-b-rsa rsa 49 | 50 | # Intermediate CA ECDSA Private Key 51 | gen_ca_private_key ca-intermediate-ecdsa ecdsa 52 | 53 | 54 | # server-a.test RSA Private Key and Encrypted Key 55 | gen_server_private_key server-a-rsa rsa aes-128-cbc password.txt 56 | 57 | # server-a.test ECDSA Private Key and Encrypted Key 58 | gen_server_private_key server-a-ecdsa ecdsa aes-128-cbc password.txt 59 | 60 | # server-a.test Ed25519 Private Key and Encrypted Key 61 | gen_server_private_key server-a-ed25519 ed25519 aes-128-cbc password.txt 62 | 63 | # server-a.test Ed488 Private Key and Encrypted Key 64 | gen_server_private_key server-a-ed488 ed488 aes-128-cbc password.txt 65 | 66 | 67 | # server-b.test RSA Private Key 68 | gen_server_private_key server-b-rsa rsa 69 | 70 | # server-b.test ECDSA Private Key 71 | gen_server_private_key server-b-ecdsa ecdsa 72 | 73 | # server-b.test Ed25519 Private Key 74 | gen_server_private_key server-b-ed25519 ed25519 75 | 76 | # server-b.test Ed488 Private Key 77 | gen_server_private_key server-b-ed488 ed488 78 | 79 | 80 | # server-c.test RSA Private Key 81 | gen_server_private_key server-c-rsa rsa 82 | 83 | # server-c.test ECDSA Private Key 84 | gen_server_private_key server-c-ecdsa ecdsa 85 | 86 | # server-c.test Ed25519 Private Key 87 | gen_server_private_key server-c-ed25519 ed25519 88 | 89 | # server-c.test Ed488 Private Key 90 | gen_server_private_key server-c-ed488 ed488 91 | 92 | 93 | # Intermediate CA A RSA OCSP Responder Private Key 94 | gen_server_private_key ca-intermediate-a-rsa-ocsp-responder rsa 95 | 96 | 97 | # variables PEM format 98 | # No EOL 99 | cat ${PRIVATE_KEY_DIR}/server-a-rsa.pem | awk '!/-----END/ {print} /-----END/ {printf("%s", $0)}' > ${PRIVATE_KEY_DIR}/misc-no-eol.pem 100 | 101 | # Explanatory Text 102 | echo "Pre Explanatory Text" > ${PRIVATE_KEY_DIR}/misc-explanatory-text.pem 103 | cat ${PRIVATE_KEY_DIR}/server-a-rsa.pem >> ${PRIVATE_KEY_DIR}/misc-explanatory-text.pem 104 | echo "Post Explanatory Text" >> ${PRIVATE_KEY_DIR}/misc-explanatory-text.pem 105 | -------------------------------------------------------------------------------- /scripts/gen-root-ca-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | 9 | source scripts/pkilib.sh 10 | 11 | gen_root_ca_cert() { 12 | local name=$1 13 | local subject=$2 14 | local days=$3 15 | local startdate=$4 16 | 17 | ca_key_file=${PRIVATE_KEY_DIR}/${name}.pem 18 | cert_file=${CA_CERT_DIR}/${name}.pem 19 | 20 | _gen_root_ca_cert ${ca_key_file} ${cert_file} "${subject}" ${days} ${startdate} 21 | } 22 | 23 | gen_intermediate_ca_cert() { 24 | local issuer_name=$1 25 | local name=$2 26 | local subject=$3 27 | local days=$4 28 | local suffix=$5 29 | local startdate=$6 30 | 31 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 32 | ca_cert_file=${CA_CERT_DIR}/${issuer_name}.pem 33 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 34 | csr_file=${CA_CERT_DIR}/${name}.csr 35 | cert_file=${CA_CERT_DIR}/${name}.pem 36 | 37 | if [[ -n "${suffix}" ]]; then 38 | cert_file=${CA_CERT_DIR}/${name}-${suffix}.pem 39 | fi 40 | 41 | _gen_intermediate_ca_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} "${subject}" ${days} ${startdate} 42 | } 43 | 44 | 45 | # Root CA G1 Certificate 46 | gen_root_ca_cert ca-root-g1-rsa "/CN=ROOT CA G1 RSA" 10957 '2005-01-01' 47 | 48 | # Root CA G2 RSA Certificate 49 | gen_root_ca_cert ca-root-g2-rsa "/CN=ROOT CA G2 RSA" 7305 '2015-01-01' 50 | 51 | # Root CA G2 ECDSA Certificate 52 | gen_root_ca_cert ca-root-g2-ecdsa "/CN=ROOT CA G2 ECDSA" 7305 '2015-01-01' 53 | 54 | # Root CA G2 RSA Certificate (Cross-Signing) 55 | gen_intermediate_ca_cert ca-root-g1-rsa ca-root-g2-rsa "/CN=ROOT CA G2 RSA" 7305 cross '2015-01-01' 56 | 57 | # Root CA G2 ECDSA Certificate (Cross-Signing) 58 | gen_intermediate_ca_cert ca-root-g1-rsa ca-root-g2-ecdsa "/CN=ROOT CA G2 ECDSA" 7305 cross '2015-01-01' 59 | 60 | 61 | cat ${CA_CERT_DIR}/{ca-root-g1-rsa,ca-root-g2-rsa,ca-root-g2-ecdsa}.pem > ${CA_CERT_DIR}/ca-root.pem 62 | 63 | exit 64 | 65 | -------------------------------------------------------------------------------- /scripts/gen-valid-cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright 2021 HEARTBEATS Corporation. All rights reserved. 3 | # Use of this source code is governed by a BSD-style 4 | # license that can be found in the LICENSE file. 5 | 6 | PRIVATE_KEY_DIR=test/testdata/pki/private 7 | CA_CERT_DIR=test/testdata/pki/root-ca 8 | CERT_DIR=test/testdata/pki/cert/valid 9 | 10 | source scripts/pkilib.sh 11 | 12 | gen_intermediate_ca_cert() { 13 | local issuer_name=$1 14 | local name=$2 15 | local subject=$3 16 | local days=$4 17 | 18 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 19 | ca_cert_file=$(_lookup_file ${CA_CERT_DIR} ${CERT_DIR} ${issuer_name}.pem) 20 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 21 | csr_file=${CERT_DIR}/${name}.csr 22 | cert_file=${CERT_DIR}/${name}.pem 23 | 24 | _gen_intermediate_ca_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} "${subject}" ${days} 25 | } 26 | 27 | gen_server_cert() { 28 | local issuer_name=$1 29 | local name=$2 30 | local domainname=$3 31 | local days=$4 32 | 33 | ca_key_file=${PRIVATE_KEY_DIR}/${issuer_name}.pem 34 | ca_cert_file=${CERT_DIR}/${issuer_name}.pem 35 | key_file=${PRIVATE_KEY_DIR}/${name}.pem 36 | csr_file=${CERT_DIR}/${name}.csr 37 | cert_file=${CERT_DIR}/${name}.pem 38 | 39 | _gen_server_cert ${ca_key_file} ${ca_cert_file} ${key_file} ${csr_file} ${cert_file} ${domainname} ${days} 40 | } 41 | 42 | 43 | # Intermediate CA A RSA Certificate 44 | gen_intermediate_ca_cert ca-root-g2-rsa ca-intermediate-a-rsa "/CN=Intermediate CA A RSA" 3653 45 | 46 | # server-a.test (RSA) 47 | gen_server_cert ca-intermediate-a-rsa server-a-rsa "server-a.test" 365 48 | 49 | # server-a.test (ECDSA) 50 | gen_server_cert ca-intermediate-a-rsa server-a-ecdsa "server-a.test" 365 51 | 52 | # server-a.test (Ed25519) 53 | gen_server_cert ca-intermediate-a-rsa server-a-ed25519 "server-a.test" 365 54 | 55 | # server-a.test (Ed488) 56 | gen_server_cert ca-intermediate-a-rsa server-a-ed488 "server-a.test" 365 57 | 58 | 59 | # Intermediate CA B RSA Certificate 60 | gen_intermediate_ca_cert ca-root-g2-rsa ca-intermediate-b-rsa "/CN=Intermediate CA B RSA" 3653 61 | 62 | # server-b.test (RSA) 63 | gen_server_cert ca-intermediate-b-rsa server-b-rsa "server-b.test" 365 64 | 65 | # server-b.test (ECDSA) 66 | gen_server_cert ca-intermediate-b-rsa server-b-ecdsa "server-b.test" 365 67 | 68 | # server-b.test (Ed25519) 69 | gen_server_cert ca-intermediate-b-rsa server-b-ed25519 "server-b.test" 365 70 | 71 | # server-b.test (Ed488) 72 | gen_server_cert ca-intermediate-b-rsa server-b-ed488 "server-b.test" 365 73 | 74 | 75 | # Intermediate CA ECDSA Certificate 76 | gen_intermediate_ca_cert ca-root-g2-ecdsa ca-intermediate-ecdsa "/CN=Intermediate CA ECDSA" 3653 77 | 78 | # server-c.test (RSA) 79 | gen_server_cert ca-intermediate-ecdsa server-c-rsa "server-c.test" 365 80 | 81 | # server-c.test (ECDSA) 82 | gen_server_cert ca-intermediate-ecdsa server-c-ecdsa "server-c.test" 365 83 | 84 | # server-c.test (Ed25519) 85 | gen_server_cert ca-intermediate-ecdsa server-c-ed25519 "server-c.test" 365 86 | 87 | # server-c.test (Ed488) 88 | gen_server_cert ca-intermediate-ecdsa server-c-ed488 "server-c.test" 365 89 | 90 | 91 | # variables PEM format 92 | # No EOL 93 | cat ${CERT_DIR}/server-a-rsa.pem | awk '!/-----END/ {print} /-----END/ {printf("%s", $0)}' > ${CERT_DIR}/misc-no-eol.pem 94 | 95 | # Explanatory Text 96 | echo "Pre Explanatory Text" > ${CERT_DIR}/misc-explanatory-text.pem 97 | cat ${CERT_DIR}/server-a-rsa.pem >> ${CERT_DIR}/misc-explanatory-text.pem 98 | echo "Post Explanatory Text" >> ${CERT_DIR}/misc-explanatory-text.pem 99 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/cert/expired/.gitkeep -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/ca-intermediate-a-rsa-ocsp-responder.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEVTCCAj2gAwIBAgIUIc5hRfl225Mip1eQFDVg41+eiBAwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowLzEtMCsGA1UEAwwkSW50ZXJtZWRpYXRlIENB 5 | IEEgUlNBIE9DU1AgUmVzcG9uZGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 6 | CgKCAQEA/mvm/Foh4zR0JMxz+9SjeOjQxdeLRebp7jZTwU1errDhk66IzzO8YYVc 7 | Ve3c9UoyzhBJC0xV5RNE5VkR4Az/0/ISYeo9v/YIeSFkxyc5TqX/VvrMM43r5F0m 8 | NGW1la2VgnWDTexEXzFcoKyd7igEbw8AMJX7lCbamQYCoyAXHWZMxKkBnEE3LgEH 9 | WO/7zy5kfki9jAhzI5X14ZdClL3/hz2e6iUj85VuAEeeHLVwSGPyH+ZKjLBhG/H+ 10 | 2b+hdBnwILeGs7z+P2e3lIaV/L4TjIRr+wB4CFFJmqne5L0XtQR5AoMYSNHf/P80 11 | fIuBtiYE3r1+JSvVM54oH/nux2WBTQIDAQABo3gwdjAfBgNVHSMEGDAWgBS9Pqzl 12 | i9PD3Mcbk/swIfR3IkXqKzAPBgkrBgEFBQcwAQUEAgUAMBMGA1UdJQQMMAoGCCsG 13 | AQUFBwMJMB0GA1UdDgQWBBS4yaBgsvHJPPMCENV5RvksKAuyNDAOBgNVHQ8BAf8E 14 | BAMCB4AwDQYJKoZIhvcNAQELBQADggIBAJ1TxWoK1L4Xk5+73OuW+HxKFUzhdHuP 15 | FlFHc01r0IXPS0HtWlDrwiAIt62+bXAkURFpwEbguvO2yOHvcVOuzJSgrEcbZVb9 16 | Ui6fOzGNG8hJ4sOzVKAbQy/iGyqJ1115VLdzOXS9rTqN/TGPEaGVWdkTpLPn5/O2 17 | opsJhxlI87d3xlnBVAC9Jx3id6TYoXMC/58VO7r5BfRZKhsOZwaYy0hePwLnXejS 18 | zvSfNjeGOpuQqH/0FPVrarBlavgLAh3yoZ9GYG4woGM/Rg9Xg5m7lzNaIR97Ui+/ 19 | QIqINlreXab4w0G43miKjnpRA4y39XdTTewlA9MkZDbwmjMdKT5ysHMDrdURR6wp 20 | la5DX19Tp4KpLlJNudfNrJeDe3pLrQZuRtFg6N0dmkUfaBbTCROH3tLb1gay48QD 21 | jHaNNoXt38/yzFWEyuenFfwxQZTQtm6JJB9U9EgYlRoroQvz1T9VL/wYeSSh0FGm 22 | jdwd8XpWryGlZAp8EGhQVef/xIX6efHyoGidKARjKV50GPAsKlW3QiRQ1SDKfH4k 23 | CrMH1FRbG9x5U/HhcnQrYmeHrJTfd6z3Ew7/tS2C5885fl6YatHw1ACbeJJcU9SR 24 | mqQMrJVVIm1FRRY/ZJZsIEz3FdWZXec/iKkpDbIv9mQjzv5cG+X9G78UWLfP2BVs 25 | ANlvFx1aHoSZ 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/ca-intermediate-a-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFSzCCAzOgAwIBAgIUWhdj+x4HiGeheWSb65x25yA8qCYwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMiBSU0EwHhcNMTUwMTAxMDAwMDAwWhcN 4 | MjAwMTAxMDAwMDAwWjAgMR4wHAYDVQQDDBVJbnRlcm1lZGlhdGUgQ0EgQSBSU0Ew 5 | ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDWmnFHwwL46rj3PP25nX/u 6 | v4Mk384WeL5S/uxeFWbf1v6EmyxRIL57L9EWehy7OE7NWQYhzcglLoTw+nmRcxvD 7 | UIGfQKsfEyn/LC6yw9r80aKyZrCrR4VjOnAm53nx3D6dNkHs/rndnI38Uycn9HRM 8 | O9mPkfeIOl7/pUoWDd/dXx33BLtH5Om4p3KhERAxzSFKIo/D3V+j2LZxzK4TB9Lm 9 | eoSyMxL/fzmaFkdIoM/I19KntphQ1BL7kC20N3/lbP8fIGtEQNDUUDXJTfzXnFgy 10 | wvfdBpdnsxePiLan4/nEFd0x0UzZbO39gQ87d7OjjZbjXLmXsUeh5+z/lnODsC1X 11 | G463IXVfQbSXgymliCvxkcDL0U1K9sTa0yakgQTG1blY94GVwy7YR68z32sEInZW 12 | JFMFqAW73KY995F/ZgwJlz5Ia5C1WagesCpK5KjNv86OE3M/zmQwp4s/2wCe7+NL 13 | R5znjNRC1NfsgRpGOvlO77gjhqrfVKYt4yqztQ6Hok071Q/3vHXFJvJxQjJ0m5Py 14 | n34ee0QUktMDNJfen7qA3LFGw2eP2HqfDAeFfPDjtk2mv16hWWrUhv9/pms44UnZ 15 | FZ+YuVKXmz4GJqPVN4tm1ElRz7oLjwH1HCCVdODR2s3QG4ogmFHf1S2afPRS0+gm 16 | ksBwytQgFXHwEJPLY9mifwIDAQABo4GDMIGAMB0GA1UdDgQWBBS9Pqzli9PD3Mcb 17 | k/swIfR3IkXqKzAfBgNVHSMEGDAWgBRXdlhuD4MxcTVJ+LS+YaZDgU9YbjAOBgNV 18 | HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1Ud 19 | EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAKeqBGko1f/QuakH4TbX2Scm 20 | ZcvBZybtQH7uqVQtebcGNRwU5C4D7DKNr00/ZOSfUYvnwW9eutpvNxbG1/D8JmHF 21 | GMyGG3KBE5vJJf8Z4BFlneitVoMAtT1ZdeHvMfNMl8aS9WMQUDh2oBEnTbSESuCG 22 | xWdF3v+LCGzDdu7kzaWs/9McEBYLpxK1xY+S9biYn3rQdN5hs5ePK2hRNOmZo4AU 23 | lCuILIptSyAzcse18HQzuXPb7jw1uuZlF45AtFLyqXLf1DRsN1d9en4n3Ke6WDbK 24 | KzEq/kI4NTcHZ5NNVJUEzy/jaVL4xYj+I4mMhMlLMCH3QWPNo0yC9W8EZpIn56LG 25 | oWjilx+LrIYZsk2ZyBv41lA5gv2/uRX7zb89wz6NxUkObVp/HHdGeLV++EQlZMvq 26 | PHaSPlwXMTnZ0e2RofH8ZEuHXQYYSeC5nt/PEm3xj4fi8In6aA07HYr8jZc7yyrv 27 | P12Wcvs65OWQQz3TRFXhU+hw+sBWcSBS+zN2yJ6yb0v2IfDGkhEwDesl29QwD575 28 | SiJvLj9qSKQr3x8z6XxhQVDx+wdsEeoN5ap/INZFkj4Xw93nAaqzlgX68dsA3M5o 29 | nF0sTzsGrCE4IkCQj6kL9s1uyKA2G3i0Cd4T1Sivmwzivepogs03paLUxlsfqfwx 30 | d9gr6cNHGyUWeTM1B33u 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/ca-intermediate-b-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFSzCCAzOgAwIBAgIUS/t+6/YvFuUg9bzwc2yK3m7psMowDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMiBSU0EwHhcNMTUwMTAxMDAwMDAwWhcN 4 | MjAwMTAxMDAwMDAwWjAgMR4wHAYDVQQDDBVJbnRlcm1lZGlhdGUgQ0EgQiBSU0Ew 5 | ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC4v/5iu81f+u8tQFnwF21a 6 | g0T6Ac1lUmzv4DAq1OTulPiFeUV+w9JXdou3+hXHKbpLoicT525rvGoHqLafiiV/ 7 | xG387bn3cGqvUncUq/cj+k8lEXclvXge5hdt6fPJE+tMTqOMtVw80YQniGbKyMLW 8 | o0zwNPTaI3LdLltRE3JQdM+uA7LYbU4BTTBNzZDRtYdSZNN2/N6W3kndOQEIzdgc 9 | xlpfhXyN0NnYWMw8RJhyvfMdtuRPmItAeoHZBQjStRGYpaHxzmSe5ov32smXgWcK 10 | LUGfKrW0RnTfQK9AEKTDy9LL12+fllUwSwqEXuoGOzsk6+lvTR+HFaPlvp8ydvJ8 11 | +F8GmuWvm/W6RBNSc992e/ZA+7AT8rLF5QUWVPgNwX6ErnMNNueJWl7lJNXdPbjN 12 | K9oi2WK4geMCUiRlbkeLoIY213UtsZgOnaBy2VgEV595Dq+OIhTrepZ/jlyPL4pr 13 | jBfYKAEyp0NOEjv5R8j0c1dQwQdldzZX2+KYqc9Qifhtu5Guq6acDbNTjuG22VUB 14 | ZaeqBJKfQYmMcEUvQMzlzCfbqvb+ApIDMgthiz7ZonkrtRqi0F77anWfyVY28ruN 15 | +1BCUqdSRb5c/ECUyEGDi0fTXYm4EAzRIqQ8jlt5UkLL4hrImQJquI9XOFn1SuOd 16 | 3+fakJMgqa6FbC+ZVOeZKwIDAQABo4GDMIGAMB0GA1UdDgQWBBSDlodB5/bcLsHZ 17 | z1hoyN07iDucJjAfBgNVHSMEGDAWgBRXdlhuD4MxcTVJ+LS+YaZDgU9YbjAOBgNV 18 | HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1Ud 19 | EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBALKnDe+r4Ns3hk4OupGZl+VX 20 | NsaqYxDHvsulZTsuqeCQ0I/l7+SenMOL/Vwuk2xC20+UcOOF0QbIB6Dr0Gna5NPw 21 | lMsBBPHOJvX7/ctr0+qmBwJne8XJB4bs1aXqj1c1ecDageCMYXMCs6LwxgaYV58/ 22 | cIETcydsjJtWKtM5eJP0e2+Bxqzmvv1YW0hEzPXAa6ra380B7nQbXx+nAKih5pX4 23 | rOHkMup6z6iV3efNdhCO5T9SkD/xN68CuN70tayV10hnqiXVZzIwqafFpn2q8w9X 24 | 1/NDyt5j6a1pi/icD/5+btZJXBIVJFCoOYOxKN51cLRpdqr06ODJ0ptA88ApfuQJ 25 | kADzYH6bh/7Dw3yiD5dMNcBBcASFeSCwgboTDm+8je4rK9aQ6t/3dYaf0in7RCP2 26 | ZpitiPUuJ5bGgqafFNrlw5FcyLt4FYfV+G0gEHwTaG/lAjH5VJHZXqrt1BcOPKEa 27 | 3klxgp4pwYhECeHSJtSo3kT7mLZOVJlwxYlLjK62h6VbLcI6tsRXYQmcQX495tak 28 | r4b+VOnqGCdrPMQMtPXzS2PoZuuRBb9z+kfCRcJY1fyjR8Tp0Z0cy9NkJlFNe5Gq 29 | KTEcoqHuzWVDNjbaaBHtdR5hCsmqbeWmJ1pGBJq2txlN75dK5Ss9jGJLudJ6g8m3 30 | oabP2OktL4VwVVHM/4cw 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/ca-intermediate-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB/TCCAYSgAwIBAgIUFIhBCwPkM4vb3s6rpZnW9guAxw0wCgYIKoZIzj0EAwMw 3 | GzEZMBcGA1UEAwwQUk9PVCBDQSBHMiBFQ0RTQTAeFw0xNTAxMDEwMDAwMDBaFw0y 4 | MDAxMDEwMDAwMDBaMCAxHjAcBgNVBAMMFUludGVybWVkaWF0ZSBDQSBFQ0RTQTB2 5 | MBAGByqGSM49AgEGBSuBBAAiA2IABDH68FN1KQhd8jhowTn5qGl077emm6tajcyj 6 | OHwYOUubEPHCW0APMhlw3Qf55+321Dr258N0nLItdG/1K87Xl9QZAlFQq4nKKmaP 7 | yJKxrc1o2WRq//0umdPR8KrHKB3REaOBgzCBgDAdBgNVHQ4EFgQUsfaVgjVOJm2z 8 | R6gbFYEc72nOpKcwHwYDVR0jBBgwFoAUJGmroiOJjCNbQHlDvGD2SmQT7i8wDgYD 9 | VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNV 10 | HRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2cAMGQCMCr/iQ0havl1OrCWUkoKInj8 11 | XTJlJYdVbUBx4FeMmSDuWLSrfJR1bXCSA47GX88sYAIwC9LS5tAVRQWrILJOxgrz 12 | /Blkj8GgflKPyy42c4LVo7qlWbSYVJkwZlNuPYs3e5Is 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-a-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDpjCCAY6gAwIBAgIUfzlw5mu35YG3K23epfaTrVtr07gwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDBZ 5 | MBMGByqGSM49AgEGCCqGSM49AwEHA0IABDbuI4eYuleNoNxyQBiuZy2SwyxDrP1Q 6 | MjS2JvQC+2yu//HnOr0wf6SyLSrHJadaYWU0+MySBHLUXyaHFOJIZNajgaowgacw 7 | HQYDVR0OBBYEFLZ+yiKISmB+adhsX31oXQMTYQo8MB8GA1UdIwQYMBaAFL0+rOWL 8 | 08PcxxuT+zAh9HciReorMCsGA1UdEQQkMCKCDXNlcnZlci1hLnRlc3SCEXd3dy5z 9 | ZXJ2ZXItYS50ZXN0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD 10 | AQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAV4xsOrzE 11 | jXfFAyXC2x5Ze3R1eJnQPwZAQVWcw2dtxfsGEcHovRL2Zq8ICnB5UMMJh9rgZzmt 12 | H+gSp641zimTRK8Wy/itYiaYKhbmiUGwEe7UDW12xcsOtm+BUFfnInwFfWbQFfSO 13 | +WBFEElroc2ASwFSbq/ViBfz4cqL7Ns5Zi2siM4EbgmGVAbuaibKpN3tnli7Tqq0 14 | 3IG3X4M1HcDuQC3hrOgPymQjjuF4lGdv/w/l4TJnb7QzV26DoTLKBqONejm5FPFe 15 | dC4pTCdcQ+nGugkL2k8g5a3YxLbjQ8CQuLgt5gW4so4B1Qw5v6QnZpP0ILMgsC0C 16 | 561KCPtT6OtiL/6Yky8KwyvyiO3UyxEX8jqco6TdtH01CXyJ7vkndpzxHpTsQ+G3 17 | uCqD40TXizNisIM9tI3DJvtLPZvoh3IrCHx0b1KZA79MyOEXyz2/DQVnzGg0w+ab 18 | Ue2X/fza3m9VxCR5SPFZQHjoSy0G20gRoXRflWe83gWnaAmjuKLF/1u4I+XzGJAj 19 | /3c7lWhJCfyGmPg7MPVX6vVw5mPyiw/mEoVB8AWAf2BpNJzEqEPWyAmiYs16OQWH 20 | xL5NR/xfJV4vNtJ9VSCjJ5rGh7NWNWc4Hp+XA/5OMflyYWqpueKpKINFNrQl0vl3 21 | UuB/h6DWA9Y6i+36y113T5NGcZuYy1Kaygk= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-a-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdzCCAV+gAwIBAgIUPN7SgQhkjIP5A3d3qmFMEMJyEHwwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDAq 5 | MAUGAytlcAMhAB2EhIA6Tw+a1sd3c4qNwl4dI6unqqFxwc/9JmrIumcWo4GqMIGn 6 | MB0GA1UdDgQWBBRcaa7pReT4icTK0QImXXHlUBEekDAfBgNVHSMEGDAWgBS9Pqzl 7 | i9PD3Mcbk/swIfR3IkXqKzArBgNVHREEJDAigg1zZXJ2ZXItYS50ZXN0ghF3d3cu 8 | c2VydmVyLWEudGVzdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH 9 | AwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAFVqeIMo 10 | DeTmdbXFHNG7ZIDV1kFRliZdajJZEb5tQW1df3DF40j+B+SAsx1GURxrW0sYlq9h 11 | NI8k6KD35XezJxYuPh2v//Cehp/fyBagVi1XPIAC5WWeB6jUb0pNySah2F+hqc0q 12 | BFt3EQyUgSjdLp/Xj6mucWr71U8ns+o0dNbDSJ0XmbcdQr9SQKjQAWFw2+OSAFc5 13 | +ETNJ7VjWePWWyHiJ9kMfDkZ/gLu5DuC6BmILOwEiBQkG0c84GR8NFSD3hU12LQR 14 | BKd/VIk9/Awr7/npvP0hIvJ85Q/ldNuR/2c//gICzLi9F9ZHtz6L+0SNLbCtc2HQ 15 | 5fpYTyjCmI02MOVth9eqL3J+8t6nC1U0j6Elv/Ugu7Q/y0ArFpqZtMfCzksHajw4 16 | jEr1Ubv7Pr/Nob2QKrEG01HBNXMqBsYCq7nTQ5+pcBszeusbJSQntdrrb5IW/wlE 17 | RgBejF2x2CoqxYA+Gzmc73fvnlsqJtmbOO6xv0D4HAZkYf9DZhxF4S2X5LrLqmtk 18 | MQDp77JCkuC6662BiI4yrQYuwJaMSQy3myT9S1ohOsyAqnupXXQ0sNw5KwtjMIXG 19 | Lgvi9ByWpvmMJAwowLqW0VxkYs/VxqM5u9ssSfRUS+kseLLODGt7jwYrZOkJqlYm 20 | 3P0S2TQY7UWE3he4UsC9JUwMS+KRlOcw9d1z 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-a-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDkDCCAXigAwIBAgIUMNl1awTAfSTQF6dkQXvlf2k61cgwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDBD 5 | MAUGAytlcQM6AMdPDCjSU+e4DJ8itsVK83kiPfJ7toEBF/VqA2EX94notmxft08f 6 | g9PzFEejh7HuKa+DbBr3HNycgKOBqjCBpzAdBgNVHQ4EFgQUONaAKMbjkeprYFH6 7 | mOr2YMLPySowHwYDVR0jBBgwFoAUvT6s5YvTw9zHG5P7MCH0dyJF6iswKwYDVR0R 8 | BCQwIoINc2VydmVyLWEudGVzdIIRd3d3LnNlcnZlci1hLnRlc3QwDgYDVR0PAQH/ 9 | BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAA 10 | MA0GCSqGSIb3DQEBCwUAA4ICAQBvsjJOmdqoSt6bAPiilmNRhgmG4F90mEMOOPtO 11 | opIlP6oj4DQOvfp600JX3Rmb3UixHUQCscxhYY3Y8FC44ZZYa2UAwTotvjCsVWis 12 | USnKPXTfORQfD3Ghy7IhYTPe7Dm2/NTjq3iI2CXn9o/TvpDwa8zixN3hJuNJkkhC 13 | xDW24YLYZ9Fhdgsnie+5yo1q4BGKFWtGrofOOqBmuR1wMrtFNy2M83Vs5xnUGqh2 14 | VIKMuIkShvxu770cX/Q3REjXiVCr40E9y6GVEe05u6io+SVse8h6QzVkzPpf6Y41 15 | dqKIskiCIqh//DqXKnU/n9wGY3uJn40njEhrz5cYi07B/qkAOa2/AHsYiyeYnufk 16 | 5qveFumkcoQI7e8t+SlS66BVXkPI2zI+PXCrC8VEtlXgTobx5BmQfOzRFuv63XE1 17 | TU4VUZOqyLetPkRjoTLfkUUvyrQwwEmkikp59B2xuyQXjj1ggZerjcrF5G+SOeMA 18 | SSdXq+xiGmTyygNFhXNT0TocWFjqorNPnCyN/Nr6HBQd9dridWJxjzLih9Y7lgkj 19 | bOWihvn+BclA6NBGl7dDjEBLdlsXP5URvQEDJt1Xr2aEWzw20POOUCxqO8pDOiNu 20 | 8oSqApcJGXHCAKO7ctcPSX+hlfvc1UJAPg8wrFniajM3MIP8cLXEpQQJCSh+TAAB 21 | jEEeEA== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-a-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEcTCCAlmgAwIBAgIUYLm4Qk08LO2HuLQH4HYLwZPrkRYwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDCC 5 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOgEEylkJQ93TIhgtLfaweh 6 | XraFGdsKMONZplkBYAqjD5+W2Uw2JKvdKVOidvB+yxlcvJHgLynzqgel81LRGUdj 7 | pQraABHiLtnxUkqQZ8JZboT9TzM0b5b+EOiXN7mLI4szQCTtAwXD/3PSgGqaZVml 8 | Sr8+fRNtraImz/8CHsToIltzC1e98xbJfwilFQZE5KMEihevnk5TyHfZAZa/1m2/ 9 | Er/xP1QSF3duptSTOPmp1ChSAhi50QLKLyEa98d/HdK1YHjY1SRDjVMTPeqwtx8e 10 | 7jx3E1HzlbPkuHo2r/vrSI4gsrAZgpnyUetR+ckIElPca+GkU9Ebatcx3ZdsNj8C 11 | AwEAAaOBqjCBpzAdBgNVHQ4EFgQU/l5gIv0xRNSeCf8EMjVIcXjb6k0wHwYDVR0j 12 | BBgwFoAUvT6s5YvTw9zHG5P7MCH0dyJF6iswKwYDVR0RBCQwIoINc2VydmVyLWEu 13 | dGVzdIIRd3d3LnNlcnZlci1hLnRlc3QwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW 14 | MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA 15 | A4ICAQBaPdio4yT9dFX4Q033tttTESpcVVkBIiNOymR5to4t7ZRxELxQGUdhm0+Z 16 | +cyKLF/BXknBbnDms44detnkQKwZrj4TKzQLANRElxbYVaXSSIzpHfs90cHOggvc 17 | FArH3tWWc4IyD24+DG4wJ4wymrxsa4USyONB9KgcmJ++G0GOmqodKYcatIFoJmX7 18 | E8PS0+XddMxDL9RESO32T/b+KxA4ws2PDQGfJca9srAfqV788zbFlpYDUrSDHjF3 19 | nZc2xdHmgaw5DsciVCRdLRwb6gZaIEAcavQXNm4wazZiF24sc8or0vHw3E+9Gj98 20 | e3Ek8p+iZ78y0zErCrybJZpCPoTYQKjItVcjtUH9+aFhDlpHjv8pVE2XxHXhYGGx 21 | gFXKmbmrJmt1lEDhsORrloUwbTFsv41uBO/XUuVLM8MbdAenqfZ7e+Rnp2Pj03yh 22 | iQwl9cTS4ijq5MZJysO/hvYC6cXIWRqa8D+xBXYKKneGHWEP0GUFN4xjxV9AVQ03 23 | kZYR0raklH78+mAMbZDisyvukkCezJ/xyrhZgW0vJbqCDaRXe6mCwYUknTRpdA77 24 | wE+Ik1lecK8urymhD4w8RzVvDjtomN1UleOoYaz9k1+MTS+Elcfw2sY8HP/RCtue 25 | Ui2srEOmqANQWb0Sm3+ADGf8OsVlV4dI/1+ejYz4jKkq/HBUFA== 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-b-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDpjCCAY6gAwIBAgIUItUnSRPCTOf4+E+fS2NlYfZgUfYwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDBZ 5 | MBMGByqGSM49AgEGCCqGSM49AwEHA0IABIdxIZux8FXCEG2iI9amWfre95E/hUzp 6 | uuV5Uy0w4cIxVNAlrXp1mU+U4/ZH64xKJgeWoxvZPFcSK9YkeTgamoCjgaowgacw 7 | HQYDVR0OBBYEFALLaBNxef2qybkjchaf3Wc2AbFvMB8GA1UdIwQYMBaAFIOWh0Hn 8 | 9twuwdnPWGjI3TuIO5wmMCsGA1UdEQQkMCKCDXNlcnZlci1iLnRlc3SCEXd3dy5z 9 | ZXJ2ZXItYi50ZXN0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD 10 | AQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAIA/Asb1U 11 | HB3RQfJZE17MwyyDs8Z4oFD8pqrN4SqYHZNyhxYGLHhfiu8aIFAdidKOSi/t08kv 12 | WUR53W+uAWisWbXUNOHT19TYA252C6y0tZto0dVG6Khn8Rq0F4xF9w3Iebls+aZs 13 | 8Zs+JWkWlHnHjCCGndw4w+tXkORKjhwrgIM0SSIjD6BBrt/bV6JU1SVH7Dk/fsGa 14 | M3jaCeewoS8/4Klz7DiD4o41bVgH92+p3qS+dBoz2eC/aDRcdHSk3VBS3SfLMGbf 15 | PdcJVTbrydNGiezKKvsTVrKxTvc27crk0h31iZd9NbgYMOYU/FWgyh5IIfaG2iiA 16 | KgfZmorrdyWh269heejf9/eL+ngEaZJNp5pzALO1V1fzJhqfU97+RAVI1hyPDVG2 17 | wGgZwE05SHrx5gCx6tplW2c8bRHpxmscDadq7iArPkYd+dXLTzbD2LOOq9QLSnDA 18 | 6UR2amPbTma9xLqX4A0lGISfLCMIx8s88+79VaTeEWqhIoCHyYQDVaj3RbZzcW6Q 19 | cjm8Y5eTUs+Q0sP70vgjpTHl1PtJafd/ejTskepna2ks0FCgckx/IestevNKp3Fr 20 | y435fiyFFUShAloLt7Oxo924iYxBBTOKufjWGkMTY8HJBF0gWuopwwu1hZEAp02U 21 | m0XynAPa4ws1Nl1nzDyFgk+uXFUoqdYRsRM= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-b-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdzCCAV+gAwIBAgIUV5dQvsi7hNrpcfrnWfzgz/2G2EcwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDAq 5 | MAUGAytlcAMhAEaFzibJ2WYDQLy6CKLO1DsBtRSamu2I/ZTAR4WWb7PZo4GqMIGn 6 | MB0GA1UdDgQWBBSittUaOGZGj9+B4qEDXa95bO7CWDAfBgNVHSMEGDAWgBSDlodB 7 | 5/bcLsHZz1hoyN07iDucJjArBgNVHREEJDAigg1zZXJ2ZXItYi50ZXN0ghF3d3cu 8 | c2VydmVyLWIudGVzdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH 9 | AwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAEaygooA 10 | yN/M+MyQ5zTZ52R2R0riOjz3O6viVHud8Ry5ZLZlmHD6kLm1w6b0uTpDZjvZu7JE 11 | D4zm4bZpcFgTV/Eqc0C/PF/RPDJFSyq5WIDaK+rNWrNZ9fnE4uc6JmjIxOgbmarz 12 | cij4MnvBYXeOsB8ZJZqgAKK/+hcHx/WawB2w5AdYj9Yh4KEGCpR67XZj/CuhMtEG 13 | feaLC+Nl6U6HnvCfmWAZBeoe0KvBU/12ItyrUzXZcnEHqOy9Xdx0RyaOvQOklatV 14 | MB4FgT0JijJP0dQYB76VJRoi0Xno7zgpKjJBYc7NJsr8T+KvaEqcomvOGs6NLp/X 15 | ZxWDdLXZ9wy/2+bPpigMFQHSIezJUQ1+rUP1ScB/VBgdMaNdL2J/jq0GTggHFbzb 16 | zuNg4aZmfo5zU4NaVO7kWDIzthyefDpQQz+8PJoIOcNaPGeDKF/PRI/cgj9vus9y 17 | zQlb9VNHGv/Hncdu0YV83fBx7Zt6nyAz3aZPjfWNk3b0Mtlxe6+QniyVlQb+Kps2 18 | i5jR7iVB22Y5pvA4AMqyZK3VVorqd9e5u2FH5VTw3iWSfkWBkEssCgvAtsvYAXPQ 19 | Yo/s8u80bfkFkoIwe4F04DSl8xbsJYtf6C/xMOWeOe+pAyPAxZ3ZEvqOOXI7ZGYT 20 | 6a9T2UF4j36llDyOj3RSIZriksvJ0oUdEt/N 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-b-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDkDCCAXigAwIBAgIUNmscOl2WAUPa2u1VCRJhKbT7Ks8wDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDBD 5 | MAUGAytlcQM6AKXmjhK9UGYOmw5uKDVB4Mrn3n2KnUZVbEC65KLZ9AhqJrAwpmEP 6 | 4j8wyIJmlJb/MeChYDPRucPegKOBqjCBpzAdBgNVHQ4EFgQU/cbGWfj7AJh6tve8 7 | 1li8gjvJlScwHwYDVR0jBBgwFoAUg5aHQef23C7B2c9YaMjdO4g7nCYwKwYDVR0R 8 | BCQwIoINc2VydmVyLWIudGVzdIIRd3d3LnNlcnZlci1iLnRlc3QwDgYDVR0PAQH/ 9 | BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAA 10 | MA0GCSqGSIb3DQEBCwUAA4ICAQAzZnocE7oaOLmmAOtcxounYsn+FYpWkfEybAlw 11 | OFSAo3CHfBqFKt+qAagMI2v2Kpi53DPjumD8LJ8e6PAG7czobZNfhsFhUnRqoPil 12 | trtli8fjs8GhOSAfHbzGkpv+k6XdK+6wUQE7EPxxsUh2SNWUv/siAaUpeVjT9Ctz 13 | TeNQA1xfXXdii7FJEhYTrm6JkCUmvj3Qr6HyKhI/rIV2cUyA+VSPhAQQPd8xqxLm 14 | beWhPA54u/wmtkct59IOaCyR7noStKeVMhJEh6DjMkOx4j1ibLTArWEezWZSMjKO 15 | kNaXYULWBz3Da4q008Uf0AVgvhSZ5QXNHoNVxhq+tyL1OqWjMHc8XHIPHwy9Dpv8 16 | Z0ZhewNUxdd79O4qgP0mYQCsU/W7JLol8gMcGxVD2xL2JxkqDOgMwidcnm1IsdTN 17 | NSl3YgqSbLtrMCTpC0r26YiScOMvWI9/4AGn4aGNEgIHDiP77h5cldrhc+YrKAbF 18 | YaD54z5VCu/ZFbi/ux2iX00fvpGoaQlb40I52762mXub7Rd2wU4J6ikPxeErx7Sn 19 | zWA0bmbx/RlqSlASLiBlwWM/xnmMBfVVvWwSdbvJgNdQHOvLn+5qfz2+6GxDjt0b 20 | yeqo/Bk1mLgbCAfiUQXshL9euznf1SNKJPeEhoaqyeQpaBJafOqrukKw1tVE7pam 21 | zFgEsQ== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-b-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEcTCCAlmgAwIBAgIUYaTZqC8uIwDJT2PygG8g96QLJ90wDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTE5MDEwMTAw 4 | MDAwMFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDCC 5 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN8QrtzQL8KNwwlKNsNMNWsI 6 | 2X7jJwPV4J2I48vOFrkbar7KnUgd6GSqoPsiSd2FUiZyp7hO2bD6Q//s6lJ6VveT 7 | J1ev2Ph0ViajQOXJVR2QxzQwtwJI2E4XEFTLk/XuXORBTZdu0OI+FUhVuioXEUol 8 | PdMehFbs5y/ieV7ZF4RAbI5DVAwM6WnbjU8jNbTjNMlFxPvUApB6AJTl6WJUnUQA 9 | b7qdC8DD9P4MslwsjenvtZY1cSBrdRfVDq4pC18/KJmX5n3VONjC2weEKU7cFOyn 10 | B7REtRS/IDdI+PUEn30iJnh7tdSy7Gt/uPmPJTUX+MwPGSh6qghb0RMHXEwVUWcC 11 | AwEAAaOBqjCBpzAdBgNVHQ4EFgQUCptjojFusQH16vdJCCh1JpTYBk8wHwYDVR0j 12 | BBgwFoAUg5aHQef23C7B2c9YaMjdO4g7nCYwKwYDVR0RBCQwIoINc2VydmVyLWIu 13 | dGVzdIIRd3d3LnNlcnZlci1iLnRlc3QwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW 14 | MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA 15 | A4ICAQCQ15QLwJSNzGQmensYvCg1Rey0RLsJq65u+Z5hz1h2MRLghnbJ9aKi42xA 16 | SELSlUo04AoPdC2c/2tg0Q3f/0Yc8Z/tp625t6VbPRW0fvKoCHQm3lXER69z60fy 17 | 1bcB8JnKFOS2mTc6dOvRYVkOtJwTq5hFgm/gbk1iKAuDw4vNqIdaKYgMEpGLzh1o 18 | X26Qo1WM8yToXxpiEWbF9w8SJj2WsLnxE9KYhZTFg1Qhmnf4k6D+EyutxVDDK5Kn 19 | dsZC0FcIRgEV3Uzb20Sr2X9R1hWEqhOIUB/NDg0AI0UkJ21Ot9PxVRXz00p+1zBs 20 | k28lnOYS4SOy+1rhQ4Ayf95quff4JpjMD95M6XowuF6oI0MP8AI1DaglaV9G2N8+ 21 | OSnljWQJw2BtRw2MG+jf5gwWUMyxgobMuHbmiYJoT8/pEenVTGOhjm7QCDj7junF 22 | plSNEQLwYPdSd6hehAVrnqdF8DAs2khtws5va5EGhZyFs55Sl7Ozpb7Di2Jk1WGZ 23 | EuR96+9OhQ/wUKdKlzZW2qMYZSFEo4zPoLOIg6aaop7ZQk9dmhP5hYQzyUpnMf4n 24 | 85gfHF6WBjdrAuD+yng8jhxxz+nx82cU4MS8t/nc5Q6LR0os8MMcv/Az21mz2sb2 25 | NjSILOl5+5OOCqoWMmBVu25t5Mt5L23UwT7LxF2/uDtbSBfcxQ== 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-c-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICBjCCAYugAwIBAgIUYZjFSlwPHHCYT6ETQlRKu5FOZhswCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTE5MDEwMTAwMDAw 4 | MFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDBZMBMG 5 | ByqGSM49AgEGCCqGSM49AwEHA0IABItKipDYXNhoXJ97T8Uzu1Xc03fbT5uy7YUs 6 | B0YxFllENUYp1D7IMOQxn1DXoELgpyr9AemWzfPid65/mmsKvOGjgaowgacwHQYD 7 | VR0OBBYEFFQfT1ulFW0FkDCmZvUduRgObCL1MB8GA1UdIwQYMBaAFLH2lYI1TiZt 8 | s0eoGxWBHO9pzqSnMCsGA1UdEQQkMCKCDXNlcnZlci1jLnRlc3SCEXd3dy5zZXJ2 9 | ZXItYy50ZXN0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI 10 | KwYBBQUHAwIwCQYDVR0TBAIwADAKBggqhkjOPQQDAgNpADBmAjEAuTI5XmfD+aDy 11 | y9G/qpmlkUu8EbnUih5U0ICUZT36g1ZN2KwIemcG40mGI7xvGUdCAjEA9l9zqHkC 12 | YFqbopP8CA3oJqEKaKW7waFbwFJFVzGfH/jfnZuLzkNtayNeM48nRTD+ 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-c-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB1TCCAVygAwIBAgIULRBAsZaNSzvcpE6BGsVqKRDyUwQwCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTE5MDEwMTAwMDAw 4 | MFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDAqMAUG 5 | AytlcAMhAHcUqym1Qj54KehXrjxhet7L2UWH4ge3l1ovVGONiE9Zo4GqMIGnMB0G 6 | A1UdDgQWBBQd1oYhjnxMWOIIleNARvaoq0R34jAfBgNVHSMEGDAWgBSx9pWCNU4m 7 | bbNHqBsVgRzvac6kpzArBgNVHREEJDAigg1zZXJ2ZXItYy50ZXN0ghF3d3cuc2Vy 8 | dmVyLWMudGVzdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG 9 | CCsGAQUFBwMCMAkGA1UdEwQCMAAwCgYIKoZIzj0EAwIDZwAwZAIwHtcK0SoRgFle 10 | u0phZtt6SMqKSkKMv2f8m+CmCbxgORMf1AgN6DdK9oMXwAjSlIfaAjA0QhR6u2gS 11 | X7DmlRVR8T8VgQNsjfZPmfuDkHFE/UxWIv98LuH8LjMRFQNac98szY8= 12 | -----END CERTIFICATE----- 13 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-c-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB8DCCAXWgAwIBAgIUR2YEF0reVkhrcGQVUJ8lpJMlJFQwCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTE5MDEwMTAwMDAw 4 | MFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDBDMAUG 5 | AytlcQM6AAmQAocN+EH6EcS3KMbbbV0lqnsnMPSXCnuiG7faJZj41KiEUG/+Y0k1 6 | oGHAn3uZmudeDdC3IhkwAKOBqjCBpzAdBgNVHQ4EFgQUovaCa5A2A+PBGnd75B1r 7 | TEG21h4wHwYDVR0jBBgwFoAUsfaVgjVOJm2zR6gbFYEc72nOpKcwKwYDVR0RBCQw 8 | IoINc2VydmVyLWMudGVzdIIRd3d3LnNlcnZlci1jLnRlc3QwDgYDVR0PAQH/BAQD 9 | AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMAoG 10 | CCqGSM49BAMCA2kAMGYCMQDa99gxyqhEk4PBBZOq+VOuCPIHtboOCPrVN8j0scVr 11 | rcKWPtusfFgaOnzSGiCV5P4CMQD88ity7ssc5A8ZDhH1jAm2rvb5p5j8lPMzOkgy 12 | dLBCETXbsVMtNWTojKS+VpgaJ+s= 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/expired/server-c-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICzzCCAlagAwIBAgIUW+zpYnKgEO18foR1cpOgxZhyPhAwCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTE5MDEwMTAwMDAw 4 | MFoXDTIwMDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDCCASIw 5 | DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7LzsdjuxHQfbO4sGo2HC+vI9JT 6 | FSSOUXkVbS1aNHqVa04iMl8bh5PlH9FrimUCa5PmYh0Xo4E7IKs7SqbeRBMb7Mb9 7 | b1pBzlkyUZ4+SlwHxCobi80l0eATr2Kx2zlx8/in5GyqyE78wtJG3h7uHyu8jzCz 8 | 8m1mEkFC1KSZ0GG7bFE20oAshQKVBwTJMhRPDGqvYDvDcdjUKzIB1psDLrIP/w5A 9 | G2kkzCYaAqZerjuIjiaHrxF2fFeroxUqYvb4O91WzpY66E6/az3JTbupcqXn9hz8 10 | M4gUyfjLLcTej8+w0HFWbvDFZ7pmyilLkSvA4ol2WX+CHszPwm5uuitSLiECAwEA 11 | AaOBqjCBpzAdBgNVHQ4EFgQUjSQbcaGFgWB8CsgHkpnD9O00k8EwHwYDVR0jBBgw 12 | FoAUsfaVgjVOJm2zR6gbFYEc72nOpKcwKwYDVR0RBCQwIoINc2VydmVyLWMudGVz 13 | dIIRd3d3LnNlcnZlci1jLnRlc3QwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG 14 | CCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA2cAMGQC 15 | MGKpiQgZ6Uy9UX4QJiEvRqqNGOQRb8r1JVzFBSpyQrkZgZsSJudlGXnM1QX4UtBm 16 | cwIwDIz06Pez/idDk9B4XDxRyqu4DtyrAUZBCY+5THiEQm3jgUhKnivuphvsXey2 17 | ALT7 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/cert/notyetvalid/.gitkeep -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/ca-intermediate-a-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFSzCCAzOgAwIBAgIUO9xeq6DU2xWYokRJs7I8tWIVbPcwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMiBSU0EwHhcNMzUwMTAxMDAwMDAwWhcN 4 | NDAwMTAxMDAwMDAwWjAgMR4wHAYDVQQDDBVJbnRlcm1lZGlhdGUgQ0EgQSBSU0Ew 5 | ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDWmnFHwwL46rj3PP25nX/u 6 | v4Mk384WeL5S/uxeFWbf1v6EmyxRIL57L9EWehy7OE7NWQYhzcglLoTw+nmRcxvD 7 | UIGfQKsfEyn/LC6yw9r80aKyZrCrR4VjOnAm53nx3D6dNkHs/rndnI38Uycn9HRM 8 | O9mPkfeIOl7/pUoWDd/dXx33BLtH5Om4p3KhERAxzSFKIo/D3V+j2LZxzK4TB9Lm 9 | eoSyMxL/fzmaFkdIoM/I19KntphQ1BL7kC20N3/lbP8fIGtEQNDUUDXJTfzXnFgy 10 | wvfdBpdnsxePiLan4/nEFd0x0UzZbO39gQ87d7OjjZbjXLmXsUeh5+z/lnODsC1X 11 | G463IXVfQbSXgymliCvxkcDL0U1K9sTa0yakgQTG1blY94GVwy7YR68z32sEInZW 12 | JFMFqAW73KY995F/ZgwJlz5Ia5C1WagesCpK5KjNv86OE3M/zmQwp4s/2wCe7+NL 13 | R5znjNRC1NfsgRpGOvlO77gjhqrfVKYt4yqztQ6Hok071Q/3vHXFJvJxQjJ0m5Py 14 | n34ee0QUktMDNJfen7qA3LFGw2eP2HqfDAeFfPDjtk2mv16hWWrUhv9/pms44UnZ 15 | FZ+YuVKXmz4GJqPVN4tm1ElRz7oLjwH1HCCVdODR2s3QG4ogmFHf1S2afPRS0+gm 16 | ksBwytQgFXHwEJPLY9mifwIDAQABo4GDMIGAMB0GA1UdDgQWBBS9Pqzli9PD3Mcb 17 | k/swIfR3IkXqKzAfBgNVHSMEGDAWgBRXdlhuD4MxcTVJ+LS+YaZDgU9YbjAOBgNV 18 | HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1Ud 19 | EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBACxtDxPpAhtfbdE0gLiUp8DD 20 | 9cNvJgSNAzg54khmKsE9dLLC5F+LsWhb/EByBo86UTKiTWm7I2oAwvGWEmfz8mPC 21 | CHGrqodbvefZoYMeZcqW4nNcaqBjz9FAu0726rDRbVBGba0oNsRQXleE9Ox0eJAM 22 | k0pocRAEF8myyURE8l9U2QTgsrqrseJTuXsjIIAggQB+O9ZZ31jIXZ66FewUrZX8 23 | bpoqHO+hubYiT8LcVm7ow3cIXawpuxctZXZUFMbQdridWRzJxB7iTIk2hHOYH8QZ 24 | 5xMRzH780PDnm9d13rMRmssNBVYeulgtmGLp37Hwycfvhg4W7lIRzVacA/30mCNB 25 | VZiROzjME5W3rNVvihyGqGF17D6LaS9GUhwQB1eEQWj723LSgvL1zc0nfX7xhAa7 26 | d8/nw2Qn6RCvdwuNjch8AK0zAVehnoY9Q+TPa0l0d74WiksmMdC02Wy3Quq9wAiJ 27 | cx2UnI0U+n0fnOA/DYavsVwQpgC5RB92724q4tHOr4Rw4XWEX3c32rxnWCWLn/2y 28 | +eHo79irMYU6btQDqGGKZDis88BYlMx67qRG46HkRYeaeDM88MVi1/6CQWAldJ59 29 | B2XOkg3kJ0lIfiBq2CMq2f+nCp7dTxAxviEtCUs/7qNn819wO67HAxuUbgXsMTbR 30 | qnJS/hnasauAmcN4xQoy 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/ca-intermediate-b-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFSzCCAzOgAwIBAgIUeg9cXzVyBsSUFtnEcXPIfbQNJPAwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMiBSU0EwHhcNMzUwMTAxMDAwMDAwWhcN 4 | NDAwMTAxMDAwMDAwWjAgMR4wHAYDVQQDDBVJbnRlcm1lZGlhdGUgQ0EgQiBSU0Ew 5 | ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC4v/5iu81f+u8tQFnwF21a 6 | g0T6Ac1lUmzv4DAq1OTulPiFeUV+w9JXdou3+hXHKbpLoicT525rvGoHqLafiiV/ 7 | xG387bn3cGqvUncUq/cj+k8lEXclvXge5hdt6fPJE+tMTqOMtVw80YQniGbKyMLW 8 | o0zwNPTaI3LdLltRE3JQdM+uA7LYbU4BTTBNzZDRtYdSZNN2/N6W3kndOQEIzdgc 9 | xlpfhXyN0NnYWMw8RJhyvfMdtuRPmItAeoHZBQjStRGYpaHxzmSe5ov32smXgWcK 10 | LUGfKrW0RnTfQK9AEKTDy9LL12+fllUwSwqEXuoGOzsk6+lvTR+HFaPlvp8ydvJ8 11 | +F8GmuWvm/W6RBNSc992e/ZA+7AT8rLF5QUWVPgNwX6ErnMNNueJWl7lJNXdPbjN 12 | K9oi2WK4geMCUiRlbkeLoIY213UtsZgOnaBy2VgEV595Dq+OIhTrepZ/jlyPL4pr 13 | jBfYKAEyp0NOEjv5R8j0c1dQwQdldzZX2+KYqc9Qifhtu5Guq6acDbNTjuG22VUB 14 | ZaeqBJKfQYmMcEUvQMzlzCfbqvb+ApIDMgthiz7ZonkrtRqi0F77anWfyVY28ruN 15 | +1BCUqdSRb5c/ECUyEGDi0fTXYm4EAzRIqQ8jlt5UkLL4hrImQJquI9XOFn1SuOd 16 | 3+fakJMgqa6FbC+ZVOeZKwIDAQABo4GDMIGAMB0GA1UdDgQWBBSDlodB5/bcLsHZ 17 | z1hoyN07iDucJjAfBgNVHSMEGDAWgBRXdlhuD4MxcTVJ+LS+YaZDgU9YbjAOBgNV 18 | HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1Ud 19 | EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAIzjAxyfdMX37Lr6FXI3uhuQ 20 | qbntO8c56lTMSPRZVIVdACaaSEvfMRBhsWWUnRboBEXJQ/Mt//JQ/nYFxdgPrLRe 21 | u4XHKu5v62cBDi2IZI+JXlYrEDivh0uv+QRxcYJhRoaj1FSVuVnz6IA3fV+CoDOG 22 | tdjZFOM2Ej23ptgmiVnQVMGhVdtwV1Gby48v2asU3cbw4tDnXpLfWBkx6MyGayU0 23 | g8Icy2hRFLjkcd56OsD+WM5a8G2FzA8D+bneTIdupi2htg50+NIfNJUN6eAx6j4B 24 | wMRq2ytPDudo5VULm5TjnvIVqQ6SlsCnfV+2HH/iiD9aRqPHMcFP4us7myiRwgtM 25 | MHeFxhXjr8hONv9b93mPpmgTigEjFLN9vtFaJGdMxbzCy8ITjdiFIGUMFNjd1tS+ 26 | LHfmtlT8VTE1NE5bOu72TYwxnraizNfGyJ9tjBtpv5uTwVfd8k9A452f3sgtF50c 27 | d0Iat+5QV0CzuxraOhcDBGBj34HCNzZOMFtyK5fJF3nYrlr68NRUuE5GcT7ePC+3 28 | ZKAj8L45I1rfvo/JDYpIIGMaK+TTZqJCVd4jkT4VjPlOCgEeJfOwZ+0TI96gfQt0 29 | TzII7g3RZKhahgclf5uLuLsiP4gUXvYSZ9kLaSaIkiTca7MwyhHAbxHE4ecl2ZLp 30 | hkdm/Yt7RxUxVDx90vqA 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/ca-intermediate-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB/jCCAYSgAwIBAgIUeueI52QAgwGikFdhBBQuCD0IwegwCgYIKoZIzj0EAwMw 3 | GzEZMBcGA1UEAwwQUk9PVCBDQSBHMiBFQ0RTQTAeFw0zNTAxMDEwMDAwMDBaFw00 4 | MDAxMDEwMDAwMDBaMCAxHjAcBgNVBAMMFUludGVybWVkaWF0ZSBDQSBFQ0RTQTB2 5 | MBAGByqGSM49AgEGBSuBBAAiA2IABDH68FN1KQhd8jhowTn5qGl077emm6tajcyj 6 | OHwYOUubEPHCW0APMhlw3Qf55+321Dr258N0nLItdG/1K87Xl9QZAlFQq4nKKmaP 7 | yJKxrc1o2WRq//0umdPR8KrHKB3REaOBgzCBgDAdBgNVHQ4EFgQUsfaVgjVOJm2z 8 | R6gbFYEc72nOpKcwHwYDVR0jBBgwFoAUJGmroiOJjCNbQHlDvGD2SmQT7i8wDgYD 9 | VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNV 10 | HRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMCu+5JeCih20Z8qJHR9xUhcb 11 | mgsKnohLDe5meKutdhYf+Hjl2oB4zbkYhoHTAlbE9QIxAKKCAtJXHcwiMw+QvPDI 12 | bTw6qL+9aviOaGpxincXotIxDmtGX9V91COGda4+SuDkLQ== 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-a-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDpjCCAY6gAwIBAgIUNtGxc92apvG2m//jtauCE/nZxT8wDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDBZ 5 | MBMGByqGSM49AgEGCCqGSM49AwEHA0IABDbuI4eYuleNoNxyQBiuZy2SwyxDrP1Q 6 | MjS2JvQC+2yu//HnOr0wf6SyLSrHJadaYWU0+MySBHLUXyaHFOJIZNajgaowgacw 7 | HQYDVR0OBBYEFLZ+yiKISmB+adhsX31oXQMTYQo8MB8GA1UdIwQYMBaAFL0+rOWL 8 | 08PcxxuT+zAh9HciReorMCsGA1UdEQQkMCKCDXNlcnZlci1hLnRlc3SCEXd3dy5z 9 | ZXJ2ZXItYS50ZXN0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD 10 | AQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAsKIzElHK 11 | FRdWBcMryVYHl9gBCkJKXtk4dIaMD1ofm+AAoWZG9Qeo6gwbO04PVuDHeRXjP/MF 12 | h9ARGeXkYDc2+he9PMLYbPbql/YlsrDiAR9IRVP0vNdDQWJlpDj7P/icTKEUOmSI 13 | QI/cuaZOD5RXYnWIsqcnU11GMS1gwtlEGX572JfookSjkd8zcLIZyENfu3VCthCD 14 | lghBbiQMJD/zMdKULMZ0543nKzhXP6QUb2AKy9c7eJUjotl+MPHaePBRfp7VZD61 15 | GDEtPATutKHKKKVwYdat7O0BBPYwDDLipKRl74Rq5UqqXE6Nqlp5u/23LbYlg76T 16 | YuQ5Fc9MqzLJQ482PrVQtfqXMn0Kg78Zuu/ulXlLsspRpfv92qBk4eRabrOfKWnX 17 | 9VwghixZ9ptCxz6utJhhcD5JXv7Yqdfr19g2ypTFjHVuXcIqEsfK8GiMM9uhHrvj 18 | zlJ8EXe0yV4YVOLhXtBPG0kxhyiY/CqssVeyjOkTKyCJTM2Nde1eWu7w6CQ1986y 19 | wbHQhzbrvepoUqiUDuv9ADvifFeKXj/bKl3CNkQVcaUOd96mMsLEcUknskbrVx19 20 | TpNQZoKKPKMGBYpJbAzmKvpDaYcKNgtHD43HQtHf4Dv3bCPyibuisgwmVvw3sbSr 21 | bIz2uvR/YgAEe1EY8Z0J/VtVGkD5kqNjoYI= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-a-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdzCCAV+gAwIBAgIUMET0JOeu0vl1kZ4SHa0nYWGO/BEwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDAq 5 | MAUGAytlcAMhAB2EhIA6Tw+a1sd3c4qNwl4dI6unqqFxwc/9JmrIumcWo4GqMIGn 6 | MB0GA1UdDgQWBBRcaa7pReT4icTK0QImXXHlUBEekDAfBgNVHSMEGDAWgBS9Pqzl 7 | i9PD3Mcbk/swIfR3IkXqKzArBgNVHREEJDAigg1zZXJ2ZXItYS50ZXN0ghF3d3cu 8 | c2VydmVyLWEudGVzdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH 9 | AwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAKsJzvWb 10 | sCrclu0Oz77kCwBKdfrALAkNrAoXrMXyVaW6cHhh35l/Z0A57gtlkWBJIwvVohFv 11 | eBotsdK1gzQJIz4Dv6a2VtW4vE8AANmS28yHRr3a2WQ0lqRbkHW1R2a92VjibgS2 12 | pfp28kwMvTk5KaD0n7yHlbQ2NKUgcUGFzPcE99M/Q3IRhDDHPf1vi9D1NhqF2mKG 13 | UkW+Ys3Znb2kJc8Zo/JARR4aaEitUZKCR8k5nyKjT4Qfj35T7SbFqkMjkKWkZki8 14 | HAoynDz7uXJOWdSIAJapwxT4R6twf4IBIfe9960B1E/kkqkxtGHN1Wg4Z+AQYLy1 15 | cWDiiwAEebTm4fghPyPbJ/PYJ/3htZhHNSmoOuQB5AnZevliuFFR/E4khWvQZOOu 16 | Am0d+4d8xHIdYjrWimV0BsWoChw/uanued0SLHlfOnCiafP3I20h55aoxlSZbgd1 17 | DcvrpzY+eAISB8k//6TAu+VDYb5KTiQO9vn9hKUM3oMY84DeImWb4fH8Iwk0uFGX 18 | hRxvxvq3it7XpooASpK3CT/lh4agUxU1z72l8aYA3HfVf9IE5uwotBmfkQp37FyL 19 | vXZRAgsVoW9RQp6ssaUgfPlCtKkcTk/lnaM8KMsggKF48REmy2rhO/ZTd+MeexH3 20 | drSpsbfY4hCbL5urhhkGM+xdAUlqysjyfCh0 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-a-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDkDCCAXigAwIBAgIUBsnzl3nfsEiPl1cueNsuhs+NQtAwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDBD 5 | MAUGAytlcQM6AMdPDCjSU+e4DJ8itsVK83kiPfJ7toEBF/VqA2EX94notmxft08f 6 | g9PzFEejh7HuKa+DbBr3HNycgKOBqjCBpzAdBgNVHQ4EFgQUONaAKMbjkeprYFH6 7 | mOr2YMLPySowHwYDVR0jBBgwFoAUvT6s5YvTw9zHG5P7MCH0dyJF6iswKwYDVR0R 8 | BCQwIoINc2VydmVyLWEudGVzdIIRd3d3LnNlcnZlci1hLnRlc3QwDgYDVR0PAQH/ 9 | BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAA 10 | MA0GCSqGSIb3DQEBCwUAA4ICAQCWtI3amDhQ3BJKRg0T82SMXUt0oDloIsEtsPNJ 11 | p+mV90Kz/xhbJWsTf9Mm673kQRiN8ARZ9TypZaLbot0SFP8ehKsI5zJP+h434Dv1 12 | CG34zfRcv/SHA/BJs1I7vsh14CfmaNqyjNMDIQsHgZAjtXp5k0+CWlB5WBKIdT8M 13 | KgmQbq3lbPq7hEO/q/nb2a78WXSQPUi+eLDUMkmoRWb1N5oOVthnORhVNPsD29k7 14 | ZdZR405B5AQUWx1PjNec5xoS/GK8q9oV7yG+8MaZcYwaLrjlsKq1+/waSzGpPIP5 15 | 90VRiTp9f8Yz0jMCazbZ2GZSU+YibVoFTC1lB8iXDifUQL7epPLSLEl5LH6KJ7ex 16 | qJpDQBGUQMTLa2hRu96hgA3IDc/0AqyihX/XxRWg9gOjzrulqMvU1f1U1AEni75x 17 | u0bhl48PxUeO+iHpFPLT4kAEKA+oThd2crwgAkit6aWXQV7CrBTCgrpmigWkAy8J 18 | iAUDS22N9W/TKOZeVvdhhqoWqVjnEpPWS884aUA7COA1i3xuOondRTPbwN3whdJi 19 | w0JuMtdgvOpaCntEg6BB05Ig8fSiCK8myqJy/9qxs0YW3cgG+aMFQpSEmX7sZo+M 20 | KaULLbqgLqMLeyD2RTtbn/5wR9wJaYx0IP7+yQ46sfetUKMGe6d3OVvGHUcso1fC 21 | gJL+kw== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-a-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEcTCCAlmgAwIBAgIUOQQXprdsUnbv3X0XKD0s0Y3feXMwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEEgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWEudGVzdDCC 5 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOgEEylkJQ93TIhgtLfaweh 6 | XraFGdsKMONZplkBYAqjD5+W2Uw2JKvdKVOidvB+yxlcvJHgLynzqgel81LRGUdj 7 | pQraABHiLtnxUkqQZ8JZboT9TzM0b5b+EOiXN7mLI4szQCTtAwXD/3PSgGqaZVml 8 | Sr8+fRNtraImz/8CHsToIltzC1e98xbJfwilFQZE5KMEihevnk5TyHfZAZa/1m2/ 9 | Er/xP1QSF3duptSTOPmp1ChSAhi50QLKLyEa98d/HdK1YHjY1SRDjVMTPeqwtx8e 10 | 7jx3E1HzlbPkuHo2r/vrSI4gsrAZgpnyUetR+ckIElPca+GkU9Ebatcx3ZdsNj8C 11 | AwEAAaOBqjCBpzAdBgNVHQ4EFgQU/l5gIv0xRNSeCf8EMjVIcXjb6k0wHwYDVR0j 12 | BBgwFoAUvT6s5YvTw9zHG5P7MCH0dyJF6iswKwYDVR0RBCQwIoINc2VydmVyLWEu 13 | dGVzdIIRd3d3LnNlcnZlci1hLnRlc3QwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW 14 | MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA 15 | A4ICAQCveU08yh81i9sSV0CHe7ihkDsaYIJohvdDFQN2qCQ54PocFrxx3ML1GP/z 16 | sVsx1Zf03xKYm3rhOQtCQxF6c3QRaYKbmqM1Eah69HYmB4SDkyIZ+Vb5pd5BKa4I 17 | ALXGa6eVQbwSwZCjzkAwatTDWd3YJofB5rHQh2ML6Rxdjk0vfGw0Jp2ML8j+wtQQ 18 | qH8km9E8J/B2SYV6bvZMYSQ8uOj/opfmIADAvGwyGBSE6csSw62s46BS93PM50oI 19 | QLzWXR4N8111qjTNCrne4dFt1m7gQ+Rqtm1pQ74iC/YNV54ST4kJm8lm3fS68u2P 20 | OKOleI5DGYEYTl+IqG5FE3rZoDxWUQeFeH9mQZYpWU70fvcNeO7wu/TuXDflkWiM 21 | mcqzNvoeYD3qaVknukUDK1qur8GVC3dC3OEIV1gL08GbI/0oFR4Mgq4N8RrDDPMI 22 | 2RqirD7Wus2BVtxL2381deCbSZUyQtCfVFnpIPmnyPee4uBTT0HTAvljKOFx46IG 23 | SIyVlZN9bawf4mQqoA6pBkXtICwc0MiT5IC17vTK/3zkjHJ6yYJ8jcI4oCpu75GI 24 | EqBpfwf1zV1QJC2NzmIOrUbIGJgQQHsB1gr2Pg0HEGmo7+S1f/g0qAfe/Td9pS2G 25 | qpbzGNJ0/AZFRt1O1a587rcufHf1xhSpFyJiC8CzR6MvOEV88Q== 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-b-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDpjCCAY6gAwIBAgIUfTFtL4F4huAgmiIjl8yAtkfrjDMwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDBZ 5 | MBMGByqGSM49AgEGCCqGSM49AwEHA0IABIdxIZux8FXCEG2iI9amWfre95E/hUzp 6 | uuV5Uy0w4cIxVNAlrXp1mU+U4/ZH64xKJgeWoxvZPFcSK9YkeTgamoCjgaowgacw 7 | HQYDVR0OBBYEFALLaBNxef2qybkjchaf3Wc2AbFvMB8GA1UdIwQYMBaAFIOWh0Hn 8 | 9twuwdnPWGjI3TuIO5wmMCsGA1UdEQQkMCKCDXNlcnZlci1iLnRlc3SCEXd3dy5z 9 | ZXJ2ZXItYi50ZXN0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD 10 | AQYIKwYBBQUHAwIwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAJEd2QM3F 11 | eiGl8Mk+u6G2cypzMcdYr7VgirnmMK8IeaMUZ4nxj7/iiu7I9ntLeCxkc/Y9Myqk 12 | OP4iUmsIMy4DCX2wro5f+pzgelheQijitzrHeCSE0qcCZZG1c/jwbaWhOMFQMpeb 13 | V6N805htGvKMSD79q8vyARSbfC0Whx8AynQoPcJLeKHeliGVvGsB18A7yy29CPo4 14 | +QbEwaqZfBcA9rqCbwFqsdx4OTJbvUjHUygEU+O0rkWBQTObaeN3s36tvftpKCqo 15 | eavmOF8W8TLZfoqi1jfffjxOWxwr6GLHx7ECvLJ+YhW4+i5i9cwg+bcJuf3IdSW3 16 | UgpRg+2xwsoRHSe+rJAp97/uHwRKIl/K/prTZKJAv3jdf/htIxSMFsD97q9vN5pn 17 | X9lbh7SSkoZGeXUJF+04UGf0DXxFBisXmSQvDmw5dQvBpQf+YoSepEvUGZB2h9O1 18 | ntWjO13d+eMHzoUcakxS/oYOMWCRSSmjY1964VR3nXJTvEd1K+De/yF7uh75ND97 19 | 1muHKW3FPYEyRTk7VZ+3Mih92NbG0YdK6tS2Tx5oKTOkA/3pi5SYDhE2Pcn0bfBo 20 | 4h0z1DYK5Os+365Hdqgc1EuAZqXsrlVkf6A0LZbMZSVB+It0OS5FgjQp0JHj46MC 21 | zNu/Y29ewzCi0U9trMDPafE0Nli8PVSt+0U= 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-b-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdzCCAV+gAwIBAgIUEeC/zOE5mlYEbu9LZM6FYbryUh8wDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDAq 5 | MAUGAytlcAMhAEaFzibJ2WYDQLy6CKLO1DsBtRSamu2I/ZTAR4WWb7PZo4GqMIGn 6 | MB0GA1UdDgQWBBSittUaOGZGj9+B4qEDXa95bO7CWDAfBgNVHSMEGDAWgBSDlodB 7 | 5/bcLsHZz1hoyN07iDucJjArBgNVHREEJDAigg1zZXJ2ZXItYi50ZXN0ghF3d3cu 8 | c2VydmVyLWIudGVzdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH 9 | AwEGCCsGAQUFBwMCMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBABFAMpXu 10 | KFBHs8ukhC59djaTRNWHOVMHkOCCTRxXEJ0m3IpSPbPlRDXEyJDhsGRn7C9Vwewj 11 | YUY823qi7WWhQN2xxgz7syGbfo1zpfQtZyF69JcSSUWmx2GrENnciSRjnFf7+WwU 12 | X+o0mM1vfj0keB0zmOv2iR/mElELfhBzi4F0o+nVoIMI0nLulsmaddbNmy+169Uu 13 | FUm6P8Dis/V4nfGSgBOEWiZZQqL1ZG0Xsb9x9MvEDUTXh8rOR/oH96xMTLlzMZmQ 14 | piHZFqAjn40IoeBHYkbTzGix2oIUoE7utYm2klX6n233990ifA7Opu1wPXIa8APn 15 | NLverMFIDGEJyTKBlnH4NElByfjgMZDVf40wk+VUzvgm/aJdXSPOa38D3dnVgBGE 16 | KtlbAC/dZX198FNAWD0VH65ZECD/2c/RPHQcD5iJ2jto/JloK1G5zn9LRJdXlCdg 17 | w0RDz3V249yzEguF9sR64Bykh8LaJVvBJ0wJXiWDrSCO4Cz2D85kQzxrYUvDXA/l 18 | IzyPs4INUNhrPVzijtbac47k+YFBaZ7wdXpmR6gjocw/7gxyFqBro+WP6jlyLv3A 19 | nh/PghNxu2vYf5ySomQSzvCTLfbCmwwE4odoQvc4OqwWeR+AZGiKGYyN98UixFPf 20 | +bYhdsWLPpstT27Mp57KJ41sR7LdFphL7Jrg 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-b-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDkDCCAXigAwIBAgIUL+9w/SGGJv6+vdFIfFyzIzqQAHcwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDBD 5 | MAUGAytlcQM6AKXmjhK9UGYOmw5uKDVB4Mrn3n2KnUZVbEC65KLZ9AhqJrAwpmEP 6 | 4j8wyIJmlJb/MeChYDPRucPegKOBqjCBpzAdBgNVHQ4EFgQU/cbGWfj7AJh6tve8 7 | 1li8gjvJlScwHwYDVR0jBBgwFoAUg5aHQef23C7B2c9YaMjdO4g7nCYwKwYDVR0R 8 | BCQwIoINc2VydmVyLWIudGVzdIIRd3d3LnNlcnZlci1iLnRlc3QwDgYDVR0PAQH/ 9 | BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAA 10 | MA0GCSqGSIb3DQEBCwUAA4ICAQBv25xvR1/s+PsAaowX446lrNXbOLFFqYNhbQKn 11 | PRW9niejSY1ZX1QThcMZBU6m90z73WaFYDT/+yGZwie8d/DtlKcVWmlItv6sLLz0 12 | jRrxLv4Y+dIMuIUfGhWXalMPxYkulxJ/bWgs1aY+zfPv+/8gdfqYcbDMDmPngWYW 13 | FaPx5OktW1VCYqs9+taKr9jx+rrwvv3+ajJE80ofy1dA8KNxV64FZ9n1V6/AvUNY 14 | 5luMVw3eTpUStle+8huA5+brjGJxL0CEewHI//ikohZkg4XfFMlZfmMug1ylv+j0 15 | 3GnGzMP/+a0ReFstYdlFm7axC4B1i3FOWlwlrjznMkEcQEdn8SGRNzOk019LNf8O 16 | NPGVNXx/vpRrfMNG0yBfKDgTFgW4xa0FCccWxzyzWavrs/K/dVzGScSXX+j/kuVE 17 | h/Eqd3WqSJOCchifz5VwFde2sMi+F0KU9u9U3uuxkdodAtqPQuNeOrzku/LByCkp 18 | DZtRCFUUb9hCz7BAJUY4RIw2XIgedGCOVk2RGvLrfDVyAEJRd3qGLlT0MKHtCBqO 19 | FvFmnmEujGYelIyYlJSvKnvsZO5hQz4Z1RuF2hHffFYNpm1swTopM4UWIUOUETW6 20 | nxMd5LfN/gfY+h2SUba7QMnOoxt4EtAa7Z9g23zl10rgtpt09JRcM88qIOsreux2 21 | mcKZ1A== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-b-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEcTCCAlmgAwIBAgIUfbXa33X5p9SKvntuOfc3epm7u5wwDQYJKoZIhvcNAQEL 3 | BQAwIDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEIgUlNBMB4XDTM1MDEwMTAw 4 | MDAwMFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWIudGVzdDCC 5 | ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN8QrtzQL8KNwwlKNsNMNWsI 6 | 2X7jJwPV4J2I48vOFrkbar7KnUgd6GSqoPsiSd2FUiZyp7hO2bD6Q//s6lJ6VveT 7 | J1ev2Ph0ViajQOXJVR2QxzQwtwJI2E4XEFTLk/XuXORBTZdu0OI+FUhVuioXEUol 8 | PdMehFbs5y/ieV7ZF4RAbI5DVAwM6WnbjU8jNbTjNMlFxPvUApB6AJTl6WJUnUQA 9 | b7qdC8DD9P4MslwsjenvtZY1cSBrdRfVDq4pC18/KJmX5n3VONjC2weEKU7cFOyn 10 | B7REtRS/IDdI+PUEn30iJnh7tdSy7Gt/uPmPJTUX+MwPGSh6qghb0RMHXEwVUWcC 11 | AwEAAaOBqjCBpzAdBgNVHQ4EFgQUCptjojFusQH16vdJCCh1JpTYBk8wHwYDVR0j 12 | BBgwFoAUg5aHQef23C7B2c9YaMjdO4g7nCYwKwYDVR0RBCQwIoINc2VydmVyLWIu 13 | dGVzdIIRd3d3LnNlcnZlci1iLnRlc3QwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW 14 | MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA 15 | A4ICAQAVIZMygVFOZM7IFdKTazjt60dx1S8M6RaFOg8L8TVNgm7YBs3qst7NPcLw 16 | 5HCSbaIyc3X8nAvAKTqnRYbFyHDhQLPBbWffmoQXWJ/IcHp2g5GCl8ns2ybYU1+v 17 | vvF1FaeaicfP0vNdd2onmzoGiHXGZY5x3Y0E537Xbp/Ybo2qf4Jnd1FoTTe2C6Yj 18 | NPulCyvWY8g6QntwqJkmwS37PLO++lVroEs9Z/XEulVqqUGJV40rOYHp5KLXygpY 19 | UDhNKvg4nhLJm6nrS5f6kiPgTn0ASlP7TKiguYPEMI2OZlljQXbGzoV3Ub94yfds 20 | +GsB3ZhcFQWPEysf5M8yiiw1Z3nIWWjnhUI3Qzz2i1qME8v0A4tJZYjXlQL1B1Ru 21 | swbGtPiM84ji6/iU2na9LI98HT30wV5QqSx1r+yki/GK7iuhI7O2g/yetFe87ReX 22 | GjPcAT2Yl01vyX+g4KyDwW8s4NcZZEWBNd4ODbnkeKYxQKPIVScb1jQIH4ywszOZ 23 | vyU32bLDcD5WigR+A6znrPsN/I7Ra15BLXu4Qi7mUJfr9cVwd3PNGt7N4OOxOcIC 24 | 2a5p8mtL8ra/t3VonKrvlBOwTFYVLn7iWt5XlyeVHTnO11Z/zsjpKOEJGVo3MoYh 25 | lty1wooAEAsp/Qn2Omfx1sssCmSZ5rJI5ycMeU8b2qZBigKOeA== 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-c-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICBTCCAYugAwIBAgIUSBaDvG/S9TRAkJ84+t23aJrVmqgwCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTM1MDEwMTAwMDAw 4 | MFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDBZMBMG 5 | ByqGSM49AgEGCCqGSM49AwEHA0IABItKipDYXNhoXJ97T8Uzu1Xc03fbT5uy7YUs 6 | B0YxFllENUYp1D7IMOQxn1DXoELgpyr9AemWzfPid65/mmsKvOGjgaowgacwHQYD 7 | VR0OBBYEFFQfT1ulFW0FkDCmZvUduRgObCL1MB8GA1UdIwQYMBaAFLH2lYI1TiZt 8 | s0eoGxWBHO9pzqSnMCsGA1UdEQQkMCKCDXNlcnZlci1jLnRlc3SCEXd3dy5zZXJ2 9 | ZXItYy50ZXN0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYI 10 | KwYBBQUHAwIwCQYDVR0TBAIwADAKBggqhkjOPQQDAgNoADBlAjBzpeKL25npBK+O 11 | 6s8E7mmmWnYmCk+OmRJCFHEReIRaHRppZKfGhNkJ276CnVU6i3QCMQC/aCioJMKj 12 | Q1VDeJdMl34Bch9HyDKKNib2GcsUFfbf5tO15aN9/1+lsUqMGN/Qr1I= 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-c-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB1zCCAVygAwIBAgIUYRvCIBUhTc0bToUxx97+5R1FC7swCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTM1MDEwMTAwMDAw 4 | MFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDAqMAUG 5 | AytlcAMhAHcUqym1Qj54KehXrjxhet7L2UWH4ge3l1ovVGONiE9Zo4GqMIGnMB0G 6 | A1UdDgQWBBQd1oYhjnxMWOIIleNARvaoq0R34jAfBgNVHSMEGDAWgBSx9pWCNU4m 7 | bbNHqBsVgRzvac6kpzArBgNVHREEJDAigg1zZXJ2ZXItYy50ZXN0ghF3d3cuc2Vy 8 | dmVyLWMudGVzdDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG 9 | CCsGAQUFBwMCMAkGA1UdEwQCMAAwCgYIKoZIzj0EAwIDaQAwZgIxANPY3PVw1NZp 10 | dX9TBh6+if6v5r/x5fP8NJJ+wetj13Pkq2WnKj0Ml3L6Zgeby+G4JQIxAIiyiOKD 11 | KNLrP4znhmeCEM3uYQWbbv6gX2ml51FQcGa6STl/FCCKB//LOpCj5Zr/Tg== 12 | -----END CERTIFICATE----- 13 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-c-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB7zCCAXWgAwIBAgIUHUWy/f9y34zeaLcpLSpj7JAkSIEwCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTIxMDIyMDA4MjQy 4 | NloXDTIyMDIyMDA4MjQyNlowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDBDMAUG 5 | AytlcQM6AAmQAocN+EH6EcS3KMbbbV0lqnsnMPSXCnuiG7faJZj41KiEUG/+Y0k1 6 | oGHAn3uZmudeDdC3IhkwAKOBqjCBpzAdBgNVHQ4EFgQUovaCa5A2A+PBGnd75B1r 7 | TEG21h4wHwYDVR0jBBgwFoAUsfaVgjVOJm2zR6gbFYEc72nOpKcwKwYDVR0RBCQw 8 | IoINc2VydmVyLWMudGVzdIIRd3d3LnNlcnZlci1jLnRlc3QwDgYDVR0PAQH/BAQD 9 | AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMAoG 10 | CCqGSM49BAMCA2gAMGUCMGVDLgbAqmceC42yLE//n/lBqFfokNtLpvOR3YdxhQTq 11 | Islzmduy7GmRRgTUjRkleAIxAJhJ/3AMQSV37aKs9KywAI38154+j7UrFRO8B2cW 12 | h+kVLtRM3NeKxDB0oa40Uqo4Ig== 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/notyetvalid/server-c-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICzzCCAlagAwIBAgIUL2781XtPoOslww/8jfgU0fslxeUwCgYIKoZIzj0EAwIw 3 | IDEeMBwGA1UEAwwVSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTM1MDEwMTAwMDAw 4 | MFoXDTM2MDEwMTAwMDAwMFowGDEWMBQGA1UEAwwNc2VydmVyLWMudGVzdDCCASIw 5 | DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7LzsdjuxHQfbO4sGo2HC+vI9JT 6 | FSSOUXkVbS1aNHqVa04iMl8bh5PlH9FrimUCa5PmYh0Xo4E7IKs7SqbeRBMb7Mb9 7 | b1pBzlkyUZ4+SlwHxCobi80l0eATr2Kx2zlx8/in5GyqyE78wtJG3h7uHyu8jzCz 8 | 8m1mEkFC1KSZ0GG7bFE20oAshQKVBwTJMhRPDGqvYDvDcdjUKzIB1psDLrIP/w5A 9 | G2kkzCYaAqZerjuIjiaHrxF2fFeroxUqYvb4O91WzpY66E6/az3JTbupcqXn9hz8 10 | M4gUyfjLLcTej8+w0HFWbvDFZ7pmyilLkSvA4ol2WX+CHszPwm5uuitSLiECAwEA 11 | AaOBqjCBpzAdBgNVHQ4EFgQUjSQbcaGFgWB8CsgHkpnD9O00k8EwHwYDVR0jBBgw 12 | FoAUsfaVgjVOJm2zR6gbFYEc72nOpKcwKwYDVR0RBCQwIoINc2VydmVyLWMudGVz 13 | dIIRd3d3LnNlcnZlci1jLnRlc3QwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG 14 | CCsGAQUFBwMBBggrBgEFBQcDAjAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA2cAMGQC 15 | MBEtNDVfe9HvfTfJL49oByQxNNFGGPiNQOXcVwFDFjXCrvBujnxtL+lWAhNlaVAO 16 | LQIwRdUsfh7G3BxdEVJx+tTbQd6JoSPPG4iNOxcUcA0s7V4gvwYVPE4Kt6N/jBtO 17 | 5ov3 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /test/testdata/pki/cert/valid/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/cert/valid/.gitkeep -------------------------------------------------------------------------------- /test/testdata/pki/chain/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/chain/.gitkeep -------------------------------------------------------------------------------- /test/testdata/pki/misc/empty.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/misc/empty.pem -------------------------------------------------------------------------------- /test/testdata/pki/private/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/.gitkeep -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-intermediate-a-rsa-ocsp-responder-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA/mvm/Foh4zR0JMxz+9SjeOjQxdeLRebp7jZTwU1errDhk66I 3 | zzO8YYVcVe3c9UoyzhBJC0xV5RNE5VkR4Az/0/ISYeo9v/YIeSFkxyc5TqX/VvrM 4 | M43r5F0mNGW1la2VgnWDTexEXzFcoKyd7igEbw8AMJX7lCbamQYCoyAXHWZMxKkB 5 | nEE3LgEHWO/7zy5kfki9jAhzI5X14ZdClL3/hz2e6iUj85VuAEeeHLVwSGPyH+ZK 6 | jLBhG/H+2b+hdBnwILeGs7z+P2e3lIaV/L4TjIRr+wB4CFFJmqne5L0XtQR5AoMY 7 | SNHf/P80fIuBtiYE3r1+JSvVM54oH/nux2WBTQIDAQABAoIBAQDrKo+iWCmUmqp0 8 | TSsz7jOAEirPhFFutmcqUbsPJNXMwSBw4lYAuAB7X8qefrPLYt8dC36I2/FVQX9g 9 | Qvk70Kgzn0CQkvSq196zIEPHtaDJ6rPfEQjo6ljNh7BFpHG4vW9B3B8XSrlUCAtn 10 | VMbSGNkoUoRJZIjbQyKxaRXM9F+JQmsNQN6nFRsLTbq0VriUtK6D2q4LRh2cNW+5 11 | 49FaMeBi3BSvookGR9VxdG4G/RQJ8ZbR9OTQ8dSQ8VDjy3Wc6eqal8UPl4Qya9DN 12 | kVH2PeWnOiHvaJ3jCHpyjWLKN6lGA3ou0js4zFJZ0fQSvVGRK6X9IQleaxYFsC6r 13 | 1gRp/7/hAoGBAP9CtiiA4KH02TFihEJUbVs4a31PkAaJl5CKKEbzS4U57eSNA/uh 14 | PxozwC3aexEoHg8jSWvT2bNyiE4lMkjzuvKcK+u518kBZ8P3AWrOU4sCZyzc4hVj 15 | 6Z9lyNFCU3rtiyFm5squmtAYSqyPN18JG3ZgBv3ju51spJHno7O0NcsZAoGBAP8o 16 | kYknqua5hJSDieg68J/j9HGb7EkTgSUp6aaZRehZTYydMOAjPR7JVJsXiUejQYsW 17 | W+MqDRUCnLHjWpkNa8Au65R0MJwQ3rnEkXKAZ+e8BTIPqLxYZwzRCA/wdPc2m1tO 18 | /9jVO8TtY24Dra8EF51HT0C6YqNGj+JHrs+6xeJVAoGAKZj9hmw6LypvmpSraQPJ 19 | LmxrV+h3WBlkEbHyDl3nmLZwBibU11TXq7VzRAWuuIUJIP5nIKNNfujTPajiIPFX 20 | LeI1ZhzLBX6tIkpGeNlW0/h4R99XGJVHpSo5J6DfadD8M11Jjw4VPIQ45xYPt/UL 21 | /KZ5fTZ3hJgH2Z8eFlLv0UECgYAgfnAaQVz4SQPjTeUQGAFwuzz0AuFSZRN7Qh0p 22 | RDes4UKI97Ozt4kfFJCbt6GZ5+Z+6fgFs+M6m7yMwuFUwGrKbK8/lpRiK5vRmIDV 23 | ThjtX/phZ7EbWz60WSJntT2QBfo+5I6cdHtKFtkkt3803JaNRvmGyrWpCWFlda+D 24 | cMumiQKBgDwKWZvfHClqGSYhV8PixSxGf1SQsiY8KgYiSvAbHLo98ZZLqU+uvwXq 25 | 8v5tKlWBhPFYQRnKSgdppCF9nGmKutffPsM9PPIAU+pjMgYLN8f3Ckor8r50VWDZ 26 | jTZ8r11Czu8vGMp8JEQ1J9fl2wdTUAX3jVfJQKa0Fi9s8f97KcOa 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-intermediate-a-rsa-ocsp-responder.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD+a+b8WiHjNHQk 3 | zHP71KN46NDF14tF5unuNlPBTV6usOGTrojPM7xhhVxV7dz1SjLOEEkLTFXlE0Tl 4 | WRHgDP/T8hJh6j2/9gh5IWTHJzlOpf9W+swzjevkXSY0ZbWVrZWCdYNN7ERfMVyg 5 | rJ3uKARvDwAwlfuUJtqZBgKjIBcdZkzEqQGcQTcuAQdY7/vPLmR+SL2MCHMjlfXh 6 | l0KUvf+HPZ7qJSPzlW4AR54ctXBIY/If5kqMsGEb8f7Zv6F0GfAgt4azvP4/Z7eU 7 | hpX8vhOMhGv7AHgIUUmaqd7kvRe1BHkCgxhI0d/8/zR8i4G2JgTevX4lK9Uznigf 8 | +e7HZYFNAgMBAAECggEBAOsqj6JYKZSaqnRNKzPuM4ASKs+EUW62ZypRuw8k1czB 9 | IHDiVgC4AHtfyp5+s8ti3x0Lfojb8VVBf2BC+TvQqDOfQJCS9KrX3rMgQ8e1oMnq 10 | s98RCOjqWM2HsEWkcbi9b0HcHxdKuVQIC2dUxtIY2ShShElkiNtDIrFpFcz0X4lC 11 | aw1A3qcVGwtNurRWuJS0roPargtGHZw1b7nj0Vox4GLcFK+iiQZH1XF0bgb9FAnx 12 | ltH05NDx1JDxUOPLdZzp6pqXxQ+XhDJr0M2RUfY95ac6Ie9oneMIenKNYso3qUYD 13 | ei7SOzjMUlnR9BK9UZErpf0hCV5rFgWwLqvWBGn/v+ECgYEA/0K2KIDgofTZMWKE 14 | QlRtWzhrfU+QBomXkIooRvNLhTnt5I0D+6E/GjPALdp7ESgeDyNJa9PZs3KITiUy 15 | SPO68pwr67nXyQFnw/cBas5TiwJnLNziFWPpn2XI0UJTeu2LIWbmyq6a0BhKrI83 16 | XwkbdmAG/eO7nWykkeejs7Q1yxkCgYEA/yiRiSeq5rmElIOJ6Drwn+P0cZvsSROB 17 | JSnppplF6FlNjJ0w4CM9HslUmxeJR6NBixZb4yoNFQKcseNamQ1rwC7rlHQwnBDe 18 | ucSRcoBn57wFMg+ovFhnDNEID/B09zabW07/2NU7xO1jbgOtrwQXnUdPQLpio0aP 19 | 4keuz7rF4lUCgYApmP2GbDovKm+alKtpA8kubGtX6HdYGWQRsfIOXeeYtnAGJtTX 20 | VNertXNEBa64hQkg/mcgo01+6NM9qOIg8Vct4jVmHMsFfq0iSkZ42VbT+HhH31cY 21 | lUelKjknoN9p0PwzXUmPDhU8hDjnFg+39Qv8pnl9NneEmAfZnx4WUu/RQQKBgCB+ 22 | cBpBXPhJA+NN5RAYAXC7PPQC4VJlE3tCHSlEN6zhQoj3s7O3iR8UkJu3oZnn5n7p 23 | +AWz4zqbvIzC4VTAaspsrz+WlGIrm9GYgNVOGO1f+mFnsRtbPrRZIme1PZAF+j7k 24 | jpx0e0oW2SS3fzTclo1G+YbKtakJYWV1r4Nwy6aJAoGAPApZm98cKWoZJiFXw+LF 25 | LEZ/VJCyJjwqBiJK8Bscuj3xlkupT66/Bery/m0qVYGE8VhBGcpKB2mkIX2caYq6 26 | 198+wz088gBT6mMyBgs3x/cKSivyvnRVYNmNNnyvXULO7y8YynwkRDUn1+XbB1NQ 27 | BfeNV8lAprQWL2zx/3spw5o= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-intermediate-a-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-intermediate-b-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-intermediate-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PARAMETERS----- 2 | BgUrgQQAIg== 3 | -----END EC PARAMETERS----- 4 | -----BEGIN EC PRIVATE KEY----- 5 | MIGkAgEBBDCuGNf3b6JB3sUSvyRs8Jn/vjEibG5I2wXiqw5w3y+RAdjlWe/TqFf3 6 | nJLcg4INEkqgBwYFK4EEACKhZANiAAQx+vBTdSkIXfI4aME5+ahpdO+3ppurWo3M 7 | ozh8GDlLmxDxwltADzIZcN0H+eft9tQ69ufDdJyyLXRv9SvO15fUGQJRUKuJyipm 8 | j8iSsa3NaNlkav/9LpnT0fCqxygd0RE= 9 | -----END EC PRIVATE KEY----- 10 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-root-g1-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-root-g2-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PARAMETERS----- 2 | BgUrgQQAIg== 3 | -----END EC PARAMETERS----- 4 | -----BEGIN EC PRIVATE KEY----- 5 | MIGkAgEBBDCrrVcOQvnMYO69xVcW3HxfWCYZ3TGmr32unxyqOowfCVihRtGgl5Gy 6 | N8dTgmGcouOgBwYFK4EEACKhZANiAATIRMf9QnnJbzHovd/eWb7WMj/882ZfqrAA 7 | cRQ7WcgY4Ud6NNcib/sqAudzWAn3Rlf5phkv87WRgnHgUK13i6Tt2Z308rTElBfo 8 | jGoGZrY7HtlZPfpnGtQgN1kOnB0JGDM= 9 | -----END EC PRIVATE KEY----- 10 | -------------------------------------------------------------------------------- /test/testdata/pki/private/ca-root-g2-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /test/testdata/pki/private/misc-explanatory-text.pem: -------------------------------------------------------------------------------- 1 | Pre Explanatory Text 2 | -----BEGIN PRIVATE KEY----- 3 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDToBBMpZCUPd0y 4 | IYLS32sHoV62hRnbCjDjWaZZAWAKow+fltlMNiSr3SlTonbwfssZXLyR4C8p86oH 5 | pfNS0RlHY6UK2gAR4i7Z8VJKkGfCWW6E/U8zNG+W/hDolze5iyOLM0Ak7QMFw/9z 6 | 0oBqmmVZpUq/Pn0Tba2iJs//Ah7E6CJbcwtXvfMWyX8IpRUGROSjBIoXr55OU8h3 7 | 2QGWv9ZtvxK/8T9UEhd3bqbUkzj5qdQoUgIYudECyi8hGvfHfx3StWB42NUkQ41T 8 | Ez3qsLcfHu48dxNR85Wz5Lh6Nq/760iOILKwGYKZ8lHrUfnJCBJT3GvhpFPRG2rX 9 | Md2XbDY/AgMBAAECggEAOQQiABSHXHlCdDQ1JA1Pr9GZTAGWUr5vJ4HK4KYPMy51 10 | kiC5UOAxhyBh9weJlggDPkUPBRpqepoMkFz0rrZpYiOFnuPXKvpOdyeebTp0yhcA 11 | QNJimUAiZIL1GUVMnS/QlrtrJ8e3jcEdvR3UvWP1tG5lMhtq5WYiZtKgLWtr0M7g 12 | Xe61C1zLXJiBVcY5AABr/F1l0668l9+JbCgTTuNgrqXfQwZJYb4kyqnaefmlqcIi 13 | 6MBIwSYI+ZlZdBTJxSwCcg+OWziqlVfxRrCWd5l/cZe554Sw67jt6nsqiEsNMMV1 14 | Erm+tVAIjT6tJOFlKodktZBZOwsAqq43LaRWCnJ+aQKBgQD55fUjaGJAN7+A35/J 15 | InyQ3zlHiBneQqgyS4bpBc+kRqqsiYb4dhNYhFTaHQMtsy5fnJyDusNJ2eSJkPQT 16 | 3t5wCJaGt2XZQ/9H1wKOU+DwmWGzkyoX1cwNPA9gw3RaX3hWm5lD9WX+6XMZJROU 17 | IXiQjTRCXDgIT2NXvkmJiqMVQwKBgQDYyt9WFD6l0SMMFtiSZImfErffa0IPk1Sx 18 | XL0LbllyXbsiIQ0H9S9hb+T+fi0CkgIBkwNuIw8DnsPhA+PShoxqXtiZbdYC78l1 19 | zIiooIpmR7KYM7z9zHpw1GBIE+64yI78yiOLzEbznSNePrQ2ElHE1Qne3NwvH40p 20 | PRLmiAtNVQKBgFxfPULuVcsJEFex0Z2Giub+LG0diPpYR1X4BxFhnYRKvtHyMBrt 21 | gm8o0zigmsksv4qGGHC0+3Tz/v8+vooNysk8029OoW4zLUy/1GkJ5k7pU20Oi/Ot 22 | irSlq8WH2h2Bxri04W12a1JTtsDnrJoH2UoNd/DDp86ikcUgSIx325qDAoGAAo6a 23 | BcTlXEVUOX9HfKqM6QBqhMsaE170f8cNP8ZEbdHnNCbZpX9h2K9eLxZD56TbOzOF 24 | tdXaBnvn6Y6HMGN/4n1N5rlh7dTwNmB8OCj0mPI9jAgIMaIoy43luNPrW+iZryef 25 | NbXqHFN9KE5rB7w9lKnCnQtT2YZwvszGnUt7fqUCgYAZ3mtp0D5Snxt01e6b57/9 26 | D+5l3dcfVwy+e6N+ttLdM2x2QKBnMtYgOBAzCcH0/tV4D0dtPSLjKBr6BU+D98Ja 27 | 027yho/cn3KIOD5TpOK3+VMiJNs6PFWg/GxX+olCSwjtsVnxLSZ1YMP/XpPnZI0v 28 | qPCW6tvCxCE6XCavP0YGLw== 29 | -----END PRIVATE KEY----- 30 | Post Explanatory Text 31 | -------------------------------------------------------------------------------- /test/testdata/pki/private/misc-no-eol.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDToBBMpZCUPd0y 3 | IYLS32sHoV62hRnbCjDjWaZZAWAKow+fltlMNiSr3SlTonbwfssZXLyR4C8p86oH 4 | pfNS0RlHY6UK2gAR4i7Z8VJKkGfCWW6E/U8zNG+W/hDolze5iyOLM0Ak7QMFw/9z 5 | 0oBqmmVZpUq/Pn0Tba2iJs//Ah7E6CJbcwtXvfMWyX8IpRUGROSjBIoXr55OU8h3 6 | 2QGWv9ZtvxK/8T9UEhd3bqbUkzj5qdQoUgIYudECyi8hGvfHfx3StWB42NUkQ41T 7 | Ez3qsLcfHu48dxNR85Wz5Lh6Nq/760iOILKwGYKZ8lHrUfnJCBJT3GvhpFPRG2rX 8 | Md2XbDY/AgMBAAECggEAOQQiABSHXHlCdDQ1JA1Pr9GZTAGWUr5vJ4HK4KYPMy51 9 | kiC5UOAxhyBh9weJlggDPkUPBRpqepoMkFz0rrZpYiOFnuPXKvpOdyeebTp0yhcA 10 | QNJimUAiZIL1GUVMnS/QlrtrJ8e3jcEdvR3UvWP1tG5lMhtq5WYiZtKgLWtr0M7g 11 | Xe61C1zLXJiBVcY5AABr/F1l0668l9+JbCgTTuNgrqXfQwZJYb4kyqnaefmlqcIi 12 | 6MBIwSYI+ZlZdBTJxSwCcg+OWziqlVfxRrCWd5l/cZe554Sw67jt6nsqiEsNMMV1 13 | Erm+tVAIjT6tJOFlKodktZBZOwsAqq43LaRWCnJ+aQKBgQD55fUjaGJAN7+A35/J 14 | InyQ3zlHiBneQqgyS4bpBc+kRqqsiYb4dhNYhFTaHQMtsy5fnJyDusNJ2eSJkPQT 15 | 3t5wCJaGt2XZQ/9H1wKOU+DwmWGzkyoX1cwNPA9gw3RaX3hWm5lD9WX+6XMZJROU 16 | IXiQjTRCXDgIT2NXvkmJiqMVQwKBgQDYyt9WFD6l0SMMFtiSZImfErffa0IPk1Sx 17 | XL0LbllyXbsiIQ0H9S9hb+T+fi0CkgIBkwNuIw8DnsPhA+PShoxqXtiZbdYC78l1 18 | zIiooIpmR7KYM7z9zHpw1GBIE+64yI78yiOLzEbznSNePrQ2ElHE1Qne3NwvH40p 19 | PRLmiAtNVQKBgFxfPULuVcsJEFex0Z2Giub+LG0diPpYR1X4BxFhnYRKvtHyMBrt 20 | gm8o0zigmsksv4qGGHC0+3Tz/v8+vooNysk8029OoW4zLUy/1GkJ5k7pU20Oi/Ot 21 | irSlq8WH2h2Bxri04W12a1JTtsDnrJoH2UoNd/DDp86ikcUgSIx325qDAoGAAo6a 22 | BcTlXEVUOX9HfKqM6QBqhMsaE170f8cNP8ZEbdHnNCbZpX9h2K9eLxZD56TbOzOF 23 | tdXaBnvn6Y6HMGN/4n1N5rlh7dTwNmB8OCj0mPI9jAgIMaIoy43luNPrW+iZryef 24 | NbXqHFN9KE5rB7w9lKnCnQtT2YZwvszGnUt7fqUCgYAZ3mtp0D5Snxt01e6b57/9 25 | D+5l3dcfVwy+e6N+ttLdM2x2QKBnMtYgOBAzCcH0/tV4D0dtPSLjKBr6BU+D98Ja 26 | 027yho/cn3KIOD5TpOK3+VMiJNs6PFWg/GxX+olCSwjtsVnxLSZ1YMP/XpPnZI0v 27 | qPCW6tvCxCE6XCavP0YGLw== 28 | -----END PRIVATE KEY----- -------------------------------------------------------------------------------- /test/testdata/pki/private/password.txt: -------------------------------------------------------------------------------- 1 | PASSWORDSTRINGS -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ecdsa-encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgYxR5qhm6imwICCAAw 3 | DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEHPn6KVeb9BSgcipIal7zl0EgZDD 4 | NLhxRLpkkztkLt7MnPV8F1lTGfNduoAIPcNkv5MjSEedNscms+Qx5TMLkzGi/9hK 5 | 7YHxo1Wta7w5o/VXOubGkECWr5H1ECFwabZmsbCFmwTDhpe/RCf4MwCSiLVVLgHx 6 | 1VmjalOh/tcWdKxexGrV3I+s1TkJImjG72B4UIbvD3BAMOpgJSrLfzbp+Yyb4yQ= 7 | -----END ENCRYPTED PRIVATE KEY----- 8 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ecdsa-traditional-encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-128-CBC,B0F409836CC7482ED0077FDC16ADF5B1 4 | 5 | 2eHOmtTBVdig1N7JimNZS+YDq4oq4jKCyvBcDtAEpsOg1r0eJbRrfIBJA5GvPtuU 6 | c2y2AiX9nKXSiV00/kOpicZyYq5Dy+f/A0KBi5ogLvJuj4oG7hhQZQdGnTzGcpKa 7 | RJIsZcx9GsEOVcJkgL9Wp81LRbiHYQp2K5+H2T+7LXg= 8 | -----END EC PRIVATE KEY----- 9 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ecdsa-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIGxOe5ZjOEMifS4Fz4cyo2x6KThx/n9gkdYxQtqRU1DDoAoGCCqGSM49 3 | AwEHoUQDQgAENu4jh5i6V42g3HJAGK5nLZLDLEOs/VAyNLYm9AL7bK7/8ec6vTB/ 4 | pLItKsclp1phZTT4zJIEctRfJocU4khk1g== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ecdsa.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-a-ecdsa.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgbE57lmM4QyJ9LgXP 3 | hzKjbHopOHH+f2CR1jFC2pFTUMOhRANCAAQ27iOHmLpXjaDcckAYrmctksMsQ6z9 4 | UDI0tib0Avtsrv/x5zq9MH+ksi0qxyWnWmFlNPjMkgRy1F8mhxTiSGTW 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ed25519-encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgfIe7uopErYwICCAAw 3 | DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEMX0ic4qChoAp0HqD5dTFlMEQCVB 4 | 5uXhCWrHkRmB2uUnBdP8hPL8uRfb0hAD10dnngkiBhVLbGbxPFciOyVZ6cHS1VEL 5 | ejapPbWTQuoPCQv3b8c= 6 | -----END ENCRYPTED PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ed25519.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-a-ed25519.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEIKw2F4YP5VB+aya6IxA29pCkA/NPAUHDcdPAzD7YPRU9 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ed488-encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIGrMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjA2l64663wkQICCAAw 3 | DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEECcL+TnItmu9lSB2VPe/LkcEUEdc 4 | yNJpaSzF+iFJRHT2lHfm1WsbMWi3CxSIPBkIJ+jT606iiFM0mq8KuWeGO7MtYmlm 5 | kDFwxFwpanQfLGKLDdt9uUD8xImaXS4OUAJ0IHc7 6 | -----END ENCRYPTED PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ed488.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-a-ed488.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MEcCAQAwBQYDK2VxBDsEOR1kiLg4DjIahbvCxicoZLAIf6ohhyz7B7CuUPvMSMqQ 3 | VAYlHDzzqz909avVlR7oMeEsu2iT/LdjCg== 4 | -----END PRIVATE KEY----- 5 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-rsa-encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQITR3tn5gv8aUCAggA 3 | MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBCphqi+bjlClqYPBsOIwqxOBIIE 4 | 0MCMM6yPeKIQNAWXaGgKS97mYBvDRslr/+ELqWcTK2Rdk9LzZrGSH5Vx3BL15e2i 5 | xTEovG8SVOfRVWA3OJid6GZXgyGjyNAuEfUhbLsYxyMuB/tlmtoWB+FZ8dpBTgO/ 6 | ZPynjxGoGUDi5aVKgexdBgi5XhTY+gmlvUSKhzvJkwqfOpoFjdYacCVuEtDcrIjY 7 | 05W+6w4JBmiYwA70aDV+GwMUkPg0/+OxNLfrmjlXkX6ssIakE3IGPMg/T8vuFtlU 8 | sbeEL5En8ztLMYjA5d1/h/S6CmzjE91kAIyFDyx8VJnjgX92yL16JB17L+u8rLB0 9 | 2oZMPaQvMy21vCbceS/GTWYe62Inl1OLakROSo/Aj5I5Jt6c0+E4HgbiCJJJckr8 10 | uQFHrgaloq4NgLEPoxa2ldPqRLUmYOXeZru4iflVVOkh8nc13Z5FqR1jt2py/Ol8 11 | BgYKm0MRyQZlioN3m7LYNJu+f2SaPC1imAyU5mC1ZTlkeTT67Q+Si+nXige+q6Xa 12 | M+e+XTq0waDJSOfViovH6MVMNRKQEH7iwkorsuO4IsRnNtO9Hsq3savz9Wia2qfO 13 | DJEl+eW5qy1svCAyqtfNTt2fi+wC1J8HFHtK3aGH2esOmHg/xpdhzfvZcUuyEfxI 14 | HHu8S6S0sUz9lEvtP93XIIWm0OhojNjS0IxruWpn0602PBogf83NxDAqJw3wD50S 15 | vNCAkpNVJr3Qyd4ZwoWNjMuMNZjXZxBgWgjE88mkcT53F42ddgcUbyyHukPSpsA5 16 | XYZ1DWRn9HIzkfJmo6pGJe1JAjhbawv5uEsQveZRqPDm2CDTI+Yos/Z8qbJUuSbt 17 | fZ8Wxa0WfPcpJRM/dLWGgvtqpmEODRKUzb482zVznWv7M1GYqo6Irt37mWoAaDT4 18 | FzOhahDeo0fNoLlFWyjAYQoQw1xNZGCGqf8776S18opLG8jUVfZ3FpaPP3PsNmuJ 19 | xo/XWvfU68TxOz+WyUMNmx5UprxiZNu2t2RfuzOrOptEN3zv3mJU+dfFv8ndB0A4 20 | HuEFDSjNx3brBPqFiDIeuoFtMv09jEz/NwOWULb6ap6JyGffOznFuX+NAaTF+lWY 21 | vSEfdyfeBWCw5QIac++nTIIIjQ5/8O7kH/Uvjjc0v3S9IjJMFsxbhEWn6blj9Pnf 22 | JWlkR5Gw3Zz6hlDXgnF2k+Ls3podfBARiONH63geO0LUMgwO9gqbpa2EloHIEVdg 23 | 8tEcHnSusQHK5UJb5TdHC38w6C75NsF9UnhBo2AjRkhgn1RPU2/qsd6B1Ytk22pC 24 | uY62bDxqykH0S+PwU6FaREPiJcnFKn3C4RroV12FFhWPI8Xdyi2GeTQvDId6OXa1 25 | oB2Fb/1DA1O2jpKsCc7Z6ExAdoILF6EzrvOBV7UyEciBgDniVSf7ylyNaOqPRbNQ 26 | xw3u1LsXasutrKaXqeX0FHRVZhKwnvVXMre/g/SIf3FFGmddzUfAOEv+U0xDap+Y 27 | kwiwMTOWJrNRH1Q2cdnLha9dykvYlCGM+z4f9JhM2v4LPj7X28BB9Wbf3dB7DgG1 28 | pFyumqIuT0c2otB5nCT3WrFiABRAHpRyGhLEI6ZQL8ArVTET+yyG95JknBCHJEYr 29 | I+fxcFizxINRGE5wRU1Q3zjx9Sq0n/o6Ch9l0z4HIx7U 30 | -----END ENCRYPTED PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-rsa-traditional-encrypted.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-128-CBC,F3E442345F7B194C0BA04FC5953B23F2 4 | 5 | 3jTRJq4qgT3FYDuy6Y2LvILCKvYkC97xzRzaAW6jXq6b4fA2s4Rf8Wk16YDk6F+q 6 | 35XzHs2y5KDBsB5LuYmVMqEblfW9E3A3qb9rIHCjtiSJPyUWH2mp/mvtqqu/GYaf 7 | 6DwvyH9xHjbpAanj4+puwv3/kVNL/F8Gq74CN8O+3eQmcDaAFQ0tn+HdF7XdIDuF 8 | e6fOKxHs8Rt8uTKk34+atcZ3KEmSBne5Gg8xYaI78t9fvNKhcfq9bqEuRxV2X1El 9 | M4pniW0klE5+2vU0pyrmyWcEOehL8cqYaDtChl0zw+Uc3xTsdlgvIOXQQA2hIbzt 10 | AgS2aL5lGRoSmAJFJitetQaVb/OQZLz4fqK5rpNnxHcA+ciRQVpC6ru/8Zs5CFZ+ 11 | Ki2Z6tjp1irEDx42MxNuViT5zUmepSlc6DjPLa3F7L3Y1d9Hj2frsmXl8wHI3u4m 12 | nadnQ2ZmVe19DMGHqDT0OYM19lH4RpCmtvcdupjlEnlVFOwotgP5xiDpRC4ITuCa 13 | 5Ykd1ufhJDpYyad7j9yCAXdmZbraOng4SnUoRezWE4pOZ8/l3c/zH7Og8Y/0oGZM 14 | L//3rNjWr6ughnye+tp+/cq+A/8A6Qw8DTCMJpX7wVndtAaPduWONcR+jGynbzZ5 15 | R2qy8Rbq+Af/p86dvH4h+r/UF3M+ddOFOY3vmNWmtPJuNiK/VSmHJVlAS92OSx5a 16 | gTh5OAl3z3etDcyujdsMbb1DnAHSQcJO16jS374UHzKAf7USDnbs+6XVllZkF5Fc 17 | Qq4OylcH3+OlD1QWmNGwpdbG4AR8lM6eHp2ifS9bzfwsNPJqhItDw+ZIhMoG2LVI 18 | 2fw3QeuvMozErY/p+3TKuVtdsMGdkafBuQwwi61btx8zuKZ00OaVSVBifOXiy0Oj 19 | 6cXx7AvCs+GKbpnySZJcATLH4YtntX1eacLtLv3qBv2lI2PsdSODTA+aJ/H6kA/c 20 | 8V/T5u5gh9uuciIqPAg6GVWb+gKfBKUy0cd4o1EPO8eq+qr3oaAubDhKJBVAaMgL 21 | zRn87o7K5TgcrixD5i+yffZEmECUR7T5XnHlIj3RmQG/2w/E4ddaGzx+Auw1X64z 22 | 3rUoHfFoB5NR6Z04vMTwR7BEB+y9sSnaMc7F6nNzftpH0/KfTqGZp9YnlesJVqjs 23 | tTSMkfzsz7QCK4BFpS5k3yeCm4YQLB7opg6+r7IaSpnvViKojJmnh4OAKcRImk+E 24 | 8OWKySO0jxWw8eovWNQi3LJTtA4e050Fi1u4nYNtxlf3G/MHtzpqvN/z6pPLtZuP 25 | txM/RHPFvUmXji5zjID/pLuVPFMUNAruPZtyc1yt1OGvnecvV32GpgD1QYIX0UyB 26 | OPUcX4hURKvsuZCw8gWs9l9+RdEkbfN1wET7JJdTFAOuozrT4C9d3c2tHudsErqu 27 | ycxm/Bcx72i0+j+5X8VlRmTiIONvkW25cBWy4GIEndNjNIaD3/1ZCdrzvVJt60su 28 | yxy4SSU8AcieSXMKUxdzt0cwrpo8zHrUmS2uCViHRrSXoVkNz+3ETE4n8RSvG+GD 29 | UO2WxBCMCbpIc1rsejlhd4+uBPCGHpGwwEUJJlKwcsGQpf8hyDK0LWghwqpDhw3e 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-rsa-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA06AQTKWQlD3dMiGC0t9rB6FetoUZ2wow41mmWQFgCqMPn5bZ 3 | TDYkq90pU6J28H7LGVy8keAvKfOqB6XzUtEZR2OlCtoAEeIu2fFSSpBnwlluhP1P 4 | MzRvlv4Q6Jc3uYsjizNAJO0DBcP/c9KAapplWaVKvz59E22toibP/wIexOgiW3ML 5 | V73zFsl/CKUVBkTkowSKF6+eTlPId9kBlr/Wbb8Sv/E/VBIXd26m1JM4+anUKFIC 6 | GLnRAsovIRr3x38d0rVgeNjVJEONUxM96rC3Hx7uPHcTUfOVs+S4ejav++tIjiCy 7 | sBmCmfJR61H5yQgSU9xr4aRT0Rtq1zHdl2w2PwIDAQABAoIBADkEIgAUh1x5QnQ0 8 | NSQNT6/RmUwBllK+byeByuCmDzMudZIguVDgMYcgYfcHiZYIAz5FDwUaanqaDJBc 9 | 9K62aWIjhZ7j1yr6Tncnnm06dMoXAEDSYplAImSC9RlFTJ0v0Ja7ayfHt43BHb0d 10 | 1L1j9bRuZTIbauVmImbSoC1ra9DO4F3utQtcy1yYgVXGOQAAa/xdZdOuvJffiWwo 11 | E07jYK6l30MGSWG+JMqp2nn5panCIujASMEmCPmZWXQUycUsAnIPjls4qpVX8Uaw 12 | lneZf3GXueeEsOu47ep7KohLDTDFdRK5vrVQCI0+rSThZSqHZLWQWTsLAKquNy2k 13 | VgpyfmkCgYEA+eX1I2hiQDe/gN+fySJ8kN85R4gZ3kKoMkuG6QXPpEaqrImG+HYT 14 | WIRU2h0DLbMuX5ycg7rDSdnkiZD0E97ecAiWhrdl2UP/R9cCjlPg8Jlhs5MqF9XM 15 | DTwPYMN0Wl94VpuZQ/Vl/ulzGSUTlCF4kI00Qlw4CE9jV75JiYqjFUMCgYEA2Mrf 16 | VhQ+pdEjDBbYkmSJnxK332tCD5NUsVy9C25Zcl27IiENB/UvYW/k/n4tApICAZMD 17 | biMPA57D4QPj0oaMal7YmW3WAu/JdcyIqKCKZkeymDO8/cx6cNRgSBPuuMiO/Moj 18 | i8xG850jXj60NhJRxNUJ3tzcLx+NKT0S5ogLTVUCgYBcXz1C7lXLCRBXsdGdhorm 19 | /ixtHYj6WEdV+AcRYZ2ESr7R8jAa7YJvKNM4oJrJLL+KhhhwtPt08/7/Pr6KDcrJ 20 | PNNvTqFuMy1Mv9RpCeZO6VNtDovzrYq0pavFh9odgca4tOFtdmtSU7bA56yaB9lK 21 | DXfww6fOopHFIEiMd9uagwKBgAKOmgXE5VxFVDl/R3yqjOkAaoTLGhNe9H/HDT/G 22 | RG3R5zQm2aV/YdivXi8WQ+ek2zszhbXV2gZ75+mOhzBjf+J9Tea5Ye3U8DZgfDgo 23 | 9JjyPYwICDGiKMuN5bjT61voma8nnzW16hxTfShOawe8PZSpwp0LU9mGcL7Mxp1L 24 | e36lAoGAGd5radA+Up8bdNXum+e//Q/uZd3XH1cMvnujfrbS3TNsdkCgZzLWIDgQ 25 | MwnB9P7VeA9HbT0i4yga+gVPg/fCWtNu8oaP3J9yiDg+U6Tit/lTIiTbOjxVoPxs 26 | V/qJQksI7bFZ8S0mdWDD/16T52SNL6jwlurbwsQhOlwmrz9GBi8= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-rsa.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-a-rsa.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-a-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDToBBMpZCUPd0y 3 | IYLS32sHoV62hRnbCjDjWaZZAWAKow+fltlMNiSr3SlTonbwfssZXLyR4C8p86oH 4 | pfNS0RlHY6UK2gAR4i7Z8VJKkGfCWW6E/U8zNG+W/hDolze5iyOLM0Ak7QMFw/9z 5 | 0oBqmmVZpUq/Pn0Tba2iJs//Ah7E6CJbcwtXvfMWyX8IpRUGROSjBIoXr55OU8h3 6 | 2QGWv9ZtvxK/8T9UEhd3bqbUkzj5qdQoUgIYudECyi8hGvfHfx3StWB42NUkQ41T 7 | Ez3qsLcfHu48dxNR85Wz5Lh6Nq/760iOILKwGYKZ8lHrUfnJCBJT3GvhpFPRG2rX 8 | Md2XbDY/AgMBAAECggEAOQQiABSHXHlCdDQ1JA1Pr9GZTAGWUr5vJ4HK4KYPMy51 9 | kiC5UOAxhyBh9weJlggDPkUPBRpqepoMkFz0rrZpYiOFnuPXKvpOdyeebTp0yhcA 10 | QNJimUAiZIL1GUVMnS/QlrtrJ8e3jcEdvR3UvWP1tG5lMhtq5WYiZtKgLWtr0M7g 11 | Xe61C1zLXJiBVcY5AABr/F1l0668l9+JbCgTTuNgrqXfQwZJYb4kyqnaefmlqcIi 12 | 6MBIwSYI+ZlZdBTJxSwCcg+OWziqlVfxRrCWd5l/cZe554Sw67jt6nsqiEsNMMV1 13 | Erm+tVAIjT6tJOFlKodktZBZOwsAqq43LaRWCnJ+aQKBgQD55fUjaGJAN7+A35/J 14 | InyQ3zlHiBneQqgyS4bpBc+kRqqsiYb4dhNYhFTaHQMtsy5fnJyDusNJ2eSJkPQT 15 | 3t5wCJaGt2XZQ/9H1wKOU+DwmWGzkyoX1cwNPA9gw3RaX3hWm5lD9WX+6XMZJROU 16 | IXiQjTRCXDgIT2NXvkmJiqMVQwKBgQDYyt9WFD6l0SMMFtiSZImfErffa0IPk1Sx 17 | XL0LbllyXbsiIQ0H9S9hb+T+fi0CkgIBkwNuIw8DnsPhA+PShoxqXtiZbdYC78l1 18 | zIiooIpmR7KYM7z9zHpw1GBIE+64yI78yiOLzEbznSNePrQ2ElHE1Qne3NwvH40p 19 | PRLmiAtNVQKBgFxfPULuVcsJEFex0Z2Giub+LG0diPpYR1X4BxFhnYRKvtHyMBrt 20 | gm8o0zigmsksv4qGGHC0+3Tz/v8+vooNysk8029OoW4zLUy/1GkJ5k7pU20Oi/Ot 21 | irSlq8WH2h2Bxri04W12a1JTtsDnrJoH2UoNd/DDp86ikcUgSIx325qDAoGAAo6a 22 | BcTlXEVUOX9HfKqM6QBqhMsaE170f8cNP8ZEbdHnNCbZpX9h2K9eLxZD56TbOzOF 23 | tdXaBnvn6Y6HMGN/4n1N5rlh7dTwNmB8OCj0mPI9jAgIMaIoy43luNPrW+iZryef 24 | NbXqHFN9KE5rB7w9lKnCnQtT2YZwvszGnUt7fqUCgYAZ3mtp0D5Snxt01e6b57/9 25 | D+5l3dcfVwy+e6N+ttLdM2x2QKBnMtYgOBAzCcH0/tV4D0dtPSLjKBr6BU+D98Ja 26 | 027yho/cn3KIOD5TpOK3+VMiJNs6PFWg/GxX+olCSwjtsVnxLSZ1YMP/XpPnZI0v 27 | qPCW6tvCxCE6XCavP0YGLw== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ecdsa-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIDWpDPpfEWKoT3zF1zU3radgw0lR2XLijTTJuRMj6yxYoAoGCCqGSM49 3 | AwEHoUQDQgAEh3Ehm7HwVcIQbaIj1qZZ+t73kT+FTOm65XlTLTDhwjFU0CWtenWZ 4 | T5Tj9kfrjEomB5ajG9k8VxIr1iR5OBqagA== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ecdsa.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-b-ecdsa.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgNakM+l8RYqhPfMXX 3 | NTetp2DDSVHZcuKNNMm5EyPrLFihRANCAASHcSGbsfBVwhBtoiPWpln63veRP4VM 4 | 6brleVMtMOHCMVTQJa16dZlPlOP2R+uMSiYHlqMb2TxXEivWJHk4GpqA 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ed25519.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-b-ed25519.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEINZSxyZH1KrNy81uiyPLm3jNoPDaMsQrWlV2vOj7fiPD 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ed488.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-b-ed488.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MEcCAQAwBQYDK2VxBDsEOV7ajC/jqHrsGHJJwGZpbjVH0FYiWl2/hV+QZFPDw2+s 3 | Q0uAT2rEUA7HcIcsYc6lfCVJ/JfQGgzStg== 4 | -----END PRIVATE KEY----- 5 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-rsa-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA3xCu3NAvwo3DCUo2w0w1awjZfuMnA9XgnYjjy84WuRtqvsqd 3 | SB3oZKqg+yJJ3YVSJnKnuE7ZsPpD/+zqUnpW95MnV6/Y+HRWJqNA5clVHZDHNDC3 4 | AkjYThcQVMuT9e5c5EFNl27Q4j4VSFW6KhcRSiU90x6EVuznL+J5XtkXhEBsjkNU 5 | DAzpaduNTyM1tOM0yUXE+9QCkHoAlOXpYlSdRABvup0LwMP0/gyyXCyN6e+1ljVx 6 | IGt1F9UOrikLXz8omZfmfdU42MLbB4QpTtwU7KcHtES1FL8gN0j49QSffSImeHu1 7 | 1LLsa3+4+Y8lNRf4zA8ZKHqqCFvREwdcTBVRZwIDAQABAoIBABzru9AzSc3utVfS 8 | AHGnwtFCz3gtGVTc+QdTxT0aVkXfsSJVgLjl78iFeuO0mWEYNQN5IBe8WWsht4lJ 9 | /UN+SyJEOPicewQTiUvvJK3mQZvYtoskucWZDjppsRtdXayoH/EUKmw02O5MYFQF 10 | kWJ9pSc41uA1d7ERfBPwSA4tFWh29+FPWT3hdJJsKeptyrt9LWJ1fzxG7NW/tZv9 11 | 3AvHgSyQpveZl6Pd4esVvTJtp6hr+3ngn0yuGmovhAK25wUo17x7tvscviWB+QRJ 12 | bE17UZBke74oxQ21VqgNZ/EBXzahRuK895+2DdkDafo3A4rAa13GKtIpWSwtHzxF 13 | RnzUlyECgYEA9B7aGkJRr/+ZG0GL1iMKPq5PbFuZDiUtHevYfmBMEN0eql+TeP8s 14 | xztNxkCQeRtk0XOjr2hnyfw9N7oNfscHhJiHzpnQpdtpmLwcbBWhQdlyLfQD5zCX 15 | aRTiR+YrplPWXSqXR+ks29eZdlDBkxE4H4fU65HnVCVtVrDIPcWGqJcCgYEA6euI 16 | XJwBeEQvdFroxmtQ75vLXMKhx3pB99l8DEPv/sv/Zq9ZfxGQvN78fvpprI+GZ7Wf 17 | Xo65+MURGZ7Y4iB932/7SnN/P61qLN2TC72f9rm5WcbdrQHCacDQUlKBmD0TVy2J 18 | +S6/5Ot5d6qM+6/C3JrcMKa/0yyWGXMDO0PKZ7ECgYBJQhTremlvKoH0xvfC3CMP 19 | 6llVSCunLgrbBtKiIh3RlbnFIQdtcQ4r/6T4UJnKbikUHeLKGcfDuplYZtHz8KBV 20 | 7zwaCNivXSfUOOdCnD8XNrzoA2lEcLWPSEAbmXwR3ujebpCVeOkIVCvucI+Wpb00 21 | 4RtJUjCcdNraABUnTGZ7owKBgB6K11IoOHToij2qBQyrRHUUpXfmHdN63hQrfGvp 22 | jvN41U8mBAx4UaqnftZhgdy7HLR73WQuRI/7wyDSQcU8stKyv1/YNrwsu1lCUQnO 23 | Z42CcHYNZjJJsYW3XDvzc+JZzyWp14MGnJ2aNVDvntrZ9xpwyeE8VH2RK8QE5V4e 24 | mtXxAoGBAKTZ5IOefQCMi6wlnnjFdW+CljVPUxTYyn7gyytLT4QumQbgpdJWx1Z1 25 | U7qMWePWthtHefTuMHE4M6iBdxe9yjjWTYHTIGDX7Df6ayC6V6EHt014yKP9ahRd 26 | zlVbHD4li+Ht1A54z/bxaWokk2PwzfFjVjMJhm5N0QvsWN2rPMP2 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-rsa.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-b-rsa.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-b-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDfEK7c0C/CjcMJ 3 | SjbDTDVrCNl+4ycD1eCdiOPLzha5G2q+yp1IHehkqqD7IkndhVImcqe4Ttmw+kP/ 4 | 7OpSelb3kydXr9j4dFYmo0DlyVUdkMc0MLcCSNhOFxBUy5P17lzkQU2XbtDiPhVI 5 | VboqFxFKJT3THoRW7Ocv4nle2ReEQGyOQ1QMDOlp241PIzW04zTJRcT71AKQegCU 6 | 5eliVJ1EAG+6nQvAw/T+DLJcLI3p77WWNXEga3UX1Q6uKQtfPyiZl+Z91TjYwtsH 7 | hClO3BTspwe0RLUUvyA3SPj1BJ99IiZ4e7XUsuxrf7j5jyU1F/jMDxkoeqoIW9ET 8 | B1xMFVFnAgMBAAECggEAHOu70DNJze61V9IAcafC0ULPeC0ZVNz5B1PFPRpWRd+x 9 | IlWAuOXvyIV647SZYRg1A3kgF7xZayG3iUn9Q35LIkQ4+Jx7BBOJS+8kreZBm9i2 10 | iyS5xZkOOmmxG11drKgf8RQqbDTY7kxgVAWRYn2lJzjW4DV3sRF8E/BIDi0VaHb3 11 | 4U9ZPeF0kmwp6m3Ku30tYnV/PEbs1b+1m/3cC8eBLJCm95mXo93h6xW9Mm2nqGv7 12 | eeCfTK4aai+EArbnBSjXvHu2+xy+JYH5BElsTXtRkGR7vijFDbVWqA1n8QFfNqFG 13 | 4rz3n7YN2QNp+jcDisBrXcYq0ilZLC0fPEVGfNSXIQKBgQD0HtoaQlGv/5kbQYvW 14 | Iwo+rk9sW5kOJS0d69h+YEwQ3R6qX5N4/yzHO03GQJB5G2TRc6OvaGfJ/D03ug1+ 15 | xweEmIfOmdCl22mYvBxsFaFB2XIt9APnMJdpFOJH5iumU9ZdKpdH6Szb15l2UMGT 16 | ETgfh9TrkedUJW1WsMg9xYaolwKBgQDp64hcnAF4RC90WujGa1Dvm8tcwqHHekH3 17 | 2XwMQ+/+y/9mr1l/EZC83vx++mmsj4ZntZ9ejrn4xREZntjiIH3fb/tKc38/rWos 18 | 3ZMLvZ/2ublZxt2tAcJpwNBSUoGYPRNXLYn5Lr/k63l3qoz7r8Lcmtwwpr/TLJYZ 19 | cwM7Q8pnsQKBgElCFOt6aW8qgfTG98LcIw/qWVVIK6cuCtsG0qIiHdGVucUhB21x 20 | Div/pPhQmcpuKRQd4soZx8O6mVhm0fPwoFXvPBoI2K9dJ9Q450KcPxc2vOgDaURw 21 | tY9IQBuZfBHe6N5ukJV46QhUK+5wj5alvTThG0lSMJx02toAFSdMZnujAoGAHorX 22 | Uig4dOiKPaoFDKtEdRSld+Yd03reFCt8a+mO83jVTyYEDHhRqqd+1mGB3LsctHvd 23 | ZC5Ej/vDINJBxTyy0rK/X9g2vCy7WUJRCc5njYJwdg1mMkmxhbdcO/Nz4lnPJanX 24 | gwacnZo1UO+e2tn3GnDJ4TxUfZErxATlXh6a1fECgYEApNnkg559AIyLrCWeeMV1 25 | b4KWNU9TFNjKfuDLK0tPhC6ZBuCl0lbHVnVTuoxZ49a2G0d59O4wcTgzqIF3F73K 26 | ONZNgdMgYNfsN/prILpXoQe3TXjIo/1qFF3OVVscPiWL4e3UDnjP9vFpaiSTY/DN 27 | 8WNWMwmGbk3RC+xY3as8w/Y= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ecdsa-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIMT9ZvRG3TIQNkGrhWFk6gBzxgoSJfpo9SFJCVeFM5zRoAoGCCqGSM49 3 | AwEHoUQDQgAEi0qKkNhc2Ghcn3tPxTO7VdzTd9tPm7LthSwHRjEWWUQ1RinUPsgw 4 | 5DGfUNegQuCnKv0B6ZbN8+J3rn+aawq84Q== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ecdsa.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-c-ecdsa.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgxP1m9EbdMhA2QauF 3 | YWTqAHPGChIl+mj1IUkJV4UznNGhRANCAASLSoqQ2FzYaFyfe0/FM7tV3NN320+b 4 | su2FLAdGMRZZRDVGKdQ+yDDkMZ9Q16BC4Kcq/QHpls3z4neuf5prCrzh 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ed25519.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-c-ed25519.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ed25519.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEINADP5AJRw54UI23bcrXJHUm7sPmlME16yNVd2LjeIbL 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ed488.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-c-ed488.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-ed488.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MEcCAQAwBQYDK2VxBDsEOfYPklaf+xXYexMnYiOw8YSawNwNKjQZmEcsYM1DXA/A 3 | Iw1tgSYVz1IXk61skHsgeqVU0GV6yrNLwQ== 4 | -----END PRIVATE KEY----- 5 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-rsa-traditional.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAzsvOx2O7EdB9s7iwajYcL68j0lMVJI5ReRVtLVo0epVrTiIy 3 | XxuHk+Uf0WuKZQJrk+ZiHRejgTsgqztKpt5EExvsxv1vWkHOWTJRnj5KXAfEKhuL 4 | zSXR4BOvYrHbOXHz+KfkbKrITvzC0kbeHu4fK7yPMLPybWYSQULUpJnQYbtsUTbS 5 | gCyFApUHBMkyFE8Maq9gO8Nx2NQrMgHWmwMusg//DkAbaSTMJhoCpl6uO4iOJoev 6 | EXZ8V6ujFSpi9vg73VbOljroTr9rPclNu6lypef2HPwziBTJ+MstxN6Pz7DQcVZu 7 | 8MVnumbKKUuRK8DiiXZZf4IezM/Cbm66K1IuIQIDAQABAoIBAAcPA97gc5k3EaNZ 8 | 0YO+lxW1l7ZtKZKW3QcSCSj8JEBu6zu+hROj/+u3bW+biRzLiVqCCaVOkkEuAH53 9 | xqONgKtaT6m3Kt7c0itPQWPyYl1j0nlReWMmQFSyt1DaG06Jqjc5m91tsuqnTAsb 10 | aieKHzxB8m1KJyM+0a6ylkmMCoXbbSUGIh3qZWb40qI3isP6n5vYRLYvOUKhBJd1 11 | ZkxqmJIPf0UiECGs7mK9gRgQ+NHJZZ4+wKtFKU+ST1Vr/Xc8uHfslSoWKjC5wFeo 12 | p9rUlcsL/FeGCe8MLPAuCoxaVhd5OhIaGUHNEOX//aA6NH8Zz57+dssMqKJeA/vE 13 | nPL++QECgYEA+IJ9djzka+FIKRHfTRX3PaQjQLrYl67mt7DjFQ+8ALuylVrSEMnb 14 | Zc6f1feuNsFRd5D8GAh1GTMoHety113z3a2k9QpaJ2IbJ7fTPzR/TWUox3diXW3q 15 | K9M04QALT6wshmsCrAxI9M+idrSWYhX3tWWIjpjNA7NIHMYyMa085/ECgYEA1Qd0 16 | OR/cfTjZVCjooz703XwPx1VwH2qNwUSyhkkk9rpG1KEU3P2xExFWt6kTAwGSXTvl 17 | qczxwdBxywBeER87j6ojekGvDi7ok3gdQCONaD3pQFOeedrBOJlJit02wvbZXpYL 18 | DSzGS+LE05pDWUcwNAdsgDps0Q4C+OELW1V3WTECgYEA1bkMA6Ms4+bU85VOUXKB 19 | tv6x3tqSqikefX5gXd2xV4QVe0OnhA7GZJFGf3NK3gZ2dPk5BcZIRwrrBohWtQg1 20 | UkIjqyZjEJncNtVulV4l2b8VSi7PZwC/sz8qrBMopzWw+U2Q97x9BiaIV8TJzMON 21 | zPDsd47MStFmRHDj/Ds8NVECgYAhjhoFgXpGkzTQZ901EY6acJc/q7qMiEkp3ztL 22 | oavb3T2Y8oKJyMAio8GIDm67M30tiGjFlU2jXMT/19/5THUiTQdnk38SedsSl4Hr 23 | /22ftNjP1BwLT6TN2H9YCz47+YwFtRaqjZnyjBa6yfq/zlHOcDjr/cf0KgPX1gLm 24 | 8RBqkQKBgQCdbjLy8Eo5UwtJvckpm2zHrsHVh/RU3f7DRi+G93tO5wPbmPJN2CyK 25 | Yq/0dEvALwWvwrF0s94KOovu9cJC1q4hRCXEv4hbacinBtvOcvYVhxAlfqfzgtdI 26 | uBcRrIdRp2j6bsOFKckv13ehLMShkJwpvO/dhhBKqFA5EXnb6apvCw== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-rsa.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/private/server-c-rsa.der -------------------------------------------------------------------------------- /test/testdata/pki/private/server-c-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOy87HY7sR0H2z 3 | uLBqNhwvryPSUxUkjlF5FW0tWjR6lWtOIjJfG4eT5R/Ra4plAmuT5mIdF6OBOyCr 4 | O0qm3kQTG+zG/W9aQc5ZMlGePkpcB8QqG4vNJdHgE69isds5cfP4p+RsqshO/MLS 5 | Rt4e7h8rvI8ws/JtZhJBQtSkmdBhu2xRNtKALIUClQcEyTIUTwxqr2A7w3HY1Csy 6 | AdabAy6yD/8OQBtpJMwmGgKmXq47iI4mh68RdnxXq6MVKmL2+DvdVs6WOuhOv2s9 7 | yU27qXKl5/Yc/DOIFMn4yy3E3o/PsNBxVm7wxWe6ZsopS5ErwOKJdll/gh7Mz8Ju 8 | brorUi4hAgMBAAECggEABw8D3uBzmTcRo1nRg76XFbWXtm0pkpbdBxIJKPwkQG7r 9 | O76FE6P/67dtb5uJHMuJWoIJpU6SQS4AfnfGo42Aq1pPqbcq3tzSK09BY/JiXWPS 10 | eVF5YyZAVLK3UNobTomqNzmb3W2y6qdMCxtqJ4ofPEHybUonIz7RrrKWSYwKhdtt 11 | JQYiHeplZvjSojeKw/qfm9hEti85QqEEl3VmTGqYkg9/RSIQIazuYr2BGBD40cll 12 | nj7Aq0UpT5JPVWv9dzy4d+yVKhYqMLnAV6in2tSVywv8V4YJ7wws8C4KjFpWF3k6 13 | EhoZQc0Q5f/9oDo0fxnPnv52ywyool4D+8Sc8v75AQKBgQD4gn12PORr4UgpEd9N 14 | Ffc9pCNAutiXrua3sOMVD7wAu7KVWtIQydtlzp/V9642wVF3kPwYCHUZMygd63LX 15 | XfPdraT1ClonYhsnt9M/NH9NZSjHd2Jdbeor0zThAAtPrCyGawKsDEj0z6J2tJZi 16 | Ffe1ZYiOmM0Ds0gcxjIxrTzn8QKBgQDVB3Q5H9x9ONlUKOijPvTdfA/HVXAfao3B 17 | RLKGSST2ukbUoRTc/bETEVa3qRMDAZJdO+WpzPHB0HHLAF4RHzuPqiN6Qa8OLuiT 18 | eB1AI41oPelAU5552sE4mUmK3TbC9tlelgsNLMZL4sTTmkNZRzA0B2yAOmzRDgL4 19 | 4QtbVXdZMQKBgQDVuQwDoyzj5tTzlU5RcoG2/rHe2pKqKR59fmBd3bFXhBV7Q6eE 20 | DsZkkUZ/c0reBnZ0+TkFxkhHCusGiFa1CDVSQiOrJmMQmdw21W6VXiXZvxVKLs9n 21 | AL+zPyqsEyinNbD5TZD3vH0GJohXxMnMw43M8Ox3jsxK0WZEcOP8Ozw1UQKBgCGO 22 | GgWBekaTNNBn3TURjppwlz+ruoyISSnfO0uhq9vdPZjygonIwCKjwYgObrszfS2I 23 | aMWVTaNcxP/X3/lMdSJNB2eTfxJ52xKXgev/bZ+02M/UHAtPpM3Yf1gLPjv5jAW1 24 | FqqNmfKMFrrJ+r/OUc5wOOv9x/QqA9fWAubxEGqRAoGBAJ1uMvLwSjlTC0m9ySmb 25 | bMeuwdWH9FTd/sNGL4b3e07nA9uY8k3YLIpir/R0S8AvBa/CsXSz3go6i+71wkLW 26 | riFEJcS/iFtpyKcG285y9hWHECV+p/OC10i4FxGsh1GnaPpuw4UpyS/Xd6EsxKGQ 27 | nCm8792GEEqoUDkRedvpqm8L 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heartbeatsjp/check-tls-cert/bef085ec8b0e2d853fad02502591e8129e4a4de3/test/testdata/pki/root-ca/.gitkeep -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/ca-root-g1-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFIzCCAwugAwIBAgIUHM7alL+p6C365VOB5CvrAIq+MQYwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMSBSU0EwHhcNMDUwMTAxMDAwMDAwWhcN 4 | MzUwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5ST09UIENBIEcxIFJTQTCCAiIwDQYJ 5 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqIZJacHiZYJfN3ikJyj+HFbBoOjt9F 6 | PjtfdvAT6d9tquE/8LENLzZ7fG3u5D2+AdJorz869JD5YuAEWNDnniw0BVJ6JZUJ 7 | rdTLtOYxGdCYxkPLOaQX74jV1tNrigAl4KgQpr1evUIXu4OhROOPSCUHxQ09HPU4 8 | i5eozIwBSmnvrhoIfCnDdV5mcBDwFMyYNWsZKveIudAclmCbhqZEz3pibYxhBCew 9 | 7h+52xGcwPDv42+P+jf3CdKk6K0nwg4YMKdwWhSXuL+nDLVvMT4+6WyP0Bx5XO/w 10 | Kb1wWqqSJgOGLuijgpYjiAvq/W86HlnGlqrF/liUYFbby9pPVoQ9fQ4P0UkS1HNH 11 | CEoVLg2DI0hpiV4uk8B2REf6R8xhaLa7Qb5eEjR6vlgj67qMUgaxjGXKbs+VS+Wb 12 | WQYi6xL42COZS+E/J6xEISS/8qSvJVl6BrfKhRupL9sPeP3oymuv7WtPFIitTKSE 13 | hlxVy5JdV+424GnyVVr9d9WFhnM0fGHkJoQPxr/vA48ZNJb8vrSTkTrqbc7ysFJk 14 | CDOYS0KVjOwYfDuXQfnBbW4FQC9cn19TOGbIUVGXp5pzJyH1eMvPeAJappxrsB9r 15 | 7HNkNkjICwtuO+fJEo+2XXz+FusUANgAOKl2Uq3RI2PSQY3mo7wa0C13/sBAfeSS 16 | cwoJIhADwrCBAgMBAAGjYzBhMB0GA1UdDgQWBBQt08hgUbLw3ds13d4qkoVDeLNj 17 | PjAfBgNVHSMEGDAWgBQt08hgUbLw3ds13d4qkoVDeLNjPjAPBgNVHRMBAf8EBTAD 18 | AQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEAcji27WokzJ8U 19 | oj8q/k5jcV6uH1n/7n2hgwJFeKogHGaAUpy0iJLnjgkmwhusWx8Zct8+J55+T1at 20 | mzbOi3dQXD8lhA0fQbOqXFTKkPSa6CBYg2KCFZpGz4b5TdntpK61GBZWrmUXdVNZ 21 | RiAq9G6KpDBMmM/qeL88y7WchFiqYc/EKR/ZKAzU+pPFMnWfnZV6G2iNgrE1q5BF 22 | N+owFfyLooSBAdjGqLD6Q6A8wgfc/iCQPc55madzCaf4cEw5PY6fCAmlOJo+wofW 23 | OmVZC0z4LP3RpJOjhxJcC6C/wxsr43KoW8+LmDXzDuyC0TbH79XQIUgWTKg68w+M 24 | Ih/7Z+7kUj9q7ZqMht46hpnhI85C/Uyqbdz7NFrVw8KftC/Cf2DA1mLARk/emDVx 25 | 0X0CZC4o6xSPmGPFCo9nwZI8hQBKuEJLTWrsE2gsyU7C2WLaTvqa0doBlnof1afH 26 | W16UUHqZPuDq/fWNto1TweDmQTGMcoaP8AS2+aQLJHL5ASc+MOjs53oCXGKpW5+7 27 | TJMEaauUz8LD7lkbdioS8ROVvcDYwjJR0nXWxFjWw9+vOQTDSCJmIfIfm/szZ0ED 28 | zzGpGmJV9qsF0ijYW0iv/JN4wN0g4o7ovrK+tbypXLMj2JLonWNnIJUqPh+baXQy 29 | LEkYlG2wKFbl/E9/TqcLfJ1SE5EUk/U= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/ca-root-g2-ecdsa-cross.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDmDCCAYCgAwIBAgIUG6U2/tZHv/7+YmTEsw9LKcSb3SMwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMSBSU0EwHhcNMTUwMTAxMDAwMDAwWhcN 4 | MzUwMTAxMDAwMDAwWjAbMRkwFwYDVQQDDBBST09UIENBIEcyIEVDRFNBMHYwEAYH 5 | KoZIzj0CAQYFK4EEACIDYgAEyETH/UJ5yW8x6L3f3lm+1jI//PNmX6qwAHEUO1nI 6 | GOFHejTXIm/7KgLnc1gJ90ZX+aYZL/O1kYJx4FCtd4uk7dmd9PK0xJQX6IxqBma2 7 | Ox7ZWT36ZxrUIDdZDpwdCRgzo4GDMIGAMB0GA1UdDgQWBBQkaauiI4mMI1tAeUO8 8 | YPZKZBPuLzAfBgNVHSMEGDAWgBQt08hgUbLw3ds13d4qkoVDeLNjPjAOBgNVHQ8B 9 | Af8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB 10 | /wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFjGRIMfg7WzvC+LTR95MYPx4ib+ 11 | 9/anc80SYFm05Bhxho9M1EmRVeSLTCuFWvU0Pd9NCW6sgX2419DCHezu9LGwerjw 12 | D52iyM0+VXm01xsLPV4u44IPTDx/84T39CWdYQf2MM0XG4oq6enEvK1Uu2Ct1U7j 13 | d906esfpS8DiEY9slyxZFT2aMocJX8urmXLLntXJopkL6X5AFaeEglzAbZGXCAIN 14 | Fq37C7waAVsuqrroaTKmujPy0QwsYV0PGLVXd3Rme2bz3E8lAruI6Mrsm3d8siYx 15 | XzuTkcbMdWWtge/pWiZne8KoLSP7uI1C3yqX3Gw0SwcTsRII/vTpzNRiNW98IH3z 16 | kTV6nfNaueWGyMgIyNWOgapJZY9C4797XoiEshL0rmy2iYMAAg4yVQ/p7VBES2/T 17 | KcfdPU//NiIGypODjXdDJag3e6RPi5Kednnh32Q/UUwbaUulT4SCxi4YWAI8db4M 18 | dpzUk73WLhKU6KuH+iOd7UR6c+TtY1Z/940beoyH87b8jnhw1JYkm+cu5LMjQpQx 19 | aD41S/XrnpMMcvJSbwDl72hjj6RD24aaP78iNyWh7+kep35DD8ewUDMhq8DFshZd 20 | nTpPpe8hMstrzK5f9VleS2kHd5XG6JwhYYRSaty5yZommxrU0ilAz3z+xTpsNteG 21 | 3HqPc3N1McZ/+LAR 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/ca-root-g2-ecdsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIB1zCCAV6gAwIBAgIUAbJQpPu5ayEeWvkxjzkamtuM2/wwCgYIKoZIzj0EAwMw 3 | GzEZMBcGA1UEAwwQUk9PVCBDQSBHMiBFQ0RTQTAeFw0xNTAxMDEwMDAwMDBaFw0z 4 | NTAxMDEwMDAwMDBaMBsxGTAXBgNVBAMMEFJPT1QgQ0EgRzIgRUNEU0EwdjAQBgcq 5 | hkjOPQIBBgUrgQQAIgNiAATIRMf9QnnJbzHovd/eWb7WMj/882ZfqrAAcRQ7WcgY 6 | 4Ud6NNcib/sqAudzWAn3Rlf5phkv87WRgnHgUK13i6Tt2Z308rTElBfojGoGZrY7 7 | HtlZPfpnGtQgN1kOnB0JGDOjYzBhMB0GA1UdDgQWBBQkaauiI4mMI1tAeUO8YPZK 8 | ZBPuLzAfBgNVHSMEGDAWgBQkaauiI4mMI1tAeUO8YPZKZBPuLzAPBgNVHRMBAf8E 9 | BTADAQH/MA4GA1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAwNnADBkAjA1XnbYgI79 10 | nG/2yfeX+8Fy21i/1fiECMtxq0QyPPD76tN9NblCzo6oLvuy9p5E0z0CMCYEJyxL 11 | gnAWDZUUbhm0nk+C8FXLyGAB1MLU0pru+Qq24vrk3Y2Va57dyEnEXOneBQ== 12 | -----END CERTIFICATE----- 13 | -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/ca-root-g2-rsa-cross.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFRDCCAyygAwIBAgIUCQQjC/PCbOmZkSd8mLcGdq6vnpAwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMSBSU0EwHhcNMTUwMTAxMDAwMDAwWhcN 4 | MzUwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5ST09UIENBIEcyIFJTQTCCAiIwDQYJ 5 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnhooFgwsXWZDJadS8RBwW5QzvRJZTW 6 | 8EhGlaUJJv2YwHUZx3AvpPGD274XCvMGAdUvpJiA5GEmTFILS4aksur1phchMonM 7 | JNZfUzAicRbSxFWtoz3Lq5obfDQgVDiWf9fHjtSJfYXlzBmC6yHIe9r1skUuQv17 8 | Mr+SOH2dyf9axhB2wJBFbZn/bGEdFIN0fMx5trSU6Q+Oab8HviGw37FnMrNPJsN9 9 | dftZOFc3UQ5XQO9JUnUtI/INNRWUvdGg4S/UKL7JEv8+T85zF+g8VyH4DHlPSIDp 10 | m5bYaAGZf5GlPS1l0kONoV+e8uYKkhZrGZfwNeuwQwtLgtLK3uw80dU52Cz9kGo2 11 | 2ysmAx2zQxHafAt0ByD6gVuAp1fEO2dMoKAt2+VD0IidQd/CDRlEKR3oeFf/HHgh 12 | 7Sgc7dMsZof1OlRnM3ixDzMPyi5KC4Rs1zfOwJ7HHcAnmEqWSqZ2jyGLpJ2lOfp2 13 | stzqJkhVDur9Q57NQs47wk5ZRH447VHw2wQ0gRIixYKlBP42+SZ2XVpMwDKETMPR 14 | OmgEwhNoRg+WVffm7yQZQEAPemJBwF1Z9CEtaUca9NJjTAxFhcZk7V2xGSAHBjTr 15 | uVh2njkX87m/0Lduq+rVBbvTlXvhv8YTDGdV9r6jiOhgHW3kWqJYRTE+TDXviYlW 16 | OQi3IYIvnomvAgMBAAGjgYMwgYAwHQYDVR0OBBYEFFd2WG4PgzFxNUn4tL5hpkOB 17 | T1huMB8GA1UdIwQYMBaAFC3TyGBRsvDd2zXd3iqShUN4s2M+MA4GA1UdDwEB/wQE 18 | AwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw 19 | AwEB/zANBgkqhkiG9w0BAQwFAAOCAgEAqiwy7OEYTddPMZQlvcyIBmCdylbKRqLC 20 | whm08GaekIn3mMOKJg2mYxZtmdBGz5EuStfVyTtl2HZCJS2cCc/PaLd9x01qqWxF 21 | LkmEz4VuIml+hudtWwTd4kR1l2TW2OWrHyKuZTQpD4EGY8P8XYaCUJLHQJOs6/+x 22 | +y4o4RpmjJBD5D/mTLq+oi0P95V9doYtP1BzWldxzylS06KaznpQELKQNbHTt3wx 23 | BCfcOBtQgppWSuT4oKUis4DrM/0C9MJhvnV9NXC9VREkjhhJQHEYUETlLLiONcr+ 24 | 8hLvAdhei+N9p2pHV0fRHpfaGGdLPZohk19PQOmsfL708+fW3xvwg7opaXgRc1+f 25 | G9PP2UkjgNFBsgb2zbej6GsbXazwDA//XS45k0estDPVOis4r2YidnMQYljECsa9 26 | evBpzLXGibCwSsU6iwQzklJYX6Q3OrcGBGnzvvAegBEpwSvbDlqlrV1A2o3NDymo 27 | jZM3hbRrmBEckhdwP1gJtF8M5HtqJ8iIOjT1xVMUEQMufhx/GFiaW/gNHC5u9N32 28 | wnUpCL6amTRbjQP5HpMLoHWRBsRoRk+v73OS+9QdFR1w7rfjet9ciYtVGXoFMqpj 29 | Ki7iwbSI/+23NEh7X/u/QYKmp6yt70dNkhH8crz2z86/mYT2iwI5AorB8YwD7vCG 30 | XbuPPe7V1+c= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/ca-root-g2-rsa.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFIzCCAwugAwIBAgIUDa9laqtVX+A1PzYjWobEAOvjXfAwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMiBSU0EwHhcNMTUwMTAxMDAwMDAwWhcN 4 | MzUwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5ST09UIENBIEcyIFJTQTCCAiIwDQYJ 5 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnhooFgwsXWZDJadS8RBwW5QzvRJZTW 6 | 8EhGlaUJJv2YwHUZx3AvpPGD274XCvMGAdUvpJiA5GEmTFILS4aksur1phchMonM 7 | JNZfUzAicRbSxFWtoz3Lq5obfDQgVDiWf9fHjtSJfYXlzBmC6yHIe9r1skUuQv17 8 | Mr+SOH2dyf9axhB2wJBFbZn/bGEdFIN0fMx5trSU6Q+Oab8HviGw37FnMrNPJsN9 9 | dftZOFc3UQ5XQO9JUnUtI/INNRWUvdGg4S/UKL7JEv8+T85zF+g8VyH4DHlPSIDp 10 | m5bYaAGZf5GlPS1l0kONoV+e8uYKkhZrGZfwNeuwQwtLgtLK3uw80dU52Cz9kGo2 11 | 2ysmAx2zQxHafAt0ByD6gVuAp1fEO2dMoKAt2+VD0IidQd/CDRlEKR3oeFf/HHgh 12 | 7Sgc7dMsZof1OlRnM3ixDzMPyi5KC4Rs1zfOwJ7HHcAnmEqWSqZ2jyGLpJ2lOfp2 13 | stzqJkhVDur9Q57NQs47wk5ZRH447VHw2wQ0gRIixYKlBP42+SZ2XVpMwDKETMPR 14 | OmgEwhNoRg+WVffm7yQZQEAPemJBwF1Z9CEtaUca9NJjTAxFhcZk7V2xGSAHBjTr 15 | uVh2njkX87m/0Lduq+rVBbvTlXvhv8YTDGdV9r6jiOhgHW3kWqJYRTE+TDXviYlW 16 | OQi3IYIvnomvAgMBAAGjYzBhMB0GA1UdDgQWBBRXdlhuD4MxcTVJ+LS+YaZDgU9Y 17 | bjAfBgNVHSMEGDAWgBRXdlhuD4MxcTVJ+LS+YaZDgU9YbjAPBgNVHRMBAf8EBTAD 18 | AQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEAbV68CS28eAR0 19 | vRwPVdQ8WYV8aX+q4HKBIPC37DkUqeVTEClXTJDLVDmfecyJ1ZnTHyCFvBlBYelB 20 | CY9GbIGgvMz85PTWSLYXG5+Ysz4nCRyi4wiNPQVcETyFNE+IVI7aEKBj9IF0c2YE 21 | f7r6nrl49MRzkivKp+P+/HEx+m0wUfW5HHtCWF2oApZfbzreHG4eOLZzSK5+kEeC 22 | rKGd19KRhSGhjJv5sqTy8yvQsepK4SVRXfmQvWK218i5irV3Vjlde56619jg0S9z 23 | dqARi+CBt4UmE4DmbKgeftIZWJw0FkOqGe0zgdoqzCaCXZ+gcZriAR1goz9n9dhO 24 | uUd5SvCuyaf4q2j/ZrQqaTcQBNGjg8gNITEGN8oD+ClY8Tb5ThCWcj/6XUx+LAYU 25 | FGtecf0dsMEKNRyOjDN2ExR8lQPlUEnYz+E7OGaYIsFYhjyNT2G1KBgMu3BSqtj0 26 | TgXgvA08j/KjzQI1LsVAONRKywj/n5lK/R1jBeUE5f9Oagn8TCpAzqbN+J0HpBh2 27 | /leHoGiJEcoZvMGFOw1KdaqiC1KQJ2li4HaFCGX/cMiUUWlWdh+C+JcdXWwaeJ+P 28 | Q/jptu1kFD8d3W4vmqKhJF5lN9/K6zML26KKIM1Dzag1aBKAIgSHeI93Sujd+DfV 29 | EKeJk9BsqKAt7FccIVfxljRIo1U+Q/g= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /test/testdata/pki/root-ca/ca-root.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFIzCCAwugAwIBAgIUHM7alL+p6C365VOB5CvrAIq+MQYwDQYJKoZIhvcNAQEM 3 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMSBSU0EwHhcNMDUwMTAxMDAwMDAwWhcN 4 | MzUwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5ST09UIENBIEcxIFJTQTCCAiIwDQYJ 5 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqIZJacHiZYJfN3ikJyj+HFbBoOjt9F 6 | PjtfdvAT6d9tquE/8LENLzZ7fG3u5D2+AdJorz869JD5YuAEWNDnniw0BVJ6JZUJ 7 | rdTLtOYxGdCYxkPLOaQX74jV1tNrigAl4KgQpr1evUIXu4OhROOPSCUHxQ09HPU4 8 | i5eozIwBSmnvrhoIfCnDdV5mcBDwFMyYNWsZKveIudAclmCbhqZEz3pibYxhBCew 9 | 7h+52xGcwPDv42+P+jf3CdKk6K0nwg4YMKdwWhSXuL+nDLVvMT4+6WyP0Bx5XO/w 10 | Kb1wWqqSJgOGLuijgpYjiAvq/W86HlnGlqrF/liUYFbby9pPVoQ9fQ4P0UkS1HNH 11 | CEoVLg2DI0hpiV4uk8B2REf6R8xhaLa7Qb5eEjR6vlgj67qMUgaxjGXKbs+VS+Wb 12 | WQYi6xL42COZS+E/J6xEISS/8qSvJVl6BrfKhRupL9sPeP3oymuv7WtPFIitTKSE 13 | hlxVy5JdV+424GnyVVr9d9WFhnM0fGHkJoQPxr/vA48ZNJb8vrSTkTrqbc7ysFJk 14 | CDOYS0KVjOwYfDuXQfnBbW4FQC9cn19TOGbIUVGXp5pzJyH1eMvPeAJappxrsB9r 15 | 7HNkNkjICwtuO+fJEo+2XXz+FusUANgAOKl2Uq3RI2PSQY3mo7wa0C13/sBAfeSS 16 | cwoJIhADwrCBAgMBAAGjYzBhMB0GA1UdDgQWBBQt08hgUbLw3ds13d4qkoVDeLNj 17 | PjAfBgNVHSMEGDAWgBQt08hgUbLw3ds13d4qkoVDeLNjPjAPBgNVHRMBAf8EBTAD 18 | AQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEAcji27WokzJ8U 19 | oj8q/k5jcV6uH1n/7n2hgwJFeKogHGaAUpy0iJLnjgkmwhusWx8Zct8+J55+T1at 20 | mzbOi3dQXD8lhA0fQbOqXFTKkPSa6CBYg2KCFZpGz4b5TdntpK61GBZWrmUXdVNZ 21 | RiAq9G6KpDBMmM/qeL88y7WchFiqYc/EKR/ZKAzU+pPFMnWfnZV6G2iNgrE1q5BF 22 | N+owFfyLooSBAdjGqLD6Q6A8wgfc/iCQPc55madzCaf4cEw5PY6fCAmlOJo+wofW 23 | OmVZC0z4LP3RpJOjhxJcC6C/wxsr43KoW8+LmDXzDuyC0TbH79XQIUgWTKg68w+M 24 | Ih/7Z+7kUj9q7ZqMht46hpnhI85C/Uyqbdz7NFrVw8KftC/Cf2DA1mLARk/emDVx 25 | 0X0CZC4o6xSPmGPFCo9nwZI8hQBKuEJLTWrsE2gsyU7C2WLaTvqa0doBlnof1afH 26 | W16UUHqZPuDq/fWNto1TweDmQTGMcoaP8AS2+aQLJHL5ASc+MOjs53oCXGKpW5+7 27 | TJMEaauUz8LD7lkbdioS8ROVvcDYwjJR0nXWxFjWw9+vOQTDSCJmIfIfm/szZ0ED 28 | zzGpGmJV9qsF0ijYW0iv/JN4wN0g4o7ovrK+tbypXLMj2JLonWNnIJUqPh+baXQy 29 | LEkYlG2wKFbl/E9/TqcLfJ1SE5EUk/U= 30 | -----END CERTIFICATE----- 31 | -----BEGIN CERTIFICATE----- 32 | MIIFIzCCAwugAwIBAgIUDa9laqtVX+A1PzYjWobEAOvjXfAwDQYJKoZIhvcNAQEM 33 | BQAwGTEXMBUGA1UEAwwOUk9PVCBDQSBHMiBSU0EwHhcNMTUwMTAxMDAwMDAwWhcN 34 | MzUwMTAxMDAwMDAwWjAZMRcwFQYDVQQDDA5ST09UIENBIEcyIFJTQTCCAiIwDQYJ 35 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMnhooFgwsXWZDJadS8RBwW5QzvRJZTW 36 | 8EhGlaUJJv2YwHUZx3AvpPGD274XCvMGAdUvpJiA5GEmTFILS4aksur1phchMonM 37 | JNZfUzAicRbSxFWtoz3Lq5obfDQgVDiWf9fHjtSJfYXlzBmC6yHIe9r1skUuQv17 38 | Mr+SOH2dyf9axhB2wJBFbZn/bGEdFIN0fMx5trSU6Q+Oab8HviGw37FnMrNPJsN9 39 | dftZOFc3UQ5XQO9JUnUtI/INNRWUvdGg4S/UKL7JEv8+T85zF+g8VyH4DHlPSIDp 40 | m5bYaAGZf5GlPS1l0kONoV+e8uYKkhZrGZfwNeuwQwtLgtLK3uw80dU52Cz9kGo2 41 | 2ysmAx2zQxHafAt0ByD6gVuAp1fEO2dMoKAt2+VD0IidQd/CDRlEKR3oeFf/HHgh 42 | 7Sgc7dMsZof1OlRnM3ixDzMPyi5KC4Rs1zfOwJ7HHcAnmEqWSqZ2jyGLpJ2lOfp2 43 | stzqJkhVDur9Q57NQs47wk5ZRH447VHw2wQ0gRIixYKlBP42+SZ2XVpMwDKETMPR 44 | OmgEwhNoRg+WVffm7yQZQEAPemJBwF1Z9CEtaUca9NJjTAxFhcZk7V2xGSAHBjTr 45 | uVh2njkX87m/0Lduq+rVBbvTlXvhv8YTDGdV9r6jiOhgHW3kWqJYRTE+TDXviYlW 46 | OQi3IYIvnomvAgMBAAGjYzBhMB0GA1UdDgQWBBRXdlhuD4MxcTVJ+LS+YaZDgU9Y 47 | bjAfBgNVHSMEGDAWgBRXdlhuD4MxcTVJ+LS+YaZDgU9YbjAPBgNVHRMBAf8EBTAD 48 | AQH/MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEAbV68CS28eAR0 49 | vRwPVdQ8WYV8aX+q4HKBIPC37DkUqeVTEClXTJDLVDmfecyJ1ZnTHyCFvBlBYelB 50 | CY9GbIGgvMz85PTWSLYXG5+Ysz4nCRyi4wiNPQVcETyFNE+IVI7aEKBj9IF0c2YE 51 | f7r6nrl49MRzkivKp+P+/HEx+m0wUfW5HHtCWF2oApZfbzreHG4eOLZzSK5+kEeC 52 | rKGd19KRhSGhjJv5sqTy8yvQsepK4SVRXfmQvWK218i5irV3Vjlde56619jg0S9z 53 | dqARi+CBt4UmE4DmbKgeftIZWJw0FkOqGe0zgdoqzCaCXZ+gcZriAR1goz9n9dhO 54 | uUd5SvCuyaf4q2j/ZrQqaTcQBNGjg8gNITEGN8oD+ClY8Tb5ThCWcj/6XUx+LAYU 55 | FGtecf0dsMEKNRyOjDN2ExR8lQPlUEnYz+E7OGaYIsFYhjyNT2G1KBgMu3BSqtj0 56 | TgXgvA08j/KjzQI1LsVAONRKywj/n5lK/R1jBeUE5f9Oagn8TCpAzqbN+J0HpBh2 57 | /leHoGiJEcoZvMGFOw1KdaqiC1KQJ2li4HaFCGX/cMiUUWlWdh+C+JcdXWwaeJ+P 58 | Q/jptu1kFD8d3W4vmqKhJF5lN9/K6zML26KKIM1Dzag1aBKAIgSHeI93Sujd+DfV 59 | EKeJk9BsqKAt7FccIVfxljRIo1U+Q/g= 60 | -----END CERTIFICATE----- 61 | -----BEGIN CERTIFICATE----- 62 | MIIB1zCCAV6gAwIBAgIUAbJQpPu5ayEeWvkxjzkamtuM2/wwCgYIKoZIzj0EAwMw 63 | GzEZMBcGA1UEAwwQUk9PVCBDQSBHMiBFQ0RTQTAeFw0xNTAxMDEwMDAwMDBaFw0z 64 | NTAxMDEwMDAwMDBaMBsxGTAXBgNVBAMMEFJPT1QgQ0EgRzIgRUNEU0EwdjAQBgcq 65 | hkjOPQIBBgUrgQQAIgNiAATIRMf9QnnJbzHovd/eWb7WMj/882ZfqrAAcRQ7WcgY 66 | 4Ud6NNcib/sqAudzWAn3Rlf5phkv87WRgnHgUK13i6Tt2Z308rTElBfojGoGZrY7 67 | HtlZPfpnGtQgN1kOnB0JGDOjYzBhMB0GA1UdDgQWBBQkaauiI4mMI1tAeUO8YPZK 68 | ZBPuLzAfBgNVHSMEGDAWgBQkaauiI4mMI1tAeUO8YPZKZBPuLzAPBgNVHRMBAf8E 69 | BTADAQH/MA4GA1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAwNnADBkAjA1XnbYgI79 70 | nG/2yfeX+8Fy21i/1fiECMtxq0QyPPD76tN9NblCzo6oLvuy9p5E0z0CMCYEJyxL 71 | gnAWDZUUbhm0nk+C8FXLyGAB1MLU0pru+Qq24vrk3Y2Va57dyEnEXOneBQ== 72 | -----END CERTIFICATE----- 73 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package version 6 | 7 | // Version describe a version number. 8 | const Version = "0.9.0" 9 | -------------------------------------------------------------------------------- /x509util/dn.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011, 2021 The Go Authors and HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This package is a modification of the crypto.x509.pkix package. 6 | // See also: 7 | // https://golang.org/src/crypto/x509/pkix/pkix.go 8 | 9 | package x509util 10 | 11 | import ( 12 | "crypto/x509/pkix" 13 | "encoding/asn1" 14 | "encoding/hex" 15 | "fmt" 16 | ) 17 | 18 | // DNType is a type of a Distinguished Name. 19 | type DNType int 20 | 21 | // DNType name 22 | const ( 23 | // strict format (RFC 4514) 24 | StrictDN = DNType(iota) 25 | 26 | // loose format with space 27 | LooseDN 28 | 29 | // OpenSSL format 30 | OpenSSLDN 31 | ) 32 | 33 | // DistinguishedName converts Distinguished Name to the specified type. 34 | func DistinguishedName(dn pkix.Name, dnType DNType) string { 35 | var converted string 36 | switch dnType { 37 | case StrictDN: 38 | converted = dn.String() 39 | case LooseDN: 40 | converted = toLooseDN(dn) 41 | case OpenSSLDN: 42 | converted = toOpenSSLDN(dn) 43 | default: 44 | converted = dn.String() 45 | } 46 | return converted 47 | } 48 | 49 | var attributeTypeNames = map[string]string{ 50 | "2.5.4.6": "C", 51 | "2.5.4.10": "O", 52 | "2.5.4.11": "OU", 53 | "2.5.4.3": "CN", 54 | "2.5.4.5": "SERIALNUMBER", 55 | "2.5.4.7": "L", 56 | "2.5.4.8": "ST", 57 | "2.5.4.9": "STREET", 58 | "2.5.4.17": "POSTALCODE", 59 | } 60 | 61 | func toLooseDN(dn pkix.Name) string { 62 | r := dn.ToRDNSequence() 63 | s := "" 64 | for i := 0; i < len(r); i++ { 65 | rdn := r[len(r)-1-i] 66 | if i > 0 { 67 | s += ", " 68 | } 69 | for j, tv := range rdn { 70 | if j > 0 { 71 | s += "+" 72 | } 73 | 74 | oidString := tv.Type.String() 75 | typeName, ok := attributeTypeNames[oidString] 76 | if !ok { 77 | derBytes, err := asn1.Marshal(tv.Value) 78 | if err == nil { 79 | s += oidString + "=#" + hex.EncodeToString(derBytes) 80 | continue // No value escaping necessary. 81 | } 82 | 83 | typeName = oidString 84 | } 85 | 86 | valueString := fmt.Sprint(tv.Value) 87 | escaped := make([]rune, 0, len(valueString)) 88 | 89 | for k, c := range valueString { 90 | escape := false 91 | 92 | switch c { 93 | case ',', '+', '"', '\\', '<', '>', ';': 94 | escape = true 95 | 96 | case ' ': 97 | escape = k == 0 || k == len(valueString)-1 98 | 99 | case '#': 100 | escape = k == 0 101 | } 102 | 103 | if escape { 104 | escaped = append(escaped, '\\', c) 105 | } else { 106 | escaped = append(escaped, c) 107 | } 108 | } 109 | 110 | s += typeName + "=" + string(escaped) 111 | } 112 | } 113 | 114 | return s 115 | } 116 | 117 | func toOpenSSLDN(dn pkix.Name) string { 118 | r := dn.ToRDNSequence() 119 | s := "" 120 | for i := 0; i < len(r); i++ { 121 | rdn := r[i] 122 | if i > 0 { 123 | s += ", " 124 | } 125 | for j, tv := range rdn { 126 | if j > 0 { 127 | s += "+" 128 | } 129 | 130 | oidString := tv.Type.String() 131 | typeName, ok := attributeTypeNames[oidString] 132 | if !ok { 133 | derBytes, err := asn1.Marshal(tv.Value) 134 | if err == nil { 135 | s += oidString + "=#" + hex.EncodeToString(derBytes) 136 | continue // No value escaping necessary. 137 | } 138 | 139 | typeName = oidString 140 | } 141 | 142 | valueString := fmt.Sprint(tv.Value) 143 | escaped := make([]rune, 0, len(valueString)) 144 | 145 | for k, c := range valueString { 146 | escape := false 147 | 148 | switch c { 149 | case ',', '+', '"', '\\', '<', '>', ';': 150 | escape = true 151 | 152 | case ' ': 153 | escape = k == 0 || k == len(valueString)-1 154 | 155 | case '#': 156 | escape = k == 0 157 | } 158 | 159 | if escape { 160 | escaped = append(escaped, '\\', c) 161 | } else { 162 | escaped = append(escaped, c) 163 | } 164 | } 165 | 166 | s += typeName + " = " + string(escaped) 167 | } 168 | } 169 | 170 | return s 171 | } 172 | -------------------------------------------------------------------------------- /x509util/dn_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package x509util_test 6 | 7 | import ( 8 | "crypto/x509/pkix" 9 | "testing" 10 | 11 | "github.com/heartbeatsjp/check-tls-cert/x509util" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func TestDistinguishedName(t *testing.T) { 16 | assert := assert.New(t) 17 | 18 | dn := pkix.Name{ 19 | CommonName: "server-a.test", 20 | Organization: []string{"Example"}, 21 | } 22 | 23 | assert.Equal("CN=server-a.test,O=Example", x509util.DistinguishedName(dn, x509util.StrictDN)) 24 | assert.Equal("CN=server-a.test, O=Example", x509util.DistinguishedName(dn, x509util.LooseDN)) 25 | assert.Equal("O = Example, CN = server-a.test", x509util.DistinguishedName(dn, x509util.OpenSSLDN)) 26 | assert.Equal("CN=server-a.test,O=Example", x509util.DistinguishedName(dn, -1)) 27 | } 28 | -------------------------------------------------------------------------------- /x509util/pem.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package x509util 6 | 7 | import "bytes" 8 | 9 | func ContainsPEMCertificate(data []byte) bool { 10 | return bytes.Contains(data, []byte("-----BEGIN CERTIFICATE-----")) 11 | } 12 | 13 | func ContainsPEMPrivateKey(data []byte) bool { 14 | pemTypes := []string{ 15 | "-----BEGIN RSA PRIVATE KEY-----", 16 | "-----BEGIN EC PRIVATE KEY-----", 17 | "-----BEGIN PRIVATE KEY-----", 18 | "-----BEGIN ENCRYPTED PRIVATE KEY-----", 19 | } 20 | 21 | for _, t := range pemTypes { 22 | if bytes.Contains(data, []byte(t)) { 23 | return true 24 | } 25 | } 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /x509util/pem_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package x509util_test 6 | 7 | import ( 8 | "os" 9 | "testing" 10 | 11 | "github.com/heartbeatsjp/check-tls-cert/x509util" 12 | "github.com/stretchr/testify/assert" 13 | ) 14 | 15 | func TestContainsPEMCertificate(t *testing.T) { 16 | var ( 17 | data []byte 18 | err error 19 | ) 20 | assert := assert.New(t) 21 | 22 | data, err = os.ReadFile("../test/testdata/pki/cert/valid/server-a-rsa.pem") 23 | assert.Nil(err) 24 | assert.True(x509util.ContainsPEMCertificate(data)) 25 | 26 | data, err = os.ReadFile("../test/testdata/pki/cert/valid/server-a-rsa.der") 27 | assert.Nil(err) 28 | assert.False(x509util.ContainsPEMCertificate(data)) 29 | 30 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-rsa.pem") 31 | assert.Nil(err) 32 | assert.False(x509util.ContainsPEMCertificate(data)) 33 | 34 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-rsa.der") 35 | assert.Nil(err) 36 | assert.False(x509util.ContainsPEMCertificate(data)) 37 | } 38 | 39 | func TestContainsPEMPrivateKey(t *testing.T) { 40 | var ( 41 | data []byte 42 | err error 43 | ) 44 | assert := assert.New(t) 45 | 46 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-rsa-traditional.pem") 47 | assert.Nil(err) 48 | assert.True(x509util.ContainsPEMPrivateKey(data)) 49 | 50 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-ecdsa-traditional.pem") 51 | assert.Nil(err) 52 | assert.True(x509util.ContainsPEMPrivateKey(data)) 53 | 54 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-rsa.pem") 55 | assert.Nil(err) 56 | assert.True(x509util.ContainsPEMPrivateKey(data)) 57 | 58 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-rsa-encrypted.pem") 59 | assert.Nil(err) 60 | assert.True(x509util.ContainsPEMPrivateKey(data)) 61 | 62 | data, err = os.ReadFile("../test/testdata/pki/private/server-a-rsa.der") 63 | assert.Nil(err) 64 | assert.False(x509util.ContainsPEMPrivateKey(data)) 65 | 66 | data, err = os.ReadFile("../test/testdata/pki/cert/valid/server-a-rsa.pem") 67 | assert.Nil(err) 68 | assert.False(x509util.ContainsPEMPrivateKey(data)) 69 | 70 | data, err = os.ReadFile("../test/testdata/pki/cert/valid/server-a-rsa.der") 71 | assert.Nil(err) 72 | assert.False(x509util.ContainsPEMPrivateKey(data)) 73 | } 74 | -------------------------------------------------------------------------------- /x509util/publickey.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package x509util 6 | 7 | import ( 8 | "crypto/ecdsa" 9 | "crypto/ed25519" 10 | "crypto/rsa" 11 | "crypto/x509" 12 | "fmt" 13 | "strings" 14 | ) 15 | 16 | // PublicKeyInfo describes the information of a public key. 17 | type PublicKeyInfo struct { 18 | SourceName string 19 | Type string 20 | PublicKeyAlgorithm x509.PublicKeyAlgorithm 21 | Key interface{} 22 | KeyString string 23 | Option map[string]string 24 | } 25 | 26 | // ExtractPublicKeyFromCertificate extracts a public key from a certificate. 27 | func ExtractPublicKeyFromCertificate(cert *x509.Certificate) (pubKeyInfo PublicKeyInfo, err error) { 28 | sourceName := "Certificate" 29 | switch cert.PublicKeyAlgorithm { 30 | case x509.RSA: 31 | pubKey := cert.PublicKey.(*rsa.PublicKey) 32 | pubKeyInfo = createRSAPublicKeyInfo(sourceName, pubKey) 33 | case x509.ECDSA: 34 | pubKey := cert.PublicKey.(*ecdsa.PublicKey) 35 | pubKeyInfo = createECDSAPublicKeyInfo(sourceName, pubKey) 36 | case x509.Ed25519: 37 | pubKey := cert.PublicKey.(ed25519.PublicKey) 38 | pubKeyInfo = createEd25519PublicKeyInfo(sourceName, pubKey) 39 | default: 40 | err = fmt.Errorf("%s: unknown public key algorithm", sourceName) 41 | } 42 | 43 | return 44 | } 45 | 46 | // ExtractPublicKeyFromPrivateKey extracts a public key from a private key. 47 | func ExtractPublicKeyFromPrivateKey(privKeyInfo PrivateKeyInfo) (pubKeyInfo PublicKeyInfo, err error) { 48 | sourceName := "Private Key" 49 | switch privKeyInfo.PublicKeyAlgorithm { 50 | case x509.RSA: 51 | pubKey := privKeyInfo.Key.(*rsa.PrivateKey).PublicKey 52 | pubKeyInfo = createRSAPublicKeyInfo(sourceName, &pubKey) 53 | case x509.ECDSA: 54 | pubKey := privKeyInfo.Key.(*ecdsa.PrivateKey).PublicKey 55 | pubKeyInfo = createECDSAPublicKeyInfo(sourceName, &pubKey) 56 | case x509.Ed25519: 57 | pubKey := privKeyInfo.Key.(ed25519.PrivateKey).Public().(ed25519.PublicKey) 58 | pubKeyInfo = createEd25519PublicKeyInfo(sourceName, pubKey) 59 | default: 60 | err = fmt.Errorf("%s: unknown public key algorithm", sourceName) 61 | } 62 | 63 | return 64 | } 65 | 66 | func createRSAPublicKeyInfo(sourceName string, pubKey *rsa.PublicKey) PublicKeyInfo { 67 | keyString := EncodeLowerCase2DigitHex(pubKey.N.Bytes()) 68 | // Add a leading 00 if the top bit is set as openssl's print_labeled_bignum(). 69 | if keyString[0] >= '8' { 70 | keyString = "00:" + keyString 71 | } 72 | return PublicKeyInfo{ 73 | SourceName: sourceName, 74 | Type: fmt.Sprintf("RSA Public-Key: (%d bit)", pubKey.Size()*8), 75 | PublicKeyAlgorithm: x509.RSA, 76 | Key: pubKey, 77 | KeyString: keyString, 78 | Option: map[string]string{"Exponent": fmt.Sprintf("%d (0x%x)", pubKey.E, pubKey.E)}, 79 | } 80 | } 81 | 82 | func createECDSAPublicKeyInfo(sourceName string, pubKey *ecdsa.PublicKey) PublicKeyInfo { 83 | prefix := "04:" // Supports only the uncompressed form. See also RFC 5480. 84 | keyString := prefix + EncodeLowerCase2DigitHex(pubKey.X.Bytes()) + 85 | ":" + EncodeLowerCase2DigitHex(pubKey.Y.Bytes()) 86 | return PublicKeyInfo{ 87 | SourceName: sourceName, 88 | Type: fmt.Sprintf("Public-Key: (%d bit)", pubKey.Curve.Params().BitSize), 89 | PublicKeyAlgorithm: x509.ECDSA, 90 | Key: pubKey, 91 | KeyString: keyString, 92 | Option: map[string]string{"NIST CURVE": pubKey.Curve.Params().Name}, 93 | } 94 | } 95 | 96 | func createEd25519PublicKeyInfo(sourceName string, pubKey ed25519.PublicKey) PublicKeyInfo { 97 | return PublicKeyInfo{ 98 | SourceName: sourceName, 99 | Type: "ED25519 Public-Key:", 100 | PublicKeyAlgorithm: x509.Ed25519, 101 | Key: pubKey, 102 | KeyString: EncodeLowerCase2DigitHex(pubKey), 103 | } 104 | } 105 | 106 | // EncodeLowerCase2DigitHex encodes bytes into lower-case two-digit hexadecimal strings separated by a colon. 107 | func EncodeLowerCase2DigitHex(bytes []byte) string { 108 | var hexElements []string 109 | for _, b := range bytes { 110 | hexElements = append(hexElements, fmt.Sprintf("%02x", uint8(b))) 111 | } 112 | return strings.Join(hexElements, ":") 113 | } 114 | 115 | // EncodeUpperCase2DigitHex encodes bytes into upper-case two-digit hexadecimal strings separated by a colon. 116 | func EncodeUpperCase2DigitHex(bytes []byte) string { 117 | var hexElements []string 118 | for _, b := range bytes { 119 | hexElements = append(hexElements, fmt.Sprintf("%02X", uint8(b))) 120 | } 121 | return strings.Join(hexElements, ":") 122 | } 123 | -------------------------------------------------------------------------------- /x509util/publickey_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 HEARTBEATS Corporation. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package x509util_test 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/heartbeatsjp/check-tls-cert/x509util" 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | func TestExtractPublicKey(t *testing.T) { 15 | assert := assert.New(t) 16 | 17 | privKeyFile := "../test/testdata/pki/private/server-a-rsa.pem" 18 | certFile := "../test/testdata/pki/cert/valid/server-a-rsa.pem" 19 | certs, _ := x509util.ParseCertificateFiles(certFile) 20 | pubKeyInfo, _ := x509util.ExtractPublicKeyFromCertificate(certs[0]) 21 | privKeyInfo, _ := x509util.ParsePrivateKeyFile(privKeyFile, nil) 22 | pubKeyInfoInPrivKey, _ := x509util.ExtractPublicKeyFromPrivateKey(privKeyInfo) 23 | assert.NotNil(pubKeyInfoInPrivKey) 24 | assert.NotNil(pubKeyInfo) 25 | assert.Equal("Certificate", pubKeyInfo.SourceName) 26 | assert.Equal("Private Key", pubKeyInfoInPrivKey.SourceName) 27 | pubKeyInfo.SourceName = "" 28 | pubKeyInfoInPrivKey.SourceName = "" 29 | assert.EqualValues(pubKeyInfo, pubKeyInfoInPrivKey) 30 | 31 | privKeyFile = "../test/testdata/pki/private/server-a-ecdsa.pem" 32 | certFile = "../test/testdata/pki/cert/valid/server-a-ecdsa.pem" 33 | certs, _ = x509util.ParseCertificateFiles(certFile) 34 | pubKeyInfo, _ = x509util.ExtractPublicKeyFromCertificate(certs[0]) 35 | privKeyInfo, _ = x509util.ParsePrivateKeyFile(privKeyFile, nil) 36 | pubKeyInfoInPrivKey, _ = x509util.ExtractPublicKeyFromPrivateKey(privKeyInfo) 37 | assert.NotNil(pubKeyInfoInPrivKey) 38 | assert.NotNil(pubKeyInfo) 39 | assert.Equal("Certificate", pubKeyInfo.SourceName) 40 | assert.Equal("Private Key", pubKeyInfoInPrivKey.SourceName) 41 | pubKeyInfo.SourceName = "" 42 | pubKeyInfoInPrivKey.SourceName = "" 43 | assert.EqualValues(pubKeyInfo, pubKeyInfoInPrivKey) 44 | 45 | privKeyFile = "../test/testdata/pki/private/server-a-ed25519.pem" 46 | certFile = "../test/testdata/pki/cert/valid/server-a-ed25519.pem" 47 | certs, _ = x509util.ParseCertificateFiles(certFile) 48 | pubKeyInfo, _ = x509util.ExtractPublicKeyFromCertificate(certs[0]) 49 | privKeyInfo, _ = x509util.ParsePrivateKeyFile(privKeyFile, nil) 50 | pubKeyInfoInPrivKey, _ = x509util.ExtractPublicKeyFromPrivateKey(privKeyInfo) 51 | assert.NotNil(pubKeyInfoInPrivKey) 52 | assert.NotNil(pubKeyInfo) 53 | assert.Equal("Certificate", pubKeyInfo.SourceName) 54 | assert.Equal("Private Key", pubKeyInfoInPrivKey.SourceName) 55 | pubKeyInfo.SourceName = "" 56 | pubKeyInfoInPrivKey.SourceName = "" 57 | assert.EqualValues(pubKeyInfo, pubKeyInfoInPrivKey) 58 | } 59 | 60 | func TestEncodeLowerCase2DigitHex(t *testing.T) { 61 | assert := assert.New(t) 62 | 63 | h := x509util.EncodeLowerCase2DigitHex([]byte("\x01")) 64 | assert.Equal("01", h, "2 digit hex string should match") 65 | 66 | h = x509util.EncodeLowerCase2DigitHex([]byte("\x01\x02")) 67 | assert.Equal("01:02", h, "2 digit hex string should match") 68 | 69 | h = x509util.EncodeLowerCase2DigitHex([]byte("\x01\x02\xff")) 70 | assert.Equal("01:02:ff", h, "2 digit hex string should match") 71 | } 72 | 73 | func TestEncodeUpperCase2DigitHex(t *testing.T) { 74 | assert := assert.New(t) 75 | 76 | h := x509util.EncodeUpperCase2DigitHex([]byte("\x01")) 77 | assert.Equal("01", h, "2 digit hex string should match") 78 | 79 | h = x509util.EncodeUpperCase2DigitHex([]byte("\x01\x02")) 80 | assert.Equal("01:02", h, "2 digit hex string should match") 81 | 82 | h = x509util.EncodeUpperCase2DigitHex([]byte("\x01\x02\xff")) 83 | assert.Equal("01:02:FF", h, "2 digit hex string should match") 84 | } 85 | --------------------------------------------------------------------------------