Search code examples
vb.netexceptionencryptionpgp

Didisoft PGP Decrypt and Verify


I am trying to Decrypt using Didisoft pgp, and running into some issues. I can generate private and public key just fine. I can also Encrypt the file using SignAndEncryptFile function, and it returns the .pgp file just fine. The problem is when I tried to use the DecryptAndVerifyFile function. It returns an exception Wrong Private Key, I have checked so many times, that my public and private key are the same to the one that I use for Encrypting the file, the password that I used is all the same, because I'm just testing it. What did I do Wrong? :(

It only happens when I tried to use public key and private key to encrypt and decrypt it. I managed to do Encrypt and Decrypt before but it only uses the private key.

Public Function GetValue(ByVal FileData As String, ByVal email As String, ByVal password As String) As String
    Dim idKey As String = Guid.NewGuid().ToString()
    Dim ks As KeyStore = New KeyStore()
    Dim keySize As Integer = 1024
    'Dim password As String = "12345"

    Dim FilePathKey As String
    Dim FilePathPublicKey As String
    Dim keys As KeyPairInformation() = ks.GetKeys()

    ' Generate DH/DSS OpenPGP key
    ks.GenerateElgamalKeyPair(keySize, email, password)
    'idKey = ks(0).KeyId
    FilePathKey = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\", "Coba\" + idKey + ".key")
    ks.ExportPrivateKey(FilePathKey, ks(0).KeyId)

    Dim sql As New MySqlConnection()
    Dim adapter As New MySqlDataAdapter
    sql.ConnectionString = "server=localhost;userid=root;database=test"
    Dim query As String = "Select public_key from public_key LIMIT 1"
    Dim cmd As MySqlCommand

    Dim dt As New DataSet()
    cmd = New MySqlCommand(query, sql)
    sql.Open()

    adapter = New MySqlDataAdapter(cmd)
    adapter.Fill(dt)

    sql.Close()
    FilePathPublicKey = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\PublicKey\", dt.Tables(0).Rows(0).Item(0).ToString + ".key")

    If File.Exists(FileData) Then
        'Encrypt Data
        Dim pgp As New PGPLib()
        Dim idData As String = Guid.NewGuid().ToString()
        Dim asciiArmor As Boolean = True
        Dim withIntegrityCheck As Boolean = True
        Dim encryptedOutputFile As String = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\Coba\", idData + ".pgp")
        'Dim encryptedOutputFile As String = Path.Combine(Directory.GetCurrentDirectory(), "Tes\" + idData + ".pgp")
        'C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\Data\
        Dim encryptedOutputFileTes As New FileInfo(encryptedOutputFile)

        cmd = New MySqlCommand("INSERT INTO `tes`(`tesid`) VALUES ('" + idKey + "')", sql)
        sql.Open()
        cmd.ExecuteNonQuery()
        sql.Close()

        pgp.SignAndEncryptFile(FileData, FilePathKey, password, FilePathPublicKey, encryptedOutputFile, asciiArmor, withIntegrityCheck)
        'pgp.SignAndEncryptFile(FileData, FilePathKey, password, FilePathPublicKey, encryptedOutputFile, asciiArmor)
        'pgp.EncryptFilePBE(FileData, FilePathKey, password, encryptedOutputFile, asciiArmor, withIntegrityCheck)

        Dim FullFile As New FullFile(idData + ".pgp", My.Computer.FileSystem.ReadAllText(encryptedOutputFile))

        cmd = New MySqlCommand("INSERT INTO `enkripsi_data`(`data`, `key`) VALUES ('" + idData + "','" + idKey + "')", sql)
        sql.Open()
        cmd.ExecuteNonQuery()
        sql.Close()
        Dim serializer As New JavaScriptSerializer
        serializer.MaxJsonLength = Int32.MaxValue
        Dim fullFileJSON = serializer.Serialize(FullFile)

        Return fullFileJSON
    Else
        'File Tidak ada
        Return "0"
    End If
    'Dim FilePath = HttpContext.Current.Server.MapPath("~/" + idKey + ".asc")
End Function

