Initial import.
This commit is contained in:
commit
7391da8567
|
@ -0,0 +1,13 @@
|
|||
Copyright (c) 2015 Kyle Isom <kyle@tyrfingr.is>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -0,0 +1,22 @@
|
|||
GOUTILS
|
||||
|
||||
This is a collection of small utility code I've written in Go; the `cmd/`
|
||||
directory has a number of command-line utilities. Rather than keep all
|
||||
of these in superfluous repositories of their own, I'm putting them here.
|
||||
|
||||
Contents:
|
||||
|
||||
die/ Death of a program.
|
||||
cmd/
|
||||
certchain/ Display the certificate chain from a
|
||||
TLS connection.
|
||||
csrpubdump/ Dump the public key from an X.509
|
||||
certificate request.
|
||||
readchain/ Print the common name for the certificates
|
||||
in a bundle.
|
||||
stealchain/ Dump the verified chain from a TLS
|
||||
connection.
|
||||
|
||||
Each program should have a small README in the directory with more information.
|
||||
|
||||
All code here is licensed under the MIT license.
|
|
@ -0,0 +1,19 @@
|
|||
certchain
|
||||
|
||||
This is a utility for printing the X.509 certificate chain from a TLS
|
||||
connection.
|
||||
|
||||
Note: while this will accept more than one server, it will print all
|
||||
of the chains without any indication where one chain ends and the next
|
||||
begins. This was the intended behaviour for the use case, but it may
|
||||
not be applicable in other cases.
|
||||
|
||||
There are no knobs.
|
||||
|
||||
Examples:
|
||||
$ certchain www.kyleisom.net
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFUTCCBDmgAwIBAgIQaaTVw0yZFGAYvFDKAIo4BzANBgkqhkiG9w0BAQsFADCB
|
||||
kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
|
||||
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV
|
||||
...
|
|
@ -0,0 +1,39 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/kisom/goutils/die"
|
||||
)
|
||||
|
||||
var hasPort = regexp.MustCompile(`:\d+$`)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
for _, server := range flag.Args() {
|
||||
if !hasPort.MatchString(server) {
|
||||
server += ":443"
|
||||
}
|
||||
|
||||
var chain string
|
||||
|
||||
conn, err := tls.Dial("tcp", server, nil)
|
||||
die.If(err)
|
||||
|
||||
details := conn.ConnectionState()
|
||||
for _, cert := range details.PeerCertificates {
|
||||
p := pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
chain += string(pem.EncodeToMemory(&p))
|
||||
}
|
||||
|
||||
fmt.Println(chain)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
csrpubdump
|
||||
|
||||
This is a small utility to dump the public key from an X.509 certificate
|
||||
signature request (CSR) to a standard RFC 5280 PKIX public key format.
|
||||
|
||||
There are no command line flags; it accepts a number of PEM- or
|
||||
DER-enoded CSRs and outputs a public key of the same name as the CSR
|
||||
with the suffix ".pub" appended.
|
||||
|
||||
Example:
|
||||
|
||||
$ csrpubdump cert.csr
|
||||
[+] wrote cert.csr.pub.
|
||||
$ openssl req -text -in cert.csr -modulus | grep ^Modulus
|
||||
Modulus=C7021819792D3ADE906156868B6475B67E475325A1AAD6C50BFD8CFE007A4B7C50E89CCA91EF14EEB13AD4B01E8FABDF6884AA74B9CAFFF4D4FD8C26ECAA9DD9DC4D232C3A54FFEE7EBB4CCD34BB4D4AFFD73FB2880A10A8E5CA99533FBC85746FDC3AEFFDA8A6FF25A95DDB010B15813AC6AD910C5CB1CA264E07783B67B1716B977A69D7C647067336D50BE3FF2CF8BCA2A9DC3D2357E441DEB4E29A1914DD30AD0B3895F8564D47E0D2B1EE879C2018A3F75736696EDF056F5BCD8DF6C7B688711B63C253A272F837356D27D4CD67109DE9E9F39F16E05F33EE9179C9B767151DF5DC78E8B2A5E71B6F33213ACE69D3131DA27ACCE86011A7D43965CECE33687C50456B622E0804FE213458D6D0BF82AA711B01FFCAE54DD7D046F14A67D3E1C089EDA62821DF48100A4FF5DEE2E98F79AC526C8A96B16F1C93E7776F8A2BF5166FE5C651713DE88A426DF92406EBDA56E0E01B6FE001B2CFCD22EAE2EB3D1EEC311E20BE739B2489A9DB581DD35837BFBEBFDC4136C2F822C53A204CB7F9
|
||||
$ openssl rsa -pubin -text -in cert.csr.pub -modulus | grep ^Modulus
|
||||
Modulus=C7021819792D3ADE906156868B6475B67E475325A1AAD6C50BFD8CFE007A4B7C50E89CCA91EF14EEB13AD4B01E8FABDF6884AA74B9CAFFF4D4FD8C26ECAA9DD9DC4D232C3A54FFEE7EBB4CCD34BB4D4AFFD73FB2880A10A8E5CA99533FBC85746FDC3AEFFDA8A6FF25A95DDB010B15813AC6AD910C5CB1CA264E07783B67B1716B977A69D7C647067336D50BE3FF2CF8BCA2A9DC3D2357E441DEB4E29A1914DD30AD0B3895F8564D47E0D2B1EE879C2018A3F75736696EDF056F5BCD8DF6C7B688711B63C253A272F837356D27D4CD67109DE9E9F39F16E05F33EE9179C9B767151DF5DC78E8B2A5E71B6F33213ACE69D3131DA27ACCE86011A7D43965CECE33687C50456B622E0804FE213458D6D0BF82AA711B01FFCAE54DD7D046F14A67D3E1C089EDA62821DF48100A4FF5DEE2E98F79AC526C8A96B16F1C93E7776F8A2BF5166FE5C651713DE88A426DF92406EBDA56E0E01B6FE001B2CFCD22EAE2EB3D1EEC311E20BE739B2489A9DB581DD35837BFBEBFDC4136C2F822C53A204CB7F9
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/kisom/die"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
for _, fileName := range flag.Args() {
|
||||
in, err := ioutil.ReadFile(fileName)
|
||||
die.If(err)
|
||||
|
||||
if p, _ := pem.Decode(in); p != nil {
|
||||
if p.Type != "CERTIFICATE REQUEST" {
|
||||
log.Fatal("INVALID FILE TYPE")
|
||||
}
|
||||
in = p.Bytes
|
||||
}
|
||||
|
||||
csr, err := x509.ParseCertificateRequest(in)
|
||||
die.If(err)
|
||||
|
||||
out, err := x509.MarshalPKIXPublicKey(csr.PublicKey)
|
||||
die.If(err)
|
||||
|
||||
var t string
|
||||
switch pub := csr.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
t = "RSA PUBLIC KEY"
|
||||
case *ecdsa.PublicKey:
|
||||
t = "EC PUBLIC KEY"
|
||||
default:
|
||||
die.With("unrecognised public key type %T", pub)
|
||||
}
|
||||
|
||||
p := &pem.Block{
|
||||
Type: t,
|
||||
Bytes: out,
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(fileName+".pub", pem.EncodeToMemory(p), 0644)
|
||||
die.If(err)
|
||||
fmt.Printf("[+] wrote %s.\n", fileName+".pub")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
readchain
|
||||
|
||||
This is a small utility to read a chain of PEM-encoded X.509 certificates
|
||||
and print their common names. It was written to quickly see what certificates
|
||||
were in a bundle.
|
||||
|
||||
It is called with the files containing chains to read passed in as an
|
||||
argument. The program has no knobs or widgets to adjust.
|
||||
|
||||
Examples:
|
||||
|
||||
$ readchain google.com.pem microsoft.com.pem
|
||||
[+] google.com.pem:
|
||||
*.google.com
|
||||
Google Internet Authority G2
|
||||
GeoTrust Global CA
|
||||
[+] microsoft.com.pem:
|
||||
microsoft.com
|
||||
MSIT Machine Auth CA 2
|
||||
Microsoft Internet Authority
|
|
@ -0,0 +1,40 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
for _, fileName := range flag.Args() {
|
||||
data, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[!] %s: %v\n", fileName, err)
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("[+] %s:\n", fileName)
|
||||
rest := data[:]
|
||||
for {
|
||||
var p *pem.Block
|
||||
p, rest = pem.Decode(rest)
|
||||
if p == nil {
|
||||
break
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(p.Bytes)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[!] %s: %v\n", fileName, err)
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Printf("\t%+v\n", cert.Subject.CommonName)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
stealchain
|
||||
|
||||
This is a utility to extract the verified X.509 chain from a TLS
|
||||
connection. It takes a list of sites on the command line; for each
|
||||
site that it can connect to, it will dump the certificates that the
|
||||
peer actually sent (and not the verified chain that is built from
|
||||
this).
|
||||
|
||||
It was written to assist in debugging issues with certificate chains.
|
||||
|
||||
There are a few knobs:
|
||||
|
||||
-ca allows the trusted CA roots to be specified via a PEM bundle of
|
||||
root certificates.
|
||||
|
||||
-sni specifies the server name for SNI. This applies to all hosts in
|
||||
the run; if this is run as
|
||||
|
||||
$ stealchain -sni foo.com foo.com bar.com
|
||||
|
||||
it will attempt to use "foo.com" as the server name for both hosts.
|
||||
|
||||
-noverify skips certificate verification. This might be useful for seeing
|
||||
what certificates a server is actually sending.
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
$ stealchain kyleisom.net
|
||||
[+] wrote kyleisom.net.pem.
|
||||
$ readchain kyleisom.net.pem
|
||||
[+] kyleisom.net.pem:
|
||||
*.kyleisom.net
|
||||
COMODO RSA Domain Validation Secure Server CA
|
||||
|
||||
$ stealchain google.com microsoft.com apple.com amazon.com
|
||||
[+] wrote google.com.pem.
|
||||
[+] wrote microsoft.com.pem.
|
||||
[+] wrote apple.com.pem.
|
||||
[+] wrote amazon.com.pem.
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/kisom/goutils/die"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var cfg = &tls.Config{}
|
||||
|
||||
var sysRoot, serverName string
|
||||
flag.StringVar(&sysRoot, "ca", "", "provide an alternate CA bundle")
|
||||
flag.StringVar(&cfg.ServerName, "sni", cfg.ServerName, "provide an SNI name")
|
||||
flag.BoolVar(&cfg.InsecureSkipVerify, "noverify", false, "don't verify certificates")
|
||||
flag.Parse()
|
||||
|
||||
if sysRoot != "" {
|
||||
pemList, err := ioutil.ReadFile(sysRoot)
|
||||
die.If(err)
|
||||
|
||||
roots := x509.NewCertPool()
|
||||
if !roots.AppendCertsFromPEM(pemList) {
|
||||
fmt.Printf("[!] no valid roots found")
|
||||
roots = nil
|
||||
}
|
||||
|
||||
cfg.RootCAs = roots
|
||||
}
|
||||
|
||||
if serverName != "" {
|
||||
cfg.ServerName = serverName
|
||||
}
|
||||
|
||||
for _, site := range flag.Args() {
|
||||
conn, err := tls.Dial("tcp", site+":443", cfg)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cs := conn.ConnectionState()
|
||||
var chain []byte
|
||||
|
||||
for _, cert := range cs.PeerCertificates {
|
||||
p := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
chain = append(chain, pem.EncodeToMemory(p)...)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(site+".pem", chain, 0644)
|
||||
die.If(err)
|
||||
fmt.Printf("[+] wrote %s.pem.\n", site)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
Simple fatal utilities for Go programs.
|
||||
|
||||
```
|
||||
result, err := doSomething()
|
||||
die.If(err)
|
||||
|
||||
ok := processResult(result)
|
||||
if !ok {
|
||||
die.With("failed to process result %s", result.Name)
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Package die contains utilities for fatal error handling.
|
||||
package die
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// If prints the error to stderr and exits if err != nil.
|
||||
func If(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[!] %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// With prints the message to stderr, appending a newline, and exits.
|
||||
func With(fstr string, args ...interface{}) {
|
||||
out := fmt.Sprintf("[!] %s\n", fstr)
|
||||
fmt.Fprintf(os.Stderr, out, args...)
|
||||
os.Exit(1)
|
||||
}
|
Loading…
Reference in New Issue