mitm/cert_utils.go

251 lines
9.3 KiB
Go

package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/pem"
"fmt"
"math/big"
"net"
"strings"
"time"
"software.sslmate.com/src/go-pkcs12"
)
// Hardcoded certificate data - users need to replace these placeholders with actual certificate data
const (
// Base64 encoded data of P12 certificate - users need to replace with actual cert.p12 file content
hardcodedP12Data = `-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
`
// PEM format data of CA certificate - users need to replace with actual CA.crt file content
hardcodedCACert = `-----BEGIN CERTIFICATE-----
MIIDOTCCAiECFD7rRtWb2t27PCZVuQJmuY6owrI0MA0GCSqGSIb3DQEBCwUAMFkx
CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJTSDELMAkGA1UEBwwCU0gxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDENMAsGA1UEAwwETUlUTTAeFw0yNTEx
MDIxMTQ0NTVaFw0zNTEwMzExMTQ0NTVaMFkxCzAJBgNVBAYTAkNOMQswCQYDVQQI
DAJTSDELMAkGA1UEBwwCU0gxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5
IEx0ZDENMAsGA1UEAwwETUlUTTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALoEwz9kS6HVq2TLWYUx/nZtR9riUe1jximA/zqSTEyUNlx0teS5pjNQIMV4
fYfDCY0XCSaeqM0psNcSXPW+i3kRaOaMb8eGDC6fFPEIrW8j3YP7q7pxZP9OxVHK
6ExCXp4cQaV9aWgDBp5VQOI4DRRWnDOejN5OCgM7BtsRaULYqu6RZXI0+m/RRFn0
7CRk9JfOb9Sp7qScQd3XiGV+sFN9HHW+IMEgYxlbv+Xh1JBJLPvrsYNmb8HIHOeB
pT1jneVyjjwrCdAzv2g/jJj5X9m8y7mq+z/9aR5tiRddzcLFX7M3lkaZXz4No/EW
MmqyWDZ3Z1+0kICv9KVu9g5B0n8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAETdb
oFes544yy3DGvpGbRbDTcCTSBceNglyAYOLuRvUAJMoica+xeN9oTrymDX7prirM
B0yIJIdBGNMsmlCV0rxzXAc3TsqFaNsQULFynpLLwCjS21wt0dY5ifn9R2cbk3Kr
i2Pye++CuzQXgLNpyMs52USUoZC/4Yn6kEwtJ80rnTSnnpdwIm2+IKauNj2cqjk/
M7Zmpe8q3/393VTypxGT/pT/sTqyYlfQBxMDjUceWCC4suFY/PxL9wgahhXknjAd
WgKzQq/PcMdqvNpQLQd2nRLbiJCzz2IC/ivYB0+OakcDbRQ7kcxrO2eWJK+Wliz1
XzFo0MZnM+Qp7Srm6Q==
-----END CERTIFICATE-----`
// P12 certificate password - users need to modify to actual password
hardcodedP12Password = "Admin!23"
)
// loadHardcodedCertificate loads hardcoded P12 certificate
func loadHardcodedCertificate() (*tls.Config, error) {
// If hardcoded data is empty or placeholder, generate self-signed certificate
if len(hardcodedP12Data) < 100 {
fmt.Println("Warning: No valid P12 certificate data provided, generating self-signed certificate for testing")
return generateSelfSignedCert()
}
// Decode base64 data
p12Data, err := decodeBase64String(hardcodedP12Data)
if err != nil {
fmt.Printf("Warning: Unable to decode P12 data (%v), generating self-signed certificate\n", err)
return generateSelfSignedCert()
}
// Parse P12 data
privateKey, cert, caCerts, err := pkcs12.DecodeChain(p12Data, hardcodedP12Password)
if err != nil {
fmt.Printf("Warning: Unable to parse P12 certificate (%v), generating self-signed certificate\n", err)
return generateSelfSignedCert()
}
// Create certificate chain
certificates := []tls.Certificate{
{
Certificate: [][]byte{cert.Raw},
PrivateKey: privateKey,
},
}
// Create CA certificate pool
caCertPool := x509.NewCertPool()
for _, caCert := range caCerts {
caCertPool.AddCert(caCert)
}
// If there's a hardcoded CA certificate, add it to the pool
if len(hardcodedCACert) > 100 {
block, _ := pem.Decode([]byte(hardcodedCACert))
if block != nil {
if caCert, err := x509.ParseCertificate(block.Bytes); err == nil {
caCertPool.AddCert(caCert)
}
}
}
return &tls.Config{
Certificates: certificates,
RootCAs: caCertPool,
InsecureSkipVerify: true,
}, nil
}
// decodeBase64String decodes base64 string, ignoring whitespace and comments
func decodeBase64String(data string) ([]byte, error) {
// Remove comment lines and whitespace
var cleanData strings.Builder
lines := strings.SplitSeq(data, "\n")
for line := range lines {
line = strings.TrimSpace(line)
if len(line) > 0 && !strings.HasPrefix(line, "--") {
cleanData.WriteString(line)
}
}
if cleanData.Len() == 0 {
return nil, fmt.Errorf("no valid base64 data")
}
// Use standard base64 decoding
return base64.StdEncoding.DecodeString(cleanData.String())
}
// generateSelfSignedCert generates self-signed certificate for testing
func generateSelfSignedCert() (*tls.Config, error) {
// Generate private key
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, err
}
// Create certificate template
template := x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
Organization: []string{"MITM Proxy"},
OrganizationalUnit: []string{"MITM Proxy CA"},
Country: []string{"US"},
Province: []string{""},
Locality: []string{""},
StreetAddress: []string{""},
PostalCode: []string{""},
CommonName: "MITM Proxy Root CA",
},
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
// Proper key usage for CA certificate
KeyUsage: x509.KeyUsageKeyEncipherment |
x509.KeyUsageDigitalSignature |
x509.KeyUsageCertSign |
x509.KeyUsageCRLSign,
// Extended key usage for server authentication
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
},
BasicConstraintsValid: true,
IsCA: true,
MaxPathLen: 0,
MaxPathLenZero: true,
// Add Subject Alternative Names for flexibility
DNSNames: []string{
"localhost",
"*.localhost",
"127.0.0.1",
},
IPAddresses: []net.IP{
net.IPv4(127, 0, 0, 1),
net.IPv6loopback,
},
}
// Generate certificate
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey)
if err != nil {
return nil, err
}
// Create TLS certificate
cert := tls.Certificate{
Certificate: [][]byte{certDER},
PrivateKey: privateKey,
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: true,
}, nil
}
// getHardcodedCACert returns hardcoded CA certificate
func getHardcodedCACert() string {
return hardcodedCACert
}