feat: add more code and features

This commit is contained in:
2025-11-21 16:55:38 +01:00
parent f8f37a9fc5
commit 7cab5ff9cb
3 changed files with 294 additions and 80 deletions

44
integrity.go Normal file
View File

@@ -0,0 +1,44 @@
package main
import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"fmt"
"log"
)
func checkPublicKey(cert *x509.Certificate) {
switch pub := cert.PublicKey.(type) {
case *rsa.PublicKey:
fmt.Println("RSA key:", pub.N.BitLen(), "bits")
case *ecdsa.PublicKey:
fmt.Println("ECDSA key:", pub.Curve.Params().Name)
case ed25519.PublicKey:
fmt.Println("Ed25519 key")
default:
log.Fatal("Unsupported public key type")
}
}
func checkCertKeyPair(certPub any, priv any) bool {
switch pub := certPub.(type) {
case *rsa.PublicKey:
privRSA, ok := priv.(*rsa.PrivateKey)
return ok && pub.N.Cmp(privRSA.N) == 0 && pub.E == privRSA.E
case *ecdsa.PublicKey:
privECDSA, ok := priv.(*ecdsa.PrivateKey)
return ok && pub.X.Cmp(privECDSA.X) == 0 && pub.Y.Cmp(privECDSA.Y) == 0
case ed25519.PublicKey:
privEd, ok := priv.(ed25519.PrivateKey)
return ok && pub.Equal(privEd.Public().(ed25519.PublicKey))
default:
return false
}
}

256
main.go
View File