Public Function GetValue(ByVal FileData As String, ByVal password As String) As String
    Dim sql As New MySqlConnection()
    Dim adapter As New MySqlDataAdapter
    Dim FileName As String
    FileName = Path.GetFileNameWithoutExtension(FileData)
    Dim pgp As New PGPLib()

    sql.ConnectionString = "server=localhost;userid=root;database=test"

    Dim dt As New DataTable()
    Dim cmd As New MySqlCommand("SELECT `key` FROM `enkripsi_data` WHERE `data`='" + FileName + "'", sql)
    sql.Open()

    adapter = New MySqlDataAdapter(cmd)
    adapter.Fill(dt)
    sql.Close()
    Dim KeyName As String
    KeyName = dt.Rows(0)(0).ToString

    Dim FilePathKey As String
    FilePathKey = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\", "Coba\" + KeyName + ".key")

    Dim decryptedOutputFile As String = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\", "Coba\Decrypted" + DateTime.Now.ToString(" dd-MM-yyyy HH.mm.ss") + ".bat")
    Dim query As String = "Select public_key from public_key LIMIT 1"
    Dim ds As New DataSet
    cmd = New MySqlCommand(query, sql)
    sql.Open()

    adapter = New MySqlDataAdapter(cmd)
    adapter.Fill(ds)

    sql.Close()
    Dim FilePathPublicKey As New String(Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\PublicKey\", ds.Tables(0).Rows(0).Item(0).ToString + ".key"))
    If File.Exists(FileData) Then
        Dim originalFileName As SignatureCheckResult
        Try
            'pgp.DecryptAndVerifyFile(FileData, FilePathKey, password, FilePathPublicKey, decryptedOutputFile)
            'originalFileName = pgp.DecryptFile(FileData, FilePathKey, password, decryptedOutputFile)
            originalFileName = pgp.DecryptAndVerifyFile(FileData, FilePathKey, password, FilePathPublicKey, decryptedOutputFile)
            '==================================================

            Dim fullFile As New FullFile(originalFileName, My.Computer.FileSystem.ReadAllText(decryptedOutputFile))

            Dim serializer As New JavaScriptSerializer
            serializer.MaxJsonLength = Int32.MaxValue
            Dim fullFileJSON = serializer.Serialize(fullFile)


            Return fullFileJSON
        Catch e As PGPException
            If TypeOf e Is NonPGPDataException Then
                Return "The input file is not an OpenPGP archive or is corrupted"
            ElseIf TypeOf e Is WrongPublicKeyException Then
                Return "The supplied public key is not an OpenPGP public key or is corrupted"
            ElseIf TypeOf e Is WrongPrivateKeyException Then
                ' The message cannot be decrypted with this private key 
                ' or the supplied private key is not an OpenPGP private key or is corrupted
                Return e.Message
            ElseIf TypeOf e Is WrongPasswordException Then
                Return "The password for the private key is incorrect"
            ElseIf TypeOf e Is FileIsPBEEncryptedException Then
                Return "The input file is password encrypted."
                Return "You have to use DecryptAndVeifyFilePBE or DecryptAndVerifyStreamPBE"
            ElseIf TypeOf e Is IntegrityCheckException Then
                Return "The encrypted data is corrupted"
            Else
                Return e.Message
            End If
        End Try

    Else
        'File gak ada
        Return "0"
    End If
End Function

Solution

  • Here is the problem:

    PGPLib.SignAndEncryptFile(dataFIle, signingPrivateKey, signingPrivateKeyPassword, encryptingPublicKey, desitinationFile)
    
    PGPLib.DecryptAndVerifyFile(dataFIle, decryptingPrivateKey, decryptingPrivateKeyPassword, signatureVerifyingPublicKey, desitinationFile)
    

    You use in both cases the same publicKey and the same private key - but PGP cryptography (and the library which implements it) expects when Decrypting to use the private key corresponding to the encryption key used in SignAndEncrypt,

    and the verification key to be the corresponding public key of the private key used in SignAndEncrypt.

    In essence here is what you shall do:

    Dim FilePathPublicKey As New String(Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\PublicKey\", ds.Tables(0).Rows(0).Item(0).ToString + ".key"))
    

    -> FilePathPublicKey must be the signature verifying public key from

    ks.GenerateElgamalKeyPair(keySize, email, password)
    

    ...

    FilePathKey = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\", "Coba\" + KeyName + ".key")
    

    -> FilePathKey mys be the private key corresponding to the key used for encrypting (the private key of FilePathPublicKey = Path.Combine("C:\Users\user\Desktop\Kuliah\Semester 8\Project\Tes\TES\WindowsApp1\bin\Debug\PublicKey\", dt.Tables(0).Rows(0).Item(0).ToString + ".key")

    originalFileName = pgp.DecryptAndVerifyFile(FileData, FilePathKey, password, FilePathPublicKey, decryptedOutputFile)