Files
Ronni Skansing 07c8adaf76 update vendor deps
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
2025-11-06 23:31:08 +01:00

91 lines
2.9 KiB
Go

package surf
import (
"bytes"
"crypto/sha256"
"crypto/tls"
"encoding/hex"
"errors"
"fmt"
)
// TLSData represents information about a TLS certificate.
type TLSData struct {
ExtensionServerName string // Server name extension of the TLS certificate.
FingerprintSHA256 string // SHA-256 fingerprint of the certificate.
FingerprintSHA256OpenSSL string // SHA-256 fingerprint compatible with OpenSSL.
TLSVersion string // TLS version used.
CommonName []string // List of common names associated with the certificate.
DNSNames []string // List of DNS names associated with the certificate.
Emails []string // List of email addresses associated with the certificate.
IssuerCommonName []string // List of common names of the certificate issuer.
IssuerOrg []string // List of organizations of the certificate issuer.
Organization []string // List of organizations associated with the certificate.
}
// tlsGrabber takes a TLS connection state and returns a tlsData struct containing information
// about the TLS connection.
func tlsGrabber(cs *tls.ConnectionState) *TLSData {
var td TLSData
if cs != nil {
cert := cs.PeerCertificates[0]
td.DNSNames = append(td.DNSNames, cert.DNSNames...)
td.Emails = append(td.Emails, cert.EmailAddresses...)
td.CommonName = append(td.CommonName, cert.Subject.CommonName)
td.Organization = append(td.Organization, cert.Subject.Organization...)
td.IssuerOrg = append(td.IssuerOrg, cert.Issuer.Organization...)
td.IssuerCommonName = append(td.IssuerCommonName, cert.Issuer.CommonName)
td.ExtensionServerName = cs.ServerName
tlsVersionStringMap := map[uint16]string{
0x0300: "SSL30",
0x0301: "TLS10",
0x0302: "TLS11",
0x0303: "TLS12",
0x0304: "TLS13",
}
if version, ok := tlsVersionStringMap[cs.Version]; ok {
td.TLSVersion = version
}
if fingerprintSHA256, err := calculateFingerprints(cs); err == nil {
td.FingerprintSHA256 = hex.EncodeToString(fingerprintSHA256)
td.FingerprintSHA256OpenSSL = openSSL(fingerprintSHA256)
}
}
return &td
}
// calculateFingerprints takes a TLS connection state and returns the SHA256 fingerprint
// of the first certificate in the chain or an error if no certificates are found.
func calculateFingerprints(c *tls.ConnectionState) ([]byte, error) {
if len(c.PeerCertificates) == 0 {
err := errors.New("no certificates found")
return nil, err
}
cert := c.PeerCertificates[0]
dataSHA256 := sha256.Sum256(cert.Raw)
fingerprintSHA256 := dataSHA256[:]
return fingerprintSHA256, nil
}
// openSSL takes a byte slice of a fingerprint and returns a string representation in the OpenSSL
// format.
func openSSL(fpBytes []byte) string {
var buf bytes.Buffer
for i, f := range fpBytes {
if i > 0 {
_, _ = fmt.Fprintf(&buf, ":")
}
_, _ = fmt.Fprintf(&buf, "%02X", f)
}
return buf.String()
}