Re: DES ECB Encryption cannot decrypt

From: Per Vestergaard-Laustsen (pvl_at_capto.dk)
Date: 05/12/03


Date: Mon, 12 May 2003 12:15:49 +0200


To-/FromBase64String does not work for me, because each of the bytes in the
array of 8 can assume any value between Hx00 and HxFF both included when
en-/decrypting.

When I try and convert from for instance Chr(0) I get an errormessage.

"Ivan Medvedev [MS]" <ivanmed@online.microsoft.com> skrev i en meddelelse
news:uKgSvjkFDHA.2800@tk2msftngp13.phx.gbl...
> Per -
> there is a thing in crypto called "padding" - when the data is
encrypted
> with DES in .NET classes by default it is padded with up to 8 bytes of
> padding, that is why you are getting 16 bytes of ciphertext. Now, the
> decryptor by default expects the cipher text to have that padding and
> attempts to remove it, and because you only give it the first 8 bytes of
the
> ciphertext it fails. Padding must be used if you need to process data of
> various lengths. If your data size is always a multiple of 8 you don't
have
> to use padding and you can turn it off by setting DES.Padding =
> PaddingMode.None for both encrypting and decrypting algorithm object.
> I would highly recommend that you read some books or online resources
on
> cryptography in general. I have seen companies having big problems because
> people implementing crypto didn't exactly know what they were doing. For
> example, I wouldn't recommend using ECB mode unless you know for sure that
> it is the right choice, instead I would recommend sticking to the default.
> In out prior conversation I have posted a modified version of your
code
> that worked without problems and could roundtrip any data. As I understood
> you could not use that code because the encryptor returned a byte array
and
> for some reason you only can pass around strings (please correct me if I
> understood it incorrectly). Therefore I suggested that you use Base64; use
> ToBase64 in the encrypting method to get a string out of the encrypted
> bytes, pass the string around and use FromBase64 in the decrypting method
to
> get bytes out of the string. ToBase64/FromBase64 guarantees that you get
the
> same byte array out as you put in.
> Please let me know if this approach does not work for you or you have
> trouble making the program work, and I will post another version of the
> program that does exactly what you want.
> --Ivan
>
> This posting is provided "AS IS" with no warranties, and confers no
rights.
>
>
> "Per Vestergaard-Laustsen" <pvl@capto.dk> wrote in message
> news:#RsQdtfFDHA.2264@TK2MSFTNGP12.phx.gbl...
> > Sorry if I make you feel tired, but Base64 does not guarantee that the
> > characters in the string are converted to the same byte values as I the
> byte
> > values I converted from before calling the ActiveX component.
> >
> > Yes in my excessive efforts to make this work, I have amongst a lot of
> other
> > things, tried to call the decryption with only 8 bytes at the time.
> Normally
> > I would just write the entire content of PIN to the decryption-stream,
> which
> > I have also tried.
> >
> > I still do not know how the API can make a subjective assessment of the
> data
> > feed to it. I would expect that if I feed a wrong encrypted value to the
> > API, the decrypted value will simply not match the original unencrypted
> > value.
> >
> > If you do not know exactly what goes wrong, and can not find out, just
say
> > so. In that case I will just use another product for this task. I need
to
> > move on now. I have a deadline.
> > "Ivan Medvedev [MS]" <ivanmed@online.microsoft.com> skrev i en
meddelelse
> > news:#HMjJ9XFDHA.2264@TK2MSFTNGP12.phx.gbl...
> > > Per -
> > >
> > > your enctyped value as you show it here is 16 bytes, while it looks
like
> > in
> > > the decrypting function you only feed 8 bytes to the cryptostream's
> Write
> > > method. Also, as I said in my previous post, I would recommend using
> > Base64
> > > encoding/decoding to do string <-> byte araay transformations.
> > > --Ivan
> > > This posting is provided "AS IS" with no warranties, and confers no
> > rights.
> > >
> > >
> > > "Per Vestergaard-Laustsen" <pvl@capto.dk> wrote in message
> > > news:uc0kjfUFDHA.2308@TK2MSFTNGP09.phx.gbl...
> > > > I am making an ActiveX component, and the application supposed to
use
> it
> > > > only supports passing arguments as strings. Internally that
particular
> > > > application only uses ASCII format for strings. I need to pass
binary
> > > values
> > > > to and from the ActiveX component, where each byte can assume all
> values
> > > > from 0 to 255 (unsigned char).
> > > >
> > > > By the way the crypto API still will not work.
> > > >
> > > > I use DES, Mode=ECB. If I have the value to encrypt =
> > > > '01-47-11-00-00-00-00-00', the Key = 'EE-B7-55-E0-E7-35-B1-74' and
IV
> =
> > > > '00-00-00-00-00-00-00-00'(since it should not be used when
mode=ECB),
> > then
> > > > when encrypting I get
> 'C0-30-76-FF-4D-2C-3C-C5-8B-03-5A-A1-96-FB-9C-3C'.
> > > >
> > > > So far so good. But now when I try and decrypt that value, with the
> same
> > > Key
> > > > and IV, I get a bad data error. The Exception thrown has Hresult =
> > > > &HFFFFFFFF80131430 and _xcode = &HFFFFFFFFE0434F4D.
> > > >
> > > > Best regards Per Vestergaard-Laustsen, Denmark
> > > >
> > > > Code used :
> > > >
> > > > Imports System
> > > >
> > > > Imports System.Security.Cryptography 'in order to be able to en- /
de-
> > > crypt
> > > >
> > > > Imports System.IO 'in order to use streams or memorystreams
> > > >
> > > > Imports System.Object 'in order to be able to create a BinaryReader
> > > >
> > > > Imports System.NotSupportedException 'in order to troubleshoot not
> > > supported
> > > > exceptions
> > > >
> > > > Imports System.Text.UTF8Encoding 'in order to be able to convert
> between
> > > > texts and bytearrays
> > > >
> > > > <ComClass(Crypto.ClassId, Crypto.InterfaceId, Crypto.EventsId)> _
> > > >
> > > > Public Class Crypto
> > > >
> > > > #Region "COM GUIDs"
> > > >
> > > > ' These GUIDs provide the COM identity for this class
> > > >
> > > > ' and its COM interfaces. If you change them, existing
> > > >
> > > > ' clients will no longer be able to access the class.
> > > >
> > > > Public Const ClassId As String =
> "E283E523-DDF6-41E5-99FD-D49BEA927F6B"
> > > >
> > > > Public Const InterfaceId As String =
> > > "63468760-BECB-43D0-B001-D656E7D83519"
> > > >
> > > > Public Const EventsId As String =
> "E42A8155-7740-4BE8-BB53-A845E0286A12"
> > > >
> > > > #End Region
> > > >
> > > > ' A creatable COM class must have a Public Sub New()
> > > >
> > > > ' with no parameters, otherwise, the class will not be
> > > >
> > > > ' registered in the COM registry and cannot be created
> > > >
> > > > ' via CreateObject.
> > > >
> > > > Public Sub New()
> > > >
> > > > MyBase.New()
> > > >
> > > > End Sub
> > > >
> > > > Protected Overrides Sub Finalize()
> > > >
> > > > MyBase.Finalize()
> > > >
> > > > End Sub
> > > >
> > > > Dim errPosition As String
> > > >
> > > > Dim globalexception As CryptographicException
> > > >
> > > > Public Sub test()
> > > >
> > > > If "0655" <> decrypt(encrypt("0655", "09689036", "80682702"),
> > "09689036",
> > > > "80682702") Then
> > > >
> > > > Console.WriteLine("Decrypted : " + decrypt(encrypt("0655",
"09689036",
> > > > "80682702"), "09689036", "80682702"))
> > > >
> > > > Console.WriteLine("Unencrypted : " + "0655")
> > > >
> > > > End If
> > > >
> > > > End Sub
> > > >
> > > > Public Function encrypt(ByRef textPIN As String, ByRef textKey As
> > String,
> > > > ByRef textInitialValue As String) As String
> > > >
> > > > On Error GoTo ErrorHandler
> > > >
> > > > errPosition = "In encrypt function"
> > > >
> > > > Dim PIN() As Byte
> > > >
> > > > Dim Key() As Byte
> > > >
> > > > Dim InitialValue() As Byte
> > > >
> > > > PIN = GetEncryptKeyByteArray(textPIN)
> > > >
> > > > Key = GetEncryptKeyByteArray(textKey)
> > > >
> > > > InitialValue = GetEncryptKeyByteArray(textInitialValue)
> > > >
> > > > Dim cryptPIN As MemoryStream
> > > >
> > > > cryptPIN = New MemoryStream()
> > > >
> > > > Dim encryption As ICryptoTransform
> > > >
> > > > Dim cryptoService As New
> > > > System.Security.Cryptography.DESCryptoServiceProvider()
> > > >
> > > > 'cryptoService.Mode = CipherMode.ECB
> > > >
> > > > encryption = cryptoService.CreateEncryptor(Key, InitialValue)
> > > >
> > > > Dim encryptStream As New
> > > System.Security.Cryptography.CryptoStream(cryptPIN,
> > > > _
> > > >
> > > > encryption, _
> > > >
> > > > CryptoStreamMode.Write)
> > > >
> > > > encryptStream.Write(PIN, 0, CInt(PIN.Length)) 'encrypt writing to
the
> > > > encryptionstream
> > > >
> > > > encryptStream.FlushFinalBlock() 'empty the temporary stream-buffer
by
> > > force
> > > >
> > > > encrypt = byte2str(cryptPIN.ToArray())
> > > >
> > > > 'close the streams that has been opened
> > > >
> > > > encryptStream.Close()
> > > >
> > > > cryptPIN.Close()
> > > >
> > > > 'destroy the objects that has been created and used
> > > >
> > > > cryptPIN = Nothing
> > > >
> > > > encryption = Nothing
> > > >
> > > > cryptoService = Nothing
> > > >
> > > > encryptStream = Nothing
> > > >
> > > > Return encrypt
> > > >
> > > > ErrorHandler:
> > > >
> > > > textPIN = Err.Description
> > > >
> > > > textKey = errPosition
> > > >
> > > > End Function
> > > >
> > > > Public Function decrypt(ByRef textPIN As String, ByRef textKey As
> > String,
> > > > ByRef textInitialValue As String) As String
> > > >
> > > > 'On Error GoTo ErrorHandler
> > > >
> > > > errPosition = "In decrypt function"
> > > >
> > > > Dim i As Integer
> > > >
> > > > Dim cryptPIN As MemoryStream
> > > >
> > > > Dim PIN(15) As Byte
> > > >
> > > > Dim Key(7) As Byte
> > > >
> > > > Dim InitialValue(7) As Byte
> > > >
> > > > PIN = GetDecryptKeyByteArray(textPIN)
> > > >
> > > > Key = GetEncryptKeyByteArray(textKey)
> > > >
> > > > InitialValue = GetEncryptKeyByteArray(textInitialValue)
> > > >
> > > > cryptPIN = New MemoryStream()
> > > >
> > > > Dim buffer(1024) As Byte
> > > >
> > > > Dim decryption As ICryptoTransform
> > > >
> > > > Dim cryptoService As New DESCryptoServiceProvider()
> > > >
> > > > 'cryptoService.Mode = CipherMode.ECB
> > > >
> > > > decryption = cryptoService.CreateDecryptor(Key, InitialValue)
> > > >
> > > > 'the decryption takes place here
> > > >
> > > > Dim decryptStream As New CryptoStream(cryptPIN, _
> > > >
> > > > decryption, _
> > > >
> > > > CryptoStreamMode.Write)
> > > >
> > > > 'temp TEST
> > > >
> > > > Dim tempArrayOfByte(7) As Byte
> > > >
> > > > For i = 0 To 7
> > > >
> > > > tempArrayOfByte(i) = PIN(i)
> > > >
> > > > Next
> > > >
> > > > Try
> > > >
> > > > decryptStream.Write(tempArrayOfByte, 0,
CInt(tempArrayOfByte.Length))
> > > > 'encrypt writing to the decryptionstream
> > > >
> > > > Catch exception As CryptographicUnexpectedOperationException
> > > >
> > > > globalexception = exception
> > > >
> > > > GoTo errorhandler
> > > >
> > > > End Try
> > > >
> > > > Try
> > > >
> > > > decryptStream.FlushFinalBlock() 'empty the temporary stream-buffer
by
> > > force
> > > >
> > > > Catch exception As CryptographicException
> > > >
> > > > globalexception = exception
> > > >
> > > > GoTo ErrorHandler
> > > >
> > > > End Try
> > > >
> > > > 'end temp TEST
> > > >
> > > > Try
> > > >
> > > > decryptStream.Write(PIN, 0, CInt(PIN.Length)) 'encrypt writing to
the
> > > > decryptionstream
> > > >
> > > > Catch exception As CryptographicUnexpectedOperationException
> > > >
> > > > globalexception = exception
> > > >
> > > > GoTo errorhandler
> > > >
> > > > End Try
> > > >
> > > > Try
> > > >
> > > > decryptStream.FlushFinalBlock() 'empty the temporary stream-buffer
by
> > > force
> > > >
> > > > Catch exception As CryptographicException
> > > >
> > > > globalexception = exception
> > > >
> > > > GoTo ErrorHandler
> > > >
> > > > End Try
> > > >
> > > > decrypt = byte2str(cryptPIN.ToArray())
> > > >
> > > > 'close the streams that has been opened
> > > >
> > > > cryptPIN.Close()
> > > >
> > > > decryptStream.Close()
> > > >
> > > > 'destroy all objects used
> > > >
> > > > decryption = Nothing
> > > >
> > > > globalexception = Nothing
> > > >
> > > > cryptoService = Nothing
> > > >
> > > > Return decrypt
> > > >
> > > > ErrorHandler:
> > > >
> > > > If globalexception.Message = "" Then
> > > >
> > > > textPIN = Err.Description
> > > >
> > > > textKey = errPosition
> > > >
> > > > Else
> > > >
> > > > Dim inner As Exception
> > > >
> > > > textPIN = globalexception.Message
> > > >
> > > > inner = globalexception.InnerException()
> > > >
> > > > If Not inner Is Nothing Then
> > > >
> > > > textKey = inner.Message
> > > >
> > > > End If
> > > >
> > > > textInitialValue = globalexception.Source
> > > >
> > > > End If
> > > >
> > > > End Function
> > > >
> > > > Public Function calcXOR(ByVal Arg1 As Integer, ByVal Arg2 As
Integer)
> As
> > > > Integer
> > > >
> > > > calcXOR = Arg1 Xor Arg2
> > > >
> > > > Return calcXOR
> > > >
> > > > End Function
> > > >
> > > > Private Function GetEncryptKeyByteArray(ByVal sPassword As String)
As
> > > Byte()
> > > >
> > > > Dim byteTemp(7) As Byte
> > > >
> > > > 'sPassword = sPassword.PadRight(8) ' make sure we have 8 chars
> > > >
> > > > Dim a, b As String
> > > >
> > > > Dim i, n As Integer
> > > >
> > > > Dim bPW(7) As Byte
> > > >
> > > > n = 0
> > > >
> > > > For i = 1 To 22 Step 3
> > > >
> > > > a = Asc(Mid(sPassword, i, 1)) - Asc("0")
> > > >
> > > > If a > 9 Then a = a - 7
> > > >
> > > > If a < 0 Or a > 15 Then
> > > >
> > > > Err.Raise(vbObjectError + 513)
> > > >
> > > > End If
> > > >
> > > > b = Asc(Mid(sPassword, i + 1, 1)) - Asc("0")
> > > >
> > > > If b > 9 Then b = b - 7
> > > >
> > > > If b < 0 Or b > 15 Then
> > > >
> > > > Err.Raise(vbObjectError + 513)
> > > >
> > > > End If
> > > >
> > > > bPW(n) = a * 16 + b
> > > >
> > > > n += 1
> > > >
> > > > Next i
> > > >
> > > > 'Dim iCharIndex As Integer
> > > >
> > > > 'For iCharIndex = 0 To sPassword.Length - 1
> > > >
> > > > 'byteTemp(iCharIndex) = Asc(Mid$(sPassword, iCharIndex + 1, 1))
> > > >
> > > > 'Next
> > > >
> > > > 'byteTemp = UTF8.GetBytes(sPassword)
> > > >
> > > > Return bPW
> > > >
> > > > End Function
> > > >
> > > > Private Function GetDecryptKeyByteArray(ByVal sPassword As String)
As
> > > Byte()
> > > >
> > > > Dim byteTemp(15) As Byte
> > > >
> > > > ' sPassword = sPassword.PadRight(16) ' make sure we have 16 chars
> > > >
> > > > Dim a, b As String
> > > >
> > > > Dim i, n As Integer
> > > >
> > > > Dim bPW(15) As Byte
> > > >
> > > > n = 0
> > > >
> > > > For i = 1 To 46 Step 3
> > > >
> > > > a = Asc(Mid(sPassword, i, 1)) - Asc("0")
> > > >
> > > > If a > 9 Then a = a - 7
> > > >
> > > > If a < 0 Or a > 15 Then
> > > >
> > > > Err.Raise(vbObjectError + 513)
> > > >
> > > > End If
> > > >
> > > > b = Asc(Mid(sPassword, i + 1, 1)) - Asc("0")
> > > >
> > > > If b > 9 Then b = b - 7
> > > >
> > > > If b < 0 Or b > 15 Then
> > > >
> > > > Err.Raise(vbObjectError + 513)
> > > >
> > > > End If
> > > >
> > > > bPW(n) = a * 16 + b
> > > >
> > > > n += 1
> > > >
> > > > Next i
> > > >
> > > > 'Dim iCharIndex As Integer
> > > >
> > > > 'For iCharIndex = 0 To sPassword.Length - 1
> > > >
> > > > 'byteTemp(iCharIndex) = Asc(Mid$(sPassword, iCharIndex + 1, 1))
> > > >
> > > > 'Next
> > > >
> > > > 'byteTemp = UTF8.GetBytes(sPassword)
> > > >
> > > > Return bPW
> > > >
> > > > End Function
> > > >
> > > > Private Function byte2str(ByRef bytes() As Byte) As String
> > > >
> > > > errPosition = "In byte2str"
> > > >
> > > > 'Dim i As Integer
> > > >
> > > > 'Dim tmpString As String
> > > >
> > > > 'Dim tmpStringOneChar As String
> > > >
> > > > 'tmpString = ""
> > > >
> > > > 'errPosition = "Before for loop in byte2str"
> > > >
> > > > 'For i = 1 To bytes.Length - 1
> > > >
> > > > 'tmpStringOneChar = Chr(bytes(i))
> > > >
> > > > 'tmpString = tmpString + tmpStringOneChar
> > > >
> > > > 'errPosition = "In for loop in byte2str"
> > > >
> > > > 'Next
> > > >
> > > > 'errPosition = "After for loop in byte2str"
> > > >
> > > > 'byte2str = tmpString
> > > >
> > > > byte2str = BitConverter.ToString(bytes)
> > > >
> > > > errPosition = "Before return from byte2str"
> > > >
> > > > Return byte2str
> > > >
> > > > End Function
> > > >
> > > > Public Function argtest(ByRef bytes As Byte()) As Object
> > > >
> > > > Return bytes
> > > >
> > > > End Function
> > > >
> > > > End Class
> > > >
> > > >
> > >
> > >
> >
> >
>
>