locked
When Decrypting Data, "The Input Data is Not A Complete Block" RRS feed

  • Question

  • User-786564416 posted

    For encrypting database fields, I tried the following:

    Public Shared Sub Main()
            Try
                Dim original As String = "Here is some data to encrypt!"
    
                Using myAes As AesCryptoServiceProvider = New AesCryptoServiceProvider()
                    Dim encrypted As Byte() = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV)
                    Dim roundtrip As String = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV)
                    Console.WriteLine("Original:   {0}", original)
                    Console.WriteLine("Round Trip: {0}", roundtrip)
                End Using
    
            Catch e As Exception
                Console.WriteLine("Error: {0}", e.Message)
            End Try
        End Sub
    
        Public Shared Function EncryptStringToBytes_Aes(ByVal plainText As String, ByVal Key As Byte(), ByVal IV As Byte()) As Byte()
            If plainText Is Nothing OrElse plainText.Length <= 0 Then Throw New ArgumentNullException("plainText")
            If Key Is Nothing OrElse Key.Length <= 0 Then Throw New ArgumentNullException("Key")
            If IV Is Nothing OrElse IV.Length <= 0 Then Throw New ArgumentNullException("IV")
            Dim encrypted As Byte()
    
            Using aesAlg As AesCryptoServiceProvider = New AesCryptoServiceProvider()
                aesAlg.Key = Key
                aesAlg.IV = IV
                Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
    
                Using msEncrypt As MemoryStream = New MemoryStream()
    
                    Using csEncrypt As CryptoStream = New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
    
                        Using swEncrypt As StreamWriter = New StreamWriter(csEncrypt)
                            swEncrypt.Write(plainText)
                        End Using
    
                        encrypted = msEncrypt.ToArray()
                    End Using
                End Using
            End Using
    
            Return encrypted
        End Function
    
        Public Shared Function DecryptStringFromBytes_Aes(ByVal cipherText As Byte(), ByVal Key As Byte(), ByVal IV As Byte()) As String
            If cipherText Is Nothing OrElse cipherText.Length <= 0 Then Throw New ArgumentNullException("cipherText")
            If Key Is Nothing OrElse Key.Length <= 0 Then Throw New ArgumentNullException("Key")
            If IV Is Nothing OrElse IV.Length <= 0 Then Throw New ArgumentNullException("IV")
            Dim plaintext As String = Nothing
    
            Using aesAlg As AesCryptoServiceProvider = New AesCryptoServiceProvider()
                aesAlg.Key = Key
                aesAlg.IV = IV
                Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
    
                Using msDecrypt As MemoryStream = New MemoryStream(cipherText)
    
                    Using csDecrypt As CryptoStream = New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
    
                        Using srDecrypt As StreamReader = New StreamReader(csDecrypt)
                            plaintext = srDecrypt.ReadToEnd()
                        End Using
                    End Using
                End Using
            End Using
    
            Return plaintext
        End Function

    It works fine for some records. However, for some of the other records, when calling the function DecryptStringFromBytes_Aes  , I got the error: "The Input Data is Not A Complete Block"

    Where is the problem?

    Wednesday, October 24, 2018 2:50 PM