@@ -1,99 +1,195 @@
package main
import (
"fmt"
"os"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"fyne.io/fyne/v2/layout"
"crypto/x509"
"encoding/pem"
"fmt"
"log"
"os"
"slices"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
)
func main() {
a := app.New()
w := a.NewWindow("Upload 3 Files")
w.Resize(fyne.NewSize(800, 400))
a := app.NewWithID("nl.systemec.pfxgen")
w := a.NewWindow("Systemec PKCS12-Generator")
w.Resize(fyne.NewSize(600, 400))
var file1Path, file2Path, file3Path string
var keyPath, certPath string
// Labels to show selected filenames
fileLabel1 := widget.NewLabel("No file selected")
fileLabel2 := widget.NewLabel("No file selected")
fileLabel3 := widget.NewLabel("No file selected")
// Labels to show selected filenames
fileLabel1 := widget.NewLabel("No file selected")
fileLabel2 := widget.NewLabel("No file selected")
// Button 1
btn1 := widget.NewButton("Upload Certificate Private Key File", func() {
dialog.ShowFileOpen(func(r fyne.URIReadCloser, err error) {
if r != nil {
fileLabel1.SetText(r.URI().Name())
file1Path = r.URI().Path()
}
}, w)
})
radioLabel1 := widget.NewLabel("Select which Sectigo Intermediate")
// Button 2
btn2 := widget.NewButton("Upload Certificate File", func() {
dialog.ShowFileOpen(func(r fyne.URIReadCloser, err error) {
if r != nil {
fileLabel2.SetText(r.URI().Name())
file2Path = r.URI().Path()
}
}, w)
})
// Certificate Keyfile
btn1 := widget.NewButton("Upload Private Key File", func() {
dialog.ShowFileOpen(func(r fyne.URIReadCloser, err error) {
if r != nil {
fileLabel1.SetText(r.URI().Name())
keyPath = r.URI().Path()
}
}, w)
})
// Button 3
btn3 := widget.NewButton("Upload Certificate Intermediate File", func() {
dialog.ShowFileOpen(func(r fyne.URIReadCloser, err error) {
if r != nil {
fileLabel3.SetText(r.URI().Name())
file3Path = r.URI().Path()
}
}, w)
})
// Certificate file
btn2 := widget.NewButton("Upload Certificate File", func() {
dialog.ShowFileOpen(func(r fyne.URIReadCloser, err error) {
if r != nil {
fileLabel2.SetText(r.URI().Name())
certPath = r.URI().Path()
}
}, w)
})
goBtn := widget.NewButton("Go", func() {
fmt.Println("Go button clicked")
files := []string{file1Path, file2Path, file3Path}
// Certificate Intermediate
var newSectigoSelected bool
caRadio := widget.NewRadioGroup([]string{"New Sectigo (2025+)", "Old Sectigo (2025-)"}, func(selected string) {
switch selected {
case "New Sectigo (2025+)":
newSectigoSelected = true
case "Old Sectigo (2025-)":
newSectigoSelected = false
default: //Fallback
newSectigoSelected = true
}
})
caRadio.SetSelected("New Sectigo (2025+)") // default
allPresent := true
for _, f := range files {
if f == "" {
allPresent = false
break
}
}
entry := widget.NewEntry()
entry.SetPlaceHolder("")
entry.Disable()
if !allPresent {
fmt.Println("One or more files missing!")
return
}
actionBtn := widget.NewButton("Generate PKCS12 (pfx)", func() {
files := []string{keyPath, certPath}
for i, f := range files {
data, err := os.ReadFile(f)
if err != nil {
fmt.Printf("Error reading file %d (%s): %v\n", i+1, f, err)
continue
}
var caCert string
if newSectigoSelected {
caCert = sectigoNew
} else {
caCert = sectigoOld
}
fmt.Printf("Contents of file %d (%s):\n%s\n\n", i+1, f, string(data))
}
})
allPresent := true
if slices.Contains(files, "") {
allPresent = false
}
content := container.NewBorder(
nil, // top
goBtn, // bottom
nil, nil, // left, right
container.NewVBox( // center content
widget.NewLabel("Select 3 files:"),
container.NewHBox(btn1, fileLabel1),
container.NewHBox(btn2, fileLabel2),
container.NewHBox(btn3, fileLabel3),
layout.NewSpacer(), // adds flexible space
),
)
if !allPresent {
fmt.Println("One or more files missing!")
return
}
w.SetContent(content)
w.ShowAndRun()
entry.SetText(integrityCheckAndGo(keyPath, certPath, caCert))
})
cancelBtn := widget.NewButton("Exit", func() {
fmt.Println("Quitting...")
os.Exit(0)
})
// CREATE LAYOUTS
bottom := container.NewHBox(
actionBtn, // left
layout.NewSpacer(), // flexible space
cancelBtn, // right
)
centerContent := container.NewVBox(
widget.NewLabel("Select relevant files."),
container.New(layout.NewGridLayout(2), btn1, fileLabel1),
container.New(layout.NewGridLayout(2), btn2, fileLabel2),
layout.NewSpacer(),
container.New(layout.NewGridLayout(2), radioLabel1, caRadio),
layout.NewSpacer(), // optional flexible space
entry, // just add the entry directly
)
content := container.NewBorder(
nil, // top
bottom, // bottom
nil, nil, // left, right
centerContent,
)
w.SetContent(content)
w.ShowAndRun()
}
func readFile(path string) []byte {
rawData, err := os.ReadFile(path)
if err != nil {
fmt.Printf("Error reading contents of %s, %e", path, err)
return nil
} else {
return rawData
}
}
func parsePrivateKey(keyData []byte) any {
block, _ := pem.Decode(keyData)
if block == nil {
log.Fatal("failed to decode key PEM")
}
privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
log.Fatal(err)
}
return privateKey
}
func parseX509(certData []byte) *x509.Certificate {
block, _ := pem.Decode(certData)
if block == nil {
log.Fatal("failed to parse PEM block")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
log.Fatal(err)
}
return cert
}
func integrityCheckAndGo(keyPath, certPath, caCertString string) string {
if _, err := os.Stat(keyPath); err != nil {
fmt.Printf("Error checking Private Keyfile, %e", err)
return "Error..."
}
if _, err := os.Stat(certPath); err != nil {
fmt.Printf("Error checking Certificate file, %e", err)
return "Error..."
}
keyData := readFile(keyPath) // Read the private key file (PEM/DER)
certData := readFile(certPath) // Read the certificate file (PEM/DER)
key := parsePrivateKey(keyData) // Convert bytes to Go private key object
cert := parseX509(certData) // Convert bytes to Go x509.Certificate
caCert := parseX509([]byte(caCertString))
checkPublicKey(cert) // Print the information about the key
if checkCertKeyPair(cert.PublicKey, key) {
fmt.Println("Private key matches certificate")
} else {
fmt.Println("Private key does NOT match certificate")
}
return generatePKCS12(key, cert, caCert)
}
func generatePKCS12(pKey any, cert, caCert *x509.Certificate) string {
return "Nice"
}

