square / certigo Goto Github PK
View Code? Open in Web Editor NEWA utility to examine and validate certificates in a variety of formats
License: Apache License 2.0
A utility to examine and validate certificates in a variety of formats
License: Apache License 2.0
We currently print PEM headers when the --pem
flag is passed with extra information, e.g. the friendly name of an entry in a PKCS12 keystore. However, OpenSSL can't handle these and will refuse to parse them. We should consider scrubbing headers on PEM output.
Right now, a root appears as something like this:
Serial: 927650371
Valid: 1999-05-25 16:09 UTC to 2019-05-25 16:39 UTC
Signature: SHA1-RSA (self-signed)
Subject Info:
Country: US
Organization: Entrust.net
Organizational Unit: www.entrust.net/CPS incorp. by ref. (limits liab.)
Organizational Unit: (c) 1999 Entrust.net Limited
CommonName: Entrust.net Secure Server Certification Authority
Issuer Info:
Country: US
Organization: Entrust.net
Organizational Unit: www.entrust.net/CPS incorp. by ref. (limits liab.)
Organizational Unit: (c) 1999 Entrust.net Limited
CommonName: Entrust.net Secure Server Certification Authority
Subject Key ID: F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
Authority Key ID: F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
Basic Constraints: CA:true
Key Usage:
Cert Sign
CRL Sign
Warnings:
Size of RSA key should be at least 2048 bits
Signed with SHA1-RSA, which is an outdated signature algorithm
We print (self-signed) next to the signature if it's self-signed.
However, we still print an issuer, repeating all the information from the subject, which since it's self-signed must be the same.
In non-verbose mode, we don't print anything at all indicating it's self-signed.
I propose we change the Issuer Info: field to say something like:
Issuer Info:
Self-signed
when the certificate is self-signed, in both verbose and non-verbose modes.
No changes to JSON are needed, as it always has a "is_self_signed": true,
field, though we could omit the issuer information in that case, but there's no real need to change that.
We often store keys and certificates in PEM format in a single file. We should show a warning if the key does not match the cert.
Certigo should output what format the tool guessed. It can help when debugging issues with other tools and/or with certigo itself.
We assume they're .pem today
Many java trust stores are "protected" with the default password changeit. Password protection often provides little value when the files are protected, perhaps in a secrets management system.
Other passwords I have seen from a github search for "keytool storepass" and we could guess:
changeit
changeme
keystore
CHANGE
ponies
ez24get
storepass
Storepass
password
passphrase
secret
123456
The jceks
package can currently only read RSA keys. We should update it to also support EC keys.
It would be nice if the dump
command would also understand PEM-formatted certificate revocation lists (CRLs).
The illustration and reproduction:
$ certigo connect www.google.com:https
panic: runtime error: index out of range [1] with length 1
goroutine 1 [running]:
github.com/square/certigo/lib.explainCipher(0xc00035e3e0, 0xc, 0xc00035e3e0, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/homes/hawklords/cks/go/src/github.com/square/certigo/lib/tls.go:182 +0x1e3
github.com/square/certigo/lib.EncodeTLSInfoToText(0xc0001222c0, 0x0, 0x2, 0x0)
/homes/hawklords/cks/go/src/github.com/square/certigo/lib/tls.go:62 +0x148
main.main()
/homes/hawklords/cks/go/src/github.com/square/certigo/main.go:162 +0x667
The problem is that explainCipher() has a hard-coded list of ciphers and it assumes that this list covers all ciphers that Go's TLS code can ever use. In Go tip, the list of supported TLS ciphers has expanded (to include TLS 1.3 ciphers, such as TLS_AES_128_GCM_SHA256, which is what I believe is being negociated here), but the cipher is not in the list and so explainCipher winds up trying to slice up a null string and creating a bad index.
One fix would be to add the new Go supported ciphers to the list. This is a bit tricky, since their tls. values are not defined in current released Go versions, so they would have to be added by explicit hex value with comments. Another would be to make explainCipher cope (somehow) with ciphers not in the cipherSuites map.
(I believe that there is probably a similar issue with the tlsVersions map, which currently doesn't include TLS 1.3.)
The build issue might be dealt with by pulling both tlsVersions and cipherSuites out into multiple separate files, each built only on Go versions with the necessary constants defined.
(It is a real pity that crypto/tls does not export any name mapping information in its public API, because it sticks programs and code like this with a tough job and a tough set of tradeoffs. But I assume that the Go authors have their reasons.)
Is there a way to verify a cert chain if the site is sitting behind some sort of LB that is using SNI or is doing a redirect?
Two examples, heise.de and oglaf.com.
certigo connect heise.de:443
** TLS Connection **
Version: TLS 1.2
Cipher Suite: ECDHE_RSA key exchange, AES_128_GCM_SHA256 cipher
** CERTIFICATE 1 **
Valid: 2017-10-08 21:20 UTC to 2018-01-06 21:20 UTC
Subject: CN=redirector.heise.de
Issuer: CN=Let's Encrypt Authority X3
DNS Names:
redirector.heise.de
** CERTIFICATE 2 **
Valid: 2016-03-17 16:40 UTC to 2021-03-17 16:40 UTC
Subject: CN=Let's Encrypt Authority X3
Issuer: CN=DST Root CA X3
Failed to verify certificate chain:
x509: certificate is valid for redirector.heise.de, not heise.de
certigo connect oglaf.com:443
** TLS Connection **
Version: TLS 1.2
Cipher Suite: ECDHE_RSA key exchange, AES_128_GCM_SHA256 cipher
** CERTIFICATE 1 **
Valid: 2015-08-11 18:24 UTC to 2025-08-08 18:24 UTC
Subject: CN=sni.dreamhost.com
Issuer: CN=sni.dreamhost.com
Warnings:
Certificate doesn't have any valid DNS/URI names or IP addresses set
Failed to verify certificate chain:
x509: certificate is valid for sni.dreamhost.com, not oglaf.com
Should also show IP subject alt names (not just DNS), and email addresses attached to a certificate.
One thing I've been using certigo
for is to validate that our systems have proper SSL certificates installed (since we're using an internal CA). The "problem" is that certigo connect
will show whether there are issues with the certificate, but it exits with a 0
regardless.
For instance:
$ certigo connect --name xxx github.com:443
** TLS Connection **
.....
Failed to verify certificate chain:
x509: certificate is valid for github.com, www.github.com, not xxx
$ echo $?
0
vs
$ certigo connect --pem github.com:443 | certigo verify --name xxx
Failed to verify certificate chain:
x509: certificate is valid for github.com, www.github.com, not xxx
$ echo $?
1
It would be useful for connect
to have an option like --verify
that fails if the certificate is invalid.
Add support for reading JCEKS key stores (in addition to PKCS12).
Bouncycastle key store
I hear Android uses them.
We should show a warning if we encounter a certificate that is using a key that's too small (e.g. 1024-bit for RSA keys, or 160-bit for ECC keys).
./certigo dump < certs/certWithPassword.p12
with an incorrect password simply exits. We should show an error message, similar to when handling jceks files.
We should vendor/pin our dependencies using a vendor management tool, such as glide.
It would be nice if the dump
command would also understand PEM-formatted certificate signing requests (CSRs) instead of just certificates.
Today, we dump all built trust chains.
That could be improved in a few ways:
see also https://letsencrypt.org/2018/04/04/sct-encoding.html for some nice details
$ go get -u github.com/square/certigo
# github.com/square/certigo/lib
/home/anybody/go/src/github.com/square/certigo/lib/tls.go:164:2: undefined: tls.VersionTLS13
It seems users currently have to guess (or look at the source code) to figure out the set of valid formats.
We should improve the output of certigo dump --help
. We could also list all the valid formats when an invalid one is provided (currently, we only return unknown file type: xyz
).
Once we have unit/integration tests, we should set up travis-ci.org for automated testing. Depends on issue #19. Also neat: coveralls for code coverage information.
The documentation indicates that certigo supports both JKS and JCEKS keystore files, but it appears to only support JCEKS files:
scapeless:jkstest elyscape$ keytool -genkeypair -keystore keystore.jks -storepass password -keypass password -alias selfsigned -keyalg RSA -keysize 2048 -validity 365 -dname CN=selfsigned
scapeless:jkstest elyscape$ certigo dump keystore.jks -p password
scapeless:jkstest elyscape$ certigo dump keystore.jks -p password -j
{"certificates":[]}
scapeless:jkstest elyscape$ keytool -list -keystore keystore.jks -storepass password
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
selfsigned, Mar 15, 2017, PrivateKeyEntry,
Certificate fingerprint (SHA1): F5:38:97:C4:D9:78:7C:0D:A8:12:1A:7E:C8:EE:28:3C:5F:22:5A:CB
By contrast, if I convert the same keystore into a JCEKS file:
scapeless:jkstest elyscape$ keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.jceks -deststoretype JCEKS -srcstorepass password -deststorepass password
Entry for alias selfsigned successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
scapeless:jkstest elyscape$ certigo dump keystore.jceks -p password
** CERTIFICATE 1 **
Valid: 2017-03-15 18:29 UTC to 2018-03-15 18:29 UTC
Subject: CN=selfsigned
Issuer: CN=selfsigned
I created the keystore files using the version of keytool
provided with Java 1.8u112:
scapeless:jkstest elyscape$ java -version
java version "1.8.0_112"
Java(TM) SE Runtime Environment (build 1.8.0_112-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode)
If you want to test with the keystore files I generated here, I've attached them in this zip file.
Should show X.509v3 key usage and extended key usage (if present) for a certificate.
certigo connect
is awesome for providing detailed information about the TLS certificate and certificate chain actively being used by a service. But sometimes displaying all that information is overkill, and what I really want to know is basic information about the certificate, the certificate chain, and the validity of the whole chain. So, this is a feature request for some sort of 'terse' flag for at least certigo connect
that would produce terser output. If this is a feature that would be accepted for certigo, I'd be happy to see if I can do at least a preliminary implementation.
What should be included in terse output is certainly an open question. What I think I would find most useful is:
A more feature-rich 'terse output' implementation might provide additional options to control some of these, but that might be best done in separate enhancements.
Should show basic constraints for a cert (CA true/false, pathlen, name constraints).
Right now, the output is a bit confusing if a file contains multiple certificates.
For example:
$ ./certigo dump --format PEM certs/cert.pem
Not Before: 2016-05-27 21:15:31 +0000 UTC
Not After : 2017-10-09 21:15:31 +0000 UTC
Signature algorithm: SHA1-RSA
Subject Info:
CommonName: ApertureScience
Organization: [Aperture Science]
OrganizationalUnit: [Research and Development]
Country: [US]
Locality: [San Francisco]
Issuer Info:
CommonName: ApertureScience
Organization: [Aperture Science]
OrganizationalUnit: [Research and Development]
Country: [US]
Locality: [San Francisco]
Subject Key ID :
Authority Key ID:
Alternate DNS Names: []
Serial Number: 11578389349061131131
Not Before: 2016-05-27 21:15:31 +0000 UTC
Not After : 2017-10-09 21:15:31 +0000 UTC
Signature algorithm: SHA1-RSA
Subject Info:
CommonName: ApertureScience
Organization: [Aperture Science]
OrganizationalUnit: [Research and Development]
Country: [US]
Locality: [San Francisco]
Issuer Info:
CommonName: ApertureScience
Organization: [Aperture Science]
OrganizationalUnit: [Research and Development]
Country: [US]
Locality: [San Francisco]
Subject Key ID :
Authority Key ID:
Alternate DNS Names: []
Serial Number: 11578389349061131131
It's not clear at first sight that those are two certificates in one file.
Some certificate validation libraries will have problems if certificates appear more than once in a bundle; it would be great if certigo could detect when there were multiple copies of a certificate in a bundle.
Hide empty fields in dump output, e.g. empty subject fields or missing key idents:
Subject Info:
CommonName: *.google.com
Organization: [Google Inc]
OrganizationalUnit: []
Country: [US]
Locality: [Mountain View]
Organizational unit doesn't need to be in the output if it's empty.
Subject Key ID :
Authority Key ID:
If key idents are missing we can elide the output.
It can be useful to diagnose connectivity problems.
We could then alert if trust status is different in various bundles.
EG: a warning like not trusted in Windows XP, Centos 6; trusted by Windows 10, Centos 7, Apple
% certigo verify --name=REDACTED -f pem server2019.csr
panic: runtime error: index out of range
goroutine 1 [running]:
github.com/square/certigo/lib.VerifyChain(0xc62e38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7ffc75d487a2, 0x18, 0x0, 0x0, ...)
/home/meta/go/src/github.com/square/certigo/lib/verify.go:129 +0x8e3
main.main()
/home/meta/go/src/github.com/square/certigo/main.go:183 +0x1033
Currently, dump
only supports files, can't read from stdin. Should also support reading from stdin.
It would be nice if dump & connect would indicate if a certificate is an Extended Validation certificate.
Improve output for certs with a lot of subject alt names.
For example, this is what google.com's current cert shows (note the many SANs):
$ ./certigo dump certs/google.com.pem
Enable Date: 2016-05-25 15:03:23 +0000 UTC
Expiry Date: 2016-08-17 14:42:00 +0000 UTC
Algorithm Type: SHA256-RSA
Subject Info:
CommonName: *.google.com
Organization: [Google Inc]
OrganizationalUnit: []
Country: [US]
Locality: [Mountain View]
Issuer Info:
CommonName: Google Internet Authority G2
Organization: [Google Inc]
OrganizationalUnit: []
Country: [US]
Locality: []
Subject Key ID : 7C:D4:C5:48:38:F5:22:2C:4B:20:AA:B1:BD:A1:08:CA:B6:4B:6E:3C
Authority Key ID: 4A:DD:06:16:1B:BC:F6:68:B5:76:F5:81:B6:BB:62:1A:BA:5A:81:2F
Alternate DNS Names: [*.google.com *.android.com *.appengine.google.com *.cloud.google.com *.google-analytics.com *.google.ca *.google.cl *.google.co.in *.google.co.jp *.google.co.uk *.google.com.ar *.google.com.au *.google.com.br *.google.com.co *.google.com.mx *.google.com.tr *.google.com.vn *.google.de *.google.es *.google.fr *.google.hu *.google.it *.google.nl *.google.pl *.google.pt *.googleadapis.com *.googleapis.cn *.googlecommerce.com *.googlevideo.com *.gstatic.cn *.gstatic.com *.gvt1.com *.gvt2.com *.metric.gstatic.com *.urchin.com *.url.google.com *.youtube-nocookie.com *.youtube.com *.youtubeeducation.com *.ytimg.com android.clients.google.com android.com g.co goo.gl google-analytics.com google.com googlecommerce.com urchin.com www.goo.gl youtu.be youtube.com youtubeeducation.com]
Serial Number: 9101476628582717928
❯❯❯ certigo connect <redacted>
panic: runtime error: index out of range [1] with length 1
goroutine 1 [running]:
github.com/square/certigo/lib.explainCipher(0xc00002a960, 0xc, 0xc00002a960, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/private/tmp/certigo-20200106-25422-1jnrsi9/certigo-1.11.0/lib/tls.go:182 +0x1e3
github.com/square/certigo/lib.EncodeTLSInfoToText(0xc0001a80b0, 0x0, 0x5, 0x0)
/private/tmp/certigo-20200106-25422-1jnrsi9/certigo-1.11.0/lib/tls.go:62 +0x148
main.main()
/private/tmp/certigo-20200106-25422-1jnrsi9/certigo-1.11.0/main.go:162 +0x667
This happened on a new AWS Classic LB, haven't been able to consistently reproduce.
The server can say what acceptable client certs authorities are.
We could print that information in the TLS section.
We could use the interface here to record that information golang/go@81038d2
Consider adding automated unit/integration tests.
Go has a built-in unit test framework: https://golang.org/pkg/testing.
For integration tests, cram (https://bitheap.org/cram) works nicely for CLI utils.
Should support dumping raw certificates that are in binary (i.e., not PEM-encoded).
Here's a list of STARTTLS type protocols I've found:
Many of these are simple text protocols, and we can probably get away with a very simple client that talks just enough to get to the STARTTLS.
Certificates should be in X.509 version 3 format. We should print a warning if we encounter a certificate that is in an old format (X.509 versions 1 or 2). Note that the "version" tag in the certificate is zero-indexed, i.e. 0/1/2.
Go can't process BER input, only DER. Would be nice to have a preprocessing step that canonicalizes any BER into DER.
$ certigo verify --name=aaaa.xxx.kube --ca=ca.crt xxx.xxx.tld.cer
Certificate has OCSP extension, but was unable to check status:
asn1: syntax error: sequence truncated
Found 1 valid certificate chain(s):
[0] CN=xxx.xxx.tld => CN=XXX-Device-CA
did we step on this? golang/go#12910
...shall be solved by:
ideas?
Should show the serial number of a certificate when dumping output.
Print unknown extensions, if there are any.
We should print a warning if we encounter a cert that is using an outdated signing algorithm such as MD-5 or SHA-1.
The Go net/smtp package that certigo's starttls.GetConnectionState uses defaults to EHLO'ing with the name localhost
. Unfortunately not all SMTP servers accept this EHLO name; since it's frequently abused by bad clients, it's also frequently rejected, which hampers using certigo connect -t smtp ...
to obtain TLS certificate information from various SMTP servers.
The official way to supply a non-localhost name is to explicitly call smtp.Hello()
immediately after connecting (before you do anything else). Probably the simplest approach here is to add an extra command line argument to specify the EHLO name to use, since this avoids the morass of trying to automatically determine a plausible host name for the connection.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.