All replies

  • User475983607 posted

    It works fine for some records. However, for some of the other records, when calling the function DecryptStringFromBytes_Aes  , I got the error: "The Input Data is Not A Complete Block"

    Where is the problem?

    My best guess is you have a bug in the code that fetches the encrypted content and/or converts the content to a byte array.

    Wednesday, October 24, 2018 3:16 PM
  • User-786564416 posted

    We have a string variable ThisComments. we want to upload its encrypted value into database field EncryptedComments of type varbinary.

    Imports System.Security.Cryptography
    Dim ThisComments As String
    Dim LetterID As String
    Dim DecryptedComments As String
    
    Public Shared Function EncryptStringToBytes_Aes(ByVal plainText As String, ByVal Key As Byte(), ByVal IV As Byte()) As Byte()
            If plainText Is Nothing OrElse plainText.Length <= 0 Then Throw New ArgumentNullException("plainText")
            If Key Is Nothing OrElse Key.Length <= 0 Then Throw New ArgumentNullException("Key")
            If IV Is Nothing OrElse IV.Length <= 0 Then Throw New ArgumentNullException("IV")
            Dim encrypted As Byte()
    
            Using aesAlg As AesCryptoServiceProvider = New AesCryptoServiceProvider()
                aesAlg.Key = Key
                aesAlg.IV = IV
                Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)
    
                Using msEncrypt As MemoryStream = New MemoryStream()
    
                    Using csEncrypt As CryptoStream = New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
    
                        Using swEncrypt As StreamWriter = New StreamWriter(csEncrypt)
                            swEncrypt.Write(plainText)
                        End Using
    
                        encrypted = msEncrypt.ToArray()
                    End Using
                End Using
            End Using
    
            Return encrypted
        End Function
    
        Public Shared Function DecryptStringFromBytes_Aes(ByVal cipherText As Byte(), ByVal Key As Byte(), ByVal IV As Byte()) As String
            If cipherText Is Nothing OrElse cipherText.Length <= 0 Then Throw New ArgumentNullException("cipherText")
            If Key Is Nothing OrElse Key.Length <= 0 Then Throw New ArgumentNullException("Key")
            If IV Is Nothing OrElse IV.Length <= 0 Then Throw New ArgumentNullException("IV")
            Dim plaintext As String = Nothing
    
            Using aesAlg As AesCryptoServiceProvider = New AesCryptoServiceProvider()
                aesAlg.Key = Key
                aesAlg.IV = IV
                Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)
    
                Using msDecrypt As MemoryStream = New MemoryStream(cipherText)
    
                    Using csDecrypt As CryptoStream = New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)
    
                        Using srDecrypt As StreamReader = New StreamReader(csDecrypt)
                            plaintext = srDecrypt.ReadToEnd()
                        End Using
                    End Using
                End Using
            End Using
    
            Return plaintext
        End Function
    • First, we get ThisComments encrypted value using the function EncryptStringToBytes_Aes. and load it into myencrypted byte array variable.
    Using myAes As AesCryptoServiceProvider = New AesCryptoServiceProvider()
    
        Dim myencrypted As Byte() = EncryptStringToBytes_Aes(ThisComments, myAes.Key, myAes.IV)
    • Store the encrypted value into SQL Server database field of type varbinary:
    queryString = "UPDATE Postings SET EncryptedComments=@ECom WHERE (LetterID=@LID)"
    Dim PlugEncryption As New SqlCommand(queryString, connection)
    PlugEncryption.Parameters.Add("@ECom", SqlDbType.VarBinary)
    PlugEncryption.Parameters("@ECom").Value = myencrypted
    PlugEncryption.Parameters.Add("@LID", SqlDbType.NVarChar)
    PlugEncryption.Parameters("@LID").Value = LetterID
    PlugEncryption.ExecuteNonQuery()
    • Now, we want to retrieve the encrypted value and load it into byte array variable
       Dim EncryptedComments As Byte()
    
       queryString = "SELECT EncryptedComments FROM Postings WHERE (LetterID=@LID)"
       Dim GetStoredEncryption As New SqlCommand(queryString, connection)
       GetStoredEncryption.Parameters.Add("@LID", SqlDbType.NVarChar)
       GetStoredEncryption.Parameters("@LID").Value = MyRowView("LetterID")
       EncryptedComments = GetStoredEncryption.ExecuteScalar()
       If EncryptedComments.Length > 0 Then
          ThisComments = DecryptStringFromBytes_Aes(EncryptedComments, myAes.Key, myAes.IV)
       Else
          ThisComments = ""
       End If

    End Using

    That's my code. How can I make sure that I made the proper storing of the byte array into varbinary SQL Server database field, and Load it properly from database back from varbinary database field type into byte array variable?

    Thursday, October 25, 2018 8:17 PM
  • User475983607 posted

    alihusain_77

    How can I make sure that I made the proper storing of the byte array into varbinary SQL Server database field, and Load it properly from database back from varbinary database field type into byte array variable?

    Man, unit test the code and/or run the code through the VS debugger!  Do some troubleshooting and explain what you have done up to this point rather than just dumping code on the forum and making us guess.

    Have you tried comparing the data at each step of the processes?  That's where I would start and you only need the debugger and notepad.  Are you passing special characters and need to encode first?  Is the database field large enough to hold the content?  Can you post sample code that reproduces the behavior?  Does the byte array coming out of the database match the data that went in?  Does ExecuteScalar return content?

    This should be very easy to troubleshoot if you create a few unit tests.

    Anyway, look into the encryption that comes with SQL server if all you need is to encrypt data at rest. 

    https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/sql-server-encryption?view=sql-server-2017

    Thursday, October 25, 2018 8:55 PM
  • User-786564416 posted

    If there is a byte array. How to save all of its parts completely into the database, and what is the best database field type to store the byte array? Is it varbinary? Then how to retrieve the varbinary and load it into Byte array? I think the problem is here. The problem with me happened only with a Byte array with a big length. That's why I get Input data is not complete block when try decrypting as the passed encrypted variable of Byte array to the Decryption function.

    Now, I want to know how to Store Byte array variable into database field and then, How to retrieve it from database field of varbinary type into Byte array variable. 

    Thursday, October 25, 2018 9:07 PM