251 lines
9.3 KiB
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
|
|
}
|