2
votes

I'm having trouble decrypting a string that was encrypted in .NET. I saw a couple other solutions on here, mainly Decrypting a string in ColdFusion encrypted with 3DES in C# but I'm still having issues trying to decrypt the .NET encrypted string that is being passed to me. Here is the error:

"An error occurred while trying to encrypt or decrypt your input string: Given final block not properly padded."

In further testing, when starting out with the same decrypted text, I am getting a different encrypted string in CF than I am in .NET

Here is the .NET code that is being used to encrypt/decrypt - I replaced the Key and IV data with fill-in info:

Imports System.IO
Imports System.Text
Imports System.Security.Cryptography

Public Class TripleDES

    ' define the triple des provider
    Private Shared m_des As New TripleDESCryptoServiceProvider

    ' define the string handler
    Private m_utf8 As New UTF8Encoding

    ' define the local property arrays
    Private m_key() As Byte
    Private m_iv() As Byte
    Private key As String = "48-digit hex key"
    Private iv As String = "16-digit hex iv"

    Public Sub New()
        Me.m_key = convertHexStringToByteArray(key)
        Me.m_iv = convertHexStringToByteArray(iv)
    End Sub
    Public Sub New(ByVal _key As String, ByVal _iv As String)
        key = _key
        iv = _iv
        Me.m_key = convertHexStringToByteArray(key)
        Me.m_iv = convertHexStringToByteArray(iv)
    End Sub
    Public Sub New(ByVal _key() As Byte, ByVal _iv() As Byte)
        Me.m_key = _key
        Me.m_iv = _iv
    End Sub
    Public Function Encryptfrombyte(ByVal input() As Byte) As Byte()
        Return Transform(input, m_des.CreateEncryptor(m_key, m_iv))
    End Function

    Public Function EncryptBytes(ByVal text As String) As Byte()
        Dim input() As Byte = m_utf8.GetBytes(text)
        Dim DesEnc As ICryptoTransform = m_des.CreateEncryptor(m_key, m_iv)
        Dim output() As Byte = Transform(input, DesEnc)
        Return output 'convertByteArrayToHexString(output)
    End Function

    Public Function encrypt(ByVal key As Byte(), ByVal data As Byte()) As Byte()
        Dim des As TripleDESCryptoServiceProvider = New TripleDESCryptoServiceProvider
        des.Key = key
        des.Mode = CipherMode.ECB
        des.Padding = PaddingMode.PKCS7
        Return des.CreateEncryptor.TransformFinalBlock(data, 0, data.Length)
    End Function
    Public Function Decrypt(ByVal input() As Byte) As String
        Dim DesEnc As ICryptoTransform = m_des.CreateDecryptor(m_key, m_iv)
        Dim output() As Byte = Transform(input, DesEnc)

        Return m_utf8.GetString(output)
    End Function
    Public Function Decrypt(ByVal text As String) As String
        Dim input() As Byte = m_utf8.GetBytes(text)
        Dim output() As Byte = Transform(input, _
                         m_des.CreateDecryptor(m_key, m_iv))
        Return m_utf8.GetString(output)
    End Function

    Private Function Transform(ByVal input() As Byte, _
        ByVal CryptoTransform As ICryptoTransform) As Byte()
        ' create the necessary streams
        Dim memStream As MemoryStream = New MemoryStream
        Dim cryptStream As CryptoStream = New _
            CryptoStream(memStream, CryptoTransform, _
            CryptoStreamMode.Write)
        ' transform the bytes as requested
        cryptStream.Write(input, 0, input.Length)
        cryptStream.FlushFinalBlock()
        ' Read the memory stream and convert it back into byte array
        memStream.Position = 0
        Dim result(CType(memStream.Length - 1, System.Int32)) As Byte
        memStream.Read(result, 0, CType(result.Length, System.Int32))
        ' close and release the streams
        memStream.Close()
        cryptStream.Close()
        ' hand back the encrypted buffer
        Return result
    End Function
    Public Function convertHexStringToByteArray(ByVal str As String) As Byte()

        '//String in Hex - 2 chars represet a byte.
        Dim size As Integer = (str.Length() / 2) - 1
        Dim b(size) As Byte
        'ReDim b  str.Length() / 2
        Dim j As Integer = 0

        Try
            For i As Integer = 0 To str.Length() - 1 Step 2
                Dim s As String = str.Substring(i, 2)
                '//parse the substring as an integer, as the 8th bit may be set
                Dim k As Integer = Convert.ToInt32(s, 16)
                '//downcast integer to byte, this down casting does not do any
                ' //harm since memory footprint of first 8 bits remains same.
                b(j) = New Byte
                b(j) = CType(k, Byte)
                j += 1
            Next
        Catch e As Exception
            Dim ti As String = 1
            'TraceLog.trace2(e)
        End Try
        Return b
    End Function
    Public Function convertByteArrayToHexString(ByVal b() As Byte) As String
        Dim buffer As String
        ' Dim hexDigit() As String = Split("0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f", "', '")

        For i As Integer = 0 To b.Length - 1
            'dim  array as char()= (hexDigit((b(i) >> 4) & chr(0x0f)), hexDigit(b(i) & 0x0f))
            Dim tmp As String = Hex(b(i))
            If tmp.Length = 1 Then
                tmp = "0" & tmp
            End If
            buffer += (tmp)
        Next

        Return buffer.ToString()
    End Function
    Public Function bytetoHex(ByVal hextBt() As Byte) As String
        Dim disc As Integer = 0
        bytetoHex = HexEncoding.ToString(hextBt)

    End Function

    Public Function hexToByte(ByVal hex As String) As Byte()
        Dim disc As Integer = 0
        hexToByte = HexEncoding.hexidecimaltoByte(hex)
    End Function

End Class

Here is the CF code that encrypts/decrypts:

<!--- Get The Key from Hex to base64 --->
<cfset theKeyHex    = "48-digit hex key" />
<cfset theKeyBin    = BinaryDecode(theKeyHex,"hex")>
<cfset theKeyB64    = BinaryEncode(theKeyBin,"base64")>

<!--- Get the IV to Binary --->
<cfset theIV        = "16-digit hex iv" />
<cfset theIVBin     = BinaryDecode(theIV,"hex")>

<!--- Define Encoding parameters --->
<cfset theAlgorithm = "DESede/ECB/PKCS5Padding">
<cfset theEncoding  = "Base64">

<!--- Define string --->
<cfset str = "108644" >

<cfoutput>
    <cfset enc = Encrypt(str, theKeyB64, theAlgorithm, theEncoding, theIVBin)>
    encrypted = #enc#<br />

    <cfset dec = Decrypt(enc, theKeyB64, theAlgorithm, theEncoding, theIVBin)>
    decrypted = #dec#<br />
</cfoutput>

Just to be clear - while trying to test this code, I was running into errors decrypting the .NET encrypted string, so I tried encrypting the value in CF to see if I get the same encrypted string.

In CF, 108644 gets encrypted to 63Yp6O+8K+U=

In .NET, 108644 gets encrypted to 7loa00RCdZo=

I'm at an impasse. I have no idea where to go from here. Any help is greatly appreciated!

1

1 Answers

2
votes

ECB mode does not use an initialization vector, so it is ignored. You need to change your mode to CBC:

<cfset theAlgorithm = "DESede/CBC/PKCS5Padding">

Edit: To elaborate, the mode varies depending on which function the .NET code uses. The encrypt(key, data) function uses ECB mode. While EncryptBytes(text) implicitly uses CBC mode, due to the presence of an iv. So you need to alter your CF code accordingly.