feat: make working certificate parser and pfx writer

This commit is contained in:
2025-11-24 10:32:56 +01:00
parent 4e84abdd28
commit fea4c33c24
5 changed files with 134 additions and 21 deletions

View File

@@ -1,6 +1,40 @@
package main
const sectigoNew string = `-----BEGIN CERTIFICATE-----
const (
sectigoRoot string = `-----BEGIN CERTIFICATE-----
MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
-----END CERTIFICATE-----`
sectigoNew string = `-----BEGIN CERTIFICATE-----
MIIGTDCCBDSgAwIBAgIQOXpmzCdWNi4NqofKbqvjsTANBgkqhkiG9w0BAQwFADBf
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
@@ -37,7 +71,7 @@ r8IWKIMxzxLPv5Kt3ePKcUdvkBU/smqujSczTzzSjIoR5QqQA6lN1ZRSnuHIWCvh
JEltkYnTAH41QJ6SAWO66GrrUESwN/cgZzL4JLEqz1Y=
-----END CERTIFICATE-----`
const sectigoOld string = `-----BEGIN CERTIFICATE-----
sectigoOld string = `-----BEGIN CERTIFICATE-----
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
@@ -72,3 +106,4 @@ LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
-----END CERTIFICATE-----`
)

26
generator.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"crypto/x509"
"log"
"software.sslmate.com/src/go-pkcs12"
)
func generatePassword(n int) string {
for i := range n {
log.Println(i)
}
return "DefaultPass"
}
func generatePKCS12(pKey any, cert *x509.Certificate, caCerts []*x509.Certificate) (string, []byte) {
pfxPass := generatePassword(50)
pfxData, err := pkcs12.Modern.Encode(pKey, cert, caCerts, pfxPass)
if err != nil {
return "Failed to create PFX with given data.", nil
} else {
return "PKCS12 generated seemingly succesfully.", pfxData
}
}

6
go.mod
View File

@@ -2,7 +2,10 @@ module pfxgen
go 1.24.6
require fyne.io/fyne/v2 v2.7.1
require (
fyne.io/fyne/v2 v2.7.1
software.sslmate.com/src/go-pkcs12 v0.6.0
)
require (
fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect
@@ -32,6 +35,7 @@ require (
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
github.com/stretchr/testify v1.11.1 // indirect
github.com/yuin/goldmark v1.7.8 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/image v0.24.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect

4
go.sum
View File

@@ -65,6 +65,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
@@ -78,3 +80,5 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
software.sslmate.com/src/go-pkcs12 v0.6.0 h1:f3sQittAeF+pao32Vb+mkli+ZyT+VwKaD014qFGq6oU=
software.sslmate.com/src/go-pkcs12 v0.6.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI=

80
main.go
View File

@@ -13,11 +13,15 @@ import (
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/widget"
)
var (
windowSize fyne.Size = fyne.NewSize(600, 500)
windowSize fyne.Size = fyne.NewSize(700, 500)
keyTextFilter []string = []string{".key", ".txt", ".pem"}
crtTextFilter []string = []string{".crt", ".cer", ".txt", ".pem"}
)
func main() {
@@ -42,8 +46,9 @@ func main() {
r.Close()
}
}, w)
// Optionally set filters, title, etc.
// certDiag.SetFilter(...)
keyFilter := storage.NewExtensionFileFilter(keyTextFilter)
keyDiag.SetFilter(keyFilter)
keyDiag.Resize(windowSize)
keyDiag.Show()
})
@@ -58,6 +63,9 @@ func main() {
r.Close()
}
}, w)
certFilter := storage.NewExtensionFileFilter(crtTextFilter)
certDiag.SetFilter(certFilter)
// Resize the dialog
certDiag.Resize(windowSize)
certDiag.Show()
@@ -77,11 +85,11 @@ func main() {
})
caRadio.SetSelected("New Sectigo (2025+)") // default
entry := widget.NewEntry()
entry.SetPlaceHolder("")
entry.Disable()
// Make a text grid to display text.
grid := widget.NewTextGrid()
grid.SetText("Status will appear here.")
actionBtn := widget.NewButton("Generate PKCS12 (pfx)", func() {
actionBtn := widget.NewButton("Generate", func() {
files := []string{keyPath, certPath}
var caCert string
@@ -90,6 +98,7 @@ func main() {
} else {
caCert = sectigoOld
}
rootCert := sectigoRoot
allPresent := true
if slices.Contains(files, "") {
@@ -101,7 +110,42 @@ func main() {
return
}
entry.SetText(integrityCheckAndGo(keyPath, certPath, caCert))
respText, pfxData := integrityCheckAndGo(keyPath, certPath, caCert, rootCert)
log.Println(respText)
grid.SetText(respText)
// Show Save File dialog immediately
svDialog := dialog.NewFileSave(
func(writer fyne.URIWriteCloser, err error) {
if err != nil {
dialog.ShowError(err, w)
return
}
if writer == nil {
// User cancelled
return
}
_, writeErr := writer.Write(pfxData)
if writeErr != nil {
dialog.ShowError(writeErr, w)
return
}
writer.Close()
var dnText string = "PKCS file saved to: " + writer.URI().Path()
log.Println(dnText)
grid.SetText(dnText)
}, w)
svDialog.Resize(windowSize)
svDialog.SetFileName("certificate_store.pfx")
svDialog.SetFilter(storage.NewExtensionFileFilter([]string{".pfx"}))
svDialog.Show()
})
cancelBtn := widget.NewButton("Exit", func() {
@@ -121,10 +165,11 @@ func main() {
widget.NewLabel("Select relevant files."),
container.New(layout.NewGridLayout(2), keyBtn, fileLabel1),
container.New(layout.NewGridLayout(2), certBtn, fileLabel2),
layout.NewSpacer(),
widget.NewLabel("\n"),
container.New(layout.NewGridLayout(2), radioLabel1, caRadio),
layout.NewSpacer(), // optional flexible space
entry, // just add the entry directly
layout.NewSpacer(), // optional flexible space
grid, // Add the referenced text grid container
widget.NewLabel(""), // Add empty line for space
)
content := container.NewBorder(
@@ -175,15 +220,15 @@ func parseX509(certData []byte) *x509.Certificate {
return cert
}
func integrityCheckAndGo(keyPath, certPath, caCertString string) string {
func integrityCheckAndGo(keyPath, certPath, caCertString, caRootString string) (string, []byte) {
if _, err := os.Stat(keyPath); err != nil {
fmt.Printf("Error checking Private Keyfile, %e", err)
return "Error..."
return "Error...", nil
}
if _, err := os.Stat(certPath); err != nil {
fmt.Printf("Error checking Certificate file, %e", err)
return "Error..."
return "Error...", nil
}
keyData := readFile(keyPath) // Read the private key file (PEM/DER)
@@ -192,6 +237,7 @@ func integrityCheckAndGo(keyPath, certPath, caCertString string) string {
key := parsePrivateKey(keyData) // Convert bytes to Go private key object
cert := parseX509(certData) // Convert bytes to Go x509.Certificate
caCert := parseX509([]byte(caCertString))
rootCert := parseX509([]byte(caRootString))
checkPublicKey(cert) // Print the information about the key
@@ -201,9 +247,7 @@ func integrityCheckAndGo(keyPath, certPath, caCertString string) string {
fmt.Println("Private key does NOT match certificate")
}
return generatePKCS12(key, cert, caCert)
}
caCertList := []*x509.Certificate{caCert, rootCert}
func generatePKCS12(pKey any, cert, caCert *x509.Certificate) string {
return "Nice"
return generatePKCS12(key, cert, caCertList)
}