Imports Chilkat.Cert
Imports System.Drawing
Imports System.IO
Imports System.Security.Cryptography.X509Certificates
Imports System.Security.Cryptography
Public Class Form1

    Private Sub btnSeleccionarCertificado_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSeleccionarCertificado.Click
        Dim OpenFileDialog As New OpenFileDialog()
        With OpenFileDialog
            .InitialDirectory = My.Application.Info.DirectoryPath & "\"
            .Title = "Seleccionar Certificado de Sellos"
            '.FileName = "BD.accdb"
            .Filter = "Sertificado de Sellos (*.cer)|*.cer"
            .Multiselect = False
            '.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
            If .ShowDialog = Windows.Forms.DialogResult.OK Then
                txtDirCertificado.Text = .FileName
            End If
        End With
        ObtenerDatosCer()
    End Sub
    Sub ObtenerDatosCer()
        Try
            'Dim objCert As New X509Certificate2()
            'Dim bRawData As Byte() = ReadFile(Me.txtDirCertificado.Text)
            'objCert.Import(bRawData)
            'Me.txtNumSerieCert.Text = FormatearSerieCert(objCert.SerialNumber)
            'Me.txtCertValidoDesde.Text = Convert.ToDateTime(objCert.NotBefore)
            'Me.txtCertValidoHasta.Text = Convert.ToDateTime(objCert.NotAfter)
            'Me.txtDatosCert.Text = objCert.Subject

            'Dim DatosCSD As New StreamWriter(Application.StartupPath & "\CSD.txt")
            'DatosCSD.WriteLine(objCert.Subject)
            'DatosCSD.Close()

            'Dim tipoCSD As String = objCert.Subject.Substring(0, 2)
            'If tipoCSD = "OU" Then
            '    Me.lblTipoCertificado.Text = "Tipo de Certificado: CSD"
            '    If (Application.StartupPath & "\CSD.txt" <> String.Empty) Then
            '        Dim leer As New StreamReader(Application.StartupPath & "\CSD.txt")
            '        Dim texto As String = ""
            '        Dim count As Integer = 6
            '        Dim split As String() = Nothing
            '        While (Not texto Is Nothing)
            '            texto = leer.ReadLine()
            '            If (Not texto Is Nothing) Then
            '                split = texto.Split(New Char() {",", ":", ";"}, count)
            '                Me.txtRazonSocial.Text = CStr(Mid(split(5), 5))
            '                Me.txtRFC.Text = CStr(Mid(split(2), 15, 13))
            '            End If
            '        End While
            '    End If
            'Else
            '    Me.lblTipoCertificado.Text = "Tipo de Certificado: FIEL"
            '    If (Application.StartupPath & "\CSD.txt" <> String.Empty) Then
            '        Dim leer As New StreamReader(Application.StartupPath & "\CSD.txt")
            '        Dim texto As String = ""
            '        Dim count As Integer = 6
            '        Dim split As String() = Nothing
            '        While (Not texto Is Nothing)
            '            texto = leer.ReadLine()
            '            If (Not texto Is Nothing) Then
            '                split = texto.Split(New Char() {",", ":", ";"}, count)
            '                Me.txtRazonSocial.Text = CStr(Mid(split(4), 4))
            '                Me.txtRFC.Text = CStr(Mid(split(1), 15, 13))
            '            End If
            '        End While
            '    End If
            'End If


            'DatosCSD.WriteLine("{0}Subject: {1}{0}", Environment.NewLine, objCert.Subject)
            'DatosCSD.WriteLine("{0}Issuer: {1}{0}", Environment.NewLine, objCert.Issuer)
            'DatosCSD.WriteLine("{0}Version: {1}{0}", Environment.NewLine, objCert.Version)
            'DatosCSD.WriteLine("{0}Valid Date: {1}{0}", Environment.NewLine, objCert.NotBefore)
            'DatosCSD.WriteLine("{0}Expiry Date: {1}{0}", Environment.NewLine, objCert.NotAfter)
            'DatosCSD.WriteLine("{0}Thumbprint: {1}{0}", Environment.NewLine, objCert.Thumbprint)
            'DatosCSD.WriteLine("{0}Serial Number: {1}{0}", Environment.NewLine, objCert.SerialNumber)
            'DatosCSD.WriteLine("{0}Friendly Name: {1}{0}", Environment.NewLine, objCert.PublicKey.Oid.FriendlyName)
            'DatosCSD.WriteLine("{0}Public Key Format: {1}{0}", Environment.NewLine, objCert.PublicKey.EncodedKeyValue.Format(True))
            'DatosCSD.WriteLine("{0}Raw Data Length: {1}{0}", Environment.NewLine, objCert.RawData.Length)
            'DatosCSD.WriteLine("{0}Certificate to string: {1}{0}", Environment.NewLine, objCert.ToString(True))
            'Dim standard As String = B.Substring(14, 2) & "-" & B.Substring(10, 3) & "-" & B.Substring(26, 4)  'and tiempo 
            'Dim dateTime As DateTime = Convert.ToDateTime(standard)
            'Me.txtCertValidoDesde.Text = String.Format("{0:dd/MM/yyy}", B) ' dd/MM/yyyy


            '======= METODO CHILKAT==============
            Dim Certificado As Chilkat.Cert = New Chilkat.Cert()
            Dim fileCertificado As String = Me.txtDirCertificado.Text
            Certificado.LoadFromFile(fileCertificado)

            'verifica que el certificado no este caducado
            If Certificado.Expired = True Then
                MsgBox("El Certificado a Caducado con fecha: " & Certificado.ValidTo.Date)
                Me.txtDirCertificado.Clear()
                Me.txtDatosCert.Clear()
                Me.txtCertValidoDesde.Clear()
                Me.txtCertValidoHasta.Clear()
                Me.txtNumSerieCert.Clear()
                Exit Sub
            End If

            If Certificado.SubjectOU <> "" Then
                Me.lblTipoCertificado.Text = "Tipo de Certificado: CSD"
            Else
                Me.lblTipoCertificado.Text = "Tipo de Certificado: FIEL"
            End If
            'muestra los datos del certificado
            txtRazonSocial.Text = Certificado.SubjectCN
            txtDatosCert.Text = Certificado.SubjectDN
            txtCertValidoDesde.Text = Certificado.ValidFrom.Date
            txtCertValidoHasta.Text = Certificado.ValidTo.Date
            txtNumSerieCert.Text = FormatearSerieCert(Certificado.SerialNumber)

        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
    Public Function FormatearSerieCert(ByVal Serie As String) As String
        Dim Resultado As String = ""
        Dim I As Integer
        For I = 2 To Len(Serie) Step 2
            Resultado = Resultado & Mid(Serie, I, 1)
        Next
        FormatearSerieCert = Resultado
    End Function

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
       
    End Sub
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub btnSeleccionarLlave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSeleccionarLlave.Click
        Dim OpenFileDialog As New OpenFileDialog()
        With OpenFileDialog
            .Title = "Seleccionar Llave Privada"
            '.FileName = "BD.accdb"
            .Filter = "Llave Privada (*.key)|*.key"
            .Multiselect = False
            .InitialDirectory = My.Application.Info.DirectoryPath & "\"
            '.InitialDirectory = My.Computer.FileSystem.SpecialDirectories.MyDocuments
            If .ShowDialog = Windows.Forms.DialogResult.OK Then
                txtDirLlave.Text = .FileName
            End If
        End With
    End Sub

    Private Sub btnGenerarPFX_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerarPFX.Click
        If File.Exists(Me.txtDirCertificado.Text) = False Then
            MsgBox("No ha selecciona el Certificado de Sellos o el archivo no existe.")
            Exit Sub
        End If

        If File.Exists(Me.txtDirLlave.Text) = False Then
            MsgBox("No ha seleccionado la llave privada del certificado correspondiente o el archivo no existe.")
            Exit Sub
        End If

        If Me.txtContraseñaLlavePrivada.Text = "" Then
            MsgBox("No ha insertado la contraseña del Certificado de sellos.")
            Exit Sub
        End If

        'cargar la clave privada a partir de un archivo de claves RSA.
        Dim privKey As New Chilkat.PrivateKey
        If privKey.LoadPkcs8EncryptedFile(Me.txtDirLlave.Text, Me.txtContraseñaLlavePrivada.Text) = False Then
            'MsgBox(privKey.LastErrorText)
            MsgBox("La contraseña de la Llave Privada es incorrecta!")
            Exit Sub
        End If


        'obtener la clave privada en formato xml
        Dim privKeyXml As String = privKey.GetXml
        Dim rsa As New Chilkat.Rsa
        If rsa.UnlockComponent("RSAT34MB34N_7F1CD986683M") = False Then
            MsgBox(rsa.LastErrorText)
            Exit Sub
        End If

        'importar la clave privada en el componente rsa
        If rsa.ImportPrivateKey(privKeyXml) = False Then
            MsgBox(rsa.LastErrorText)
            Exit Sub
        End If

        'crear la firma como una cadena base64
        rsa.Charset = "utf-8"
        rsa.EncodingMode = "Base64"

        'Verifica que el certificado exista
        Dim Cer As Chilkat.Cert = New Chilkat.Cert()
        Dim CerFile As String = Me.txtDirCertificado.Text
        If Cer.LoadFromFile(CerFile) = False Then
            MsgBox(Cer.LastErrorText)
            Exit Sub
        End If

        Dim pubKey As Chilkat.PublicKey
        pubKey = Cer.ExportPublicKey

        'ahora verificar el uso de una instancia independiente del objeto rsa
        Dim rsa2 As New Chilkat.Rsa

        'importar la clave pública en el objeto rsa
        If rsa2.ImportPublicKey(pubKey.GetXml()) = False Then
            MsgBox(rsa2.LastErrorText)
            Exit Sub
        End If

        Try
            Dim SaveFileDialog As New SaveFileDialog()
            ' Extension por defecto
            SaveFileDialog.DefaultExt = "pfx"
            ' Extensiones disponibles
            SaveFileDialog.Filter = "Archivo (*.pfx)|*.pfx"
            'Anadir extension en cas de que el usuario no lo haga
            SaveFileDialog.AddExtension = True
            ' Restaura el directosio selectionado la proxima vez
            SaveFileDialog.RestoreDirectory = True
            ' Titulo de la ventana
            SaveFileDialog.Title = "Guardar Archivo para cancelacion FacturaNET"
            ' Directorio donde compenzar a buscar
            SaveFileDialog.InitialDirectory = My.Application.Info.DirectoryPath & "\"
            If SaveFileDialog.ShowDialog() = DialogResult.OK Then


                Dim ConvierteCerAPem As String
                Dim ConvierteKeyAPem As String
                Dim ConviertePfx As String
                Dim ArchivoCer As String = Me.txtDirCertificado.Text
                Dim ArchivoKey As String = Me.txtDirLlave.Text
                Dim NombreArchivoCertificado As String = Path.GetFileName(ArchivoCer)
                If Not File.Exists(ArchivoCer) Then
                    MessageBox.Show("La ruta del Certificado no existe")
                    Exit Sub
                End If
                Dim NombreArchivoLlave As String = Path.GetFileName(ArchivoKey)
                If Not File.Exists(ArchivoKey) Then
                    MessageBox.Show("La ruta del la llave privada no existe.")
                    Exit Sub
                End If

                ConvierteCerAPem = Application.StartupPath & "\OpenSSL\openssl x509 -inform DER -outform PEM -in " & ArchivoCer & " -pubkey > " & Application.StartupPath & "\" & NombreArchivoCertificado & ".pem"
                ConvierteKeyAPem = Application.StartupPath & "\OpenSSL\openssl pkcs8 -inform DER -in " & ArchivoKey & " -passin pass:" & Me.txtContraseñaLlavePrivada.Text & " -out " & Application.StartupPath & "\" & NombreArchivoLlave & ".pem"
                ConviertePfx = Application.StartupPath & "\OpenSSL\openssl pkcs12 -export -out " & SaveFileDialog.FileName & " -inkey " & Application.StartupPath & "\" & NombreArchivoLlave & ".pem -in " & Application.StartupPath & "\" & NombreArchivoCertificado & ".pem -passout pass:" & Me.txtContraseñaLlavePrivada.Text
                
                'Crea el archivo Certificado.BAT
                Dim oSW As New StreamWriter(Application.StartupPath & "\CertificadoPFX.bat")
                oSW.WriteLine(ConvierteCerAPem)
                oSW.WriteLine(ConvierteKeyAPem)
                oSW.WriteLine(ConviertePfx)
                'oSW.WriteLine("pause")
                oSW.Close()
                Dim Process As New Process
                Process.Start(Application.StartupPath & "\CertificadoPFX.bat")
                'Process.WaitForExit()

                System.Threading.Thread.Sleep(4000)


                If File.Exists(SaveFileDialog.FileName) = True Then
                    Me.txtDirArchivoPfx.Text = SaveFileDialog.FileName
                    MessageBox.Show("Archivo generado exitosamente!")
                ElseIf Not File.Exists(SaveFileDialog.FileName) Then
                    Me.txtDirArchivoPfx.Clear()
                    MessageBox.Show("Se encontro un problema al generar el Certificado pfx!")
                End If

                If File.Exists(Application.StartupPath & "\" & NombreArchivoCertificado & ".pem") = True Then
                    File.Delete(Application.StartupPath & "\" & NombreArchivoCertificado & ".pem")
                End If

                If File.Exists(Application.StartupPath & "\" & NombreArchivoLlave & ".pem") = True Then
                    File.Delete(Application.StartupPath & "\" & NombreArchivoLlave & ".pem")
                End If

                If File.Exists(Application.StartupPath & "\CertificadoPFX.bat") = True Then
                    File.Delete(Application.StartupPath & "\CertificadoPFX.bat")
                End If

            End If
            SaveFileDialog.Dispose()
            SaveFileDialog = Nothing
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
End Class