74
sectigo_certificates.go Normal file
View File

@@ -0,0 +1,74 @@
package main
const sectigoNew string = `-----BEGIN CERTIFICATE-----
MIIGTDCCBDSgAwIBAgIQOXpmzCdWNi4NqofKbqvjsTANBgkqhkiG9w0BAQwFADBf
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBgMQswCQYDVQQGEwJHQjEY
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFB1Ymxp
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gQ0EgRFYgUjM2MIIBojANBgkqhkiG9w0B
AQEFAAOCAY8AMIIBigKCAYEAljZf2HIz7+SPUPQCQObZYcrxLTHYdf1ZtMRe7Yeq
RPSwygz16qJ9cAWtWNTcuICc++p8Dct7zNGxCpqmEtqifO7NvuB5dEVexXn9RFFH
12Hm+NtPRQgXIFjx6MSJcNWuVO3XGE57L1mHlcQYj+g4hny90aFh2SCZCDEVkAja
EMMfYPKuCjHuuF+bzHFb/9gV8P9+ekcHENF2nR1efGWSKwnfG5RawlkaQDpRtZTm
M64TIsv/r7cyFO4nSjs1jLdXYdz5q3a4L0NoabZfbdxVb+CUEHfB0bpulZQtH1Rv
38e/lIdP7OTTIlZh6OYL6NhxP8So0/sht/4J9mqIGxRFc0/pC8suja+wcIUna0HB
pXKfXTKpzgis+zmXDL06ASJf5E4A2/m+Hp6b84sfPAwQ766rI65mh50S0Di9E3Pn
2WcaJc+PILsBmYpgtmgWTR9eV9otfKRUBfzHUHcVgarub/XluEpRlTtZudU5xbFN
xx/DgMrXLUAPaI60fZ6wA+PTAgMBAAGjggGBMIIBfTAfBgNVHSMEGDAWgBRWc1hk
lfmSGrASKgRieaFAFYghSTAdBgNVHQ4EFgQUaMASFhgOr872h6YyV6NGUV3LBycw
DgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYI
KwYBBQUHAwEGCCsGAQUFBwMCMBsGA1UdIAQUMBIwBgYEVR0gADAIBgZngQwBAgEw
VAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdv
UHVibGljU2VydmVyQXV0aGVudGljYXRpb25Sb290UjQ2LmNybDCBhAYIKwYBBQUH
AQEEeDB2ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3Rp
Z29QdWJsaWNTZXJ2ZXJBdXRoZW50aWNhdGlvblJvb3RSNDYucDdjMCMGCCsGAQUF
BzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEA
YtOC9Fy+TqECFw40IospI92kLGgoSZGPOSQXMBqmsGWZUQ7rux7cj1du6d9rD6C8
ze1B2eQjkrGkIL/OF1s7vSmgYVafsRoZd/IHUrkoQvX8FZwUsmPu7amgBfaY3g+d
q1x0jNGKb6I6Bzdl6LgMD9qxp+3i7GQOnd9J8LFSietY6Z4jUBzVoOoz8iAU84OF
h2HhAuiPw1ai0VnY38RTI+8kepGWVfGxfBWzwH9uIjeooIeaosVFvE8cmYUB4TSH
5dUyD0jHct2+8ceKEtIoFU/FfHq/mDaVnvcDCZXtIgitdMFQdMZaVehmObyhRdDD
4NQCs0gaI9AAgFj4L9QtkARzhQLNyRf87Kln+YU0lgCGr9HLg3rGO8q+Y4ppLsOd
unQZ6ZxPNGIfOApbPVf5hCe58EZwiWdHIMn9lPP6+F404y8NNugbQixBber+x536
WrZhFZLjEkhp7fFXf9r32rNPfb74X/U90Bdy4lzp3+X1ukh1BuMxA/EEhDoTOS3l
7ABvc7BYSQubQ2490OcdkIzUh3ZwDrakMVrbaTxUM2p24N6dB+ns2zptWCva6jzW
r8IWKIMxzxLPv5Kt3ePKcUdvkBU/smqujSczTzzSjIoR5QqQA6lN1ZRSnuHIWCvh
JEltkYnTAH41QJ6SAWO66GrrUESwN/cgZzL4JLEqz1Y=
-----END CERTIFICATE-----`
const sectigoOld string = `-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
-----END CERTIFICATE-----`