' Copyright (C) 2025  P4pillon.org
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU Affero General Public License as
' published by the Free Software Foundation, either version 3 of the
' License, or (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU Affero General Public License for more details.
'
' You should have received a copy of the GNU Affero General Public License
' along with this program.  If not, see <https://www.gnu.org/licenses/>.
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Security.Cryptography.Pkcs
Imports System.Xml
Imports System
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Public Class Form1


    Public Sub ShellandWait(ByVal ProcessDirectory As String, ByVal ProcessName As String, ByVal arguments As String)
        Dim objProcess As System.Diagnostics.Process
        Try
            objProcess = New System.Diagnostics.Process()
            objProcess.StartInfo.FileName = ProcessName
            objProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized
            objProcess.StartInfo.Arguments = arguments
            objProcess.StartInfo.WorkingDirectory = ProcessDirectory
            objProcess.Start()

            'Wait until the process passes back an exit code 
            objProcess.WaitForExit()

            'Free resources associated with this process
            objProcess.Close()
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Could not start process " & ProcessName)
        End Try
    End Sub

    Private Function Create_Certif(ByVal NumPharma As String) As Boolean
        RichTextBox1.AppendText("CREATION CERTIFICAT" & vbCrLf)
        Try
            ShellandWait(Application.StartupPath, "makecert.exe", Chr(34) & Application.StartupPath & "\Licences\" & NumPharma.ToString & ".public.cer" & Chr(34) & " -a sha1 -n " & Chr(34) & "CN=License Officine " & NumPharma.ToString & Chr(34) & " -ss My -sky signature -pe -len 2048")
        Catch ex As Exception
            RichTextBox1.AppendText("CREATION CERTIFICAT ECHOUEE" & vbCrLf & ex.Message & vbCrLf)
            Return False
        End Try
        Return True

    End Function

    Private Function Création_Fichier(ByVal NumPharma As String) As Boolean
        RichTextBox1.AppendText("CREATION FICHIER" & vbCrLf)
        Dim stringXML As String
        Try
            stringXML = "<?xml version=" + Chr(34) + "1.0" + Chr(34) + " encoding=" + Chr(34) + "UTF-8" + Chr(34) + "?>" + Chr(10) + _
            "<Licence>" + Chr(10) + _
            "<NumPharma>" + NumPharma + "</NumPharma>" + Chr(10) + _
            "<date_expiration>" + Format(DateTimePicker1.Value, "dd/MM/yyyy") + "</date_expiration>" + Chr(10) + _
            "</Licence>"
            Dim xmldoc As New XmlDocument
            xmldoc.LoadXml(stringXML)
            xmldoc.Save(Application.StartupPath & "\Licences\" & NumPharma.ToString & ".xml")
            SignXmlFile(Application.StartupPath & "\Licences\" & NumPharma.ToString & ".xml", Application.StartupPath & "\Licences\" & NumPharma.ToString & ".signed.xml", get_certif(NumPharma).PrivateKey)
        Catch ex As Exception
            RichTextBox1.AppendText("CREATION FICHIER ECHOUEE" & vbCrLf & ex.Message & vbCrLf)
            Return False
        End Try
        Return True
    End Function

    Public Shared Sub SignXmlFile(FileName As String, SignedFileName As String, Key As RSA)
        ' Create a new XML document.
        Dim doc As New XmlDocument()

        ' Load the passed XML file using its name.
        doc.Load(New XmlTextReader(FileName))

        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(doc)

        ' Add the key to the SignedXml document. 
        signedXml.SigningKey = Key

        ' Create a reference to be signed.
        Dim reference As New Reference()
        reference.Uri = ""

        ' Add an enveloped transformation to the reference.
        Dim env As New XmlDsigEnvelopedSignatureTransform()
        reference.AddTransform(env)

        ' Add the reference to the SignedXml object.
        signedXml.AddReference(reference)

        ' Compute the signature.
        signedXml.ComputeSignature()

        ' Get the XML representation of the signature and save
        ' it to an XmlElement object.
        Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()

        ' Append the element to the XML document.
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))

        If TypeOf doc.FirstChild Is XmlDeclaration Then
            doc.RemoveChild(doc.FirstChild)
        End If

        ' Save the signed XML document to a file specified
        ' using the passed string.
        Dim xmltw As New XmlTextWriter(SignedFileName, New UTF8Encoding(False))
        doc.WriteTo(xmltw)
        xmltw.Close()
    End Sub
    Private Function get_certif(ByVal NumPharma) As X509Certificate2

        Dim store As New X509Store(StoreLocation.CurrentUser)
        store.Open(OpenFlags.ReadOnly)
        Dim certCollection As X509Certificate2Collection = store.Certificates
        Dim certificate As X509Certificate2 = Nothing
        Dim c As X509Certificate2
        For Each c In certCollection
            If c.GetNameInfo(X509NameType.SimpleName, False) = "License Officine " & NumPharma.ToString Then
                certificate = c
                Exit For
            End If
        Next c
        store.Close()
        If certificate Is Nothing Then
            RichTextBox1.AppendText("OUVERTURE CERTIFICAT ECHOUEE" & vbCrLf)
        End If
        Return certificate
    End Function

    Public Shared Function VerifyXmlFile(Name As [String], Key As RSA) As [Boolean]
        ' Create a new XML document.
        Dim xmlDocument As New XmlDocument()

        ' Load the passed XML file into the document. 
        xmlDocument.Load(Name)

        ' Create a new SignedXml object and pass it
        ' the XML document class.
        Dim signedXml As New SignedXml(xmlDocument)

        ' Find the "Signature" node and create a new
        ' XmlNodeList object.
        Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature")

        ' Load the signature node.
        signedXml.LoadXml(CType(nodeList(0), XmlElement))

        ' Check the signature and return the result.
        Return signedXml.CheckSignature(Key)
    End Function

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        RichTextBox1.Clear()
        If Create_Certif(TextBox1.Text) = False Then Exit Sub
        If Création_Fichier(TextBox1.Text) = False Then Exit Sub
        RichTextBox1.AppendText("LICENCE " & TextBox1.Text & " GENEREE" & vbCrLf)
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        MsgBox(VerifyXmlFile(Application.StartupPath & "\Licences\" & TextBox1.Text.ToString & ".signed.xml", get_certif(TextBox1.Text).PublicKey.Key).ToString)
    End Sub
End Class
