269 lines
11 KiB
Go
269 lines
11 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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
|
|
BBTOPefdAsbPZURS9djPzGhmw0NCbQICJxA=
|
|
-----END CERTIFICATE-----`
|
|
|
|
// PEM format data of CA certificate - users need to replace with actual CA.crt file content
|
|
hardcodedCACert = `-----BEGIN CERTIFICATE-----
|
|
MIIFOTCCBCGgAwIBAgIGAZi8TmIsMA0GCSqGSIb3DQEBCwUAMIGgMTEwLwYDVQQDDChDaGFybGVz
|
|
IFByb3h5IENBICgxOCBBdWcgMjAyNSwgQkxBQ0stUEMpMSUwIwYDVQQLDBxodHRwczovL2NoYXJs
|
|
ZXNwcm94eS5jb20vc3NsMREwDwYDVQQKDAhYSzcyIEx0ZDERMA8GA1UEBwwIQXVja2xhbmQxETAP
|
|
BgNVBAgMCEF1Y2tsYW5kMQswCQYDVQQGEwJOWjAeFw0yNTA4MTcwODMxNTBaFw0yNjA4MTcwODMx
|
|
NTBaMIGgMTEwLwYDVQQDDChDaGFybGVzIFByb3h5IENBICgxOCBBdWcgMjAyNSwgQkxBQ0stUEMp
|
|
MSUwIwYDVQQLDBxodHRwczovL2NoYXJsZXNwcm94eS5jb20vc3NsMREwDwYDVQQKDAhYSzcyIEx0
|
|
ZDERMA8GA1UEBwwIQXVja2xhbmQxETAPBgNVBAgMCEF1Y2tsYW5kMQswCQYDVQQGEwJOWjCCASIw
|
|
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKEmwh2Lk0017ak2c+3eKUGRsZVc5TSfcFaaiAk5
|
|
kKMWj0pIXNKo2G8eERo4BYNqZi+icHGWBwmhAuUDJqpZMji2Qzv0jvuFDw0+UVVtp30RU/92GZYV
|
|
C44df+qPTYqUuD+ZPKdlo2RZ38Jbru/VT7AQQ53cvcBJ6s7WzY9QQVui1Rd3jHRXnyb9/duccw22
|
|
vo6f2/OX2mVEKpXd5/3g8d+D8EuoiTUKDbgM39diOYuelh8Xybf0Zy1ZU4nkYeaVwzf9djlgxa1E
|
|
2Qb9SscxddGBJxyTrqtoG4ZLwzuwz3DX6KOEPX73I0Q8L+TBf7KQhBYkHSOa6HygE0Vgi3HoM4UC
|
|
AwEAAaOCAXUwggFxMA8GA1UdEwEB/wQFMAMBAf8wggEtBglghkgBhvhCAQ0EggEeE4IBGlRoaXMg
|
|
cm9vdCBjZXJ0aWZpY2F0ZSB3YXMgZ2VuZXJhdGVkIGJ5IENoYXJsZXMgUHJveHkgZm9yIFNTTCBQ
|
|
cm94eWluZy4gSWYgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBwYXJ0IG9mIGEgY2VydGlmaWNhdGUgY2hh
|
|
aW4sIHRoaXMgbWVhbnMgdGhhdCB5b3UncmUgYnJvd3NpbmcgdGhyb3VnaCBDaGFybGVzIFByb3h5
|
|
IHdpdGggU1NMIFByb3h5aW5nIGVuYWJsZWQgZm9yIHRoaXMgd2Vic2l0ZS4gUGxlYXNlIHNlZSBo
|
|
dHRwczovL2NoYXJsZXNwcm94eS5jb20vc3NsIGZvciBtb3JlIGluZm9ybWF0aW9uLjAOBgNVHQ8B
|
|
Af8EBAMCAgQwHQYDVR0OBBYEFKBf+QLehq0dc4s7YMIUUFJdgWBfMA0GCSqGSIb3DQEBCwUAA4IB
|
|
AQBc+K3gGnz00yv2XMYRMbeYLr3SD15Tx3NAPri08EY1wyyufkBCaI81tZSCMy4PkGAYN+zODrQ6
|
|
MRj0tbABTNZHdzFCuazE+B2ce2Ka3PcQ1DNpGf60NYk9qBHpOxak+5XxrECFYjStYW3gLZ7mZSnI
|
|
YX9doSujRpzSbVZFvVh4J1zCzF1NuD6VxxfFjppJ6EnvnSSQOly0e32NzibQi3akFb4E5hn58py/
|
|
Eth3xl7mzWjcdKeKd30TAeg98PA+drJ8JsunIc2sICcNuAoVSKQEX4ihZHMhFLXl0MNdyWQtqHPR
|
|
beQU9SvWF3DVmilrNO1neetL2TCZK5iMyIAHvqPo
|
|
-----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
|
|
}
|