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
> > > >
> > > >
> > >
> > >
> >
> >
>
>



Relevant Pages

  • Re: DES ECB Encryption cannot decrypt
    ... padding, that is why you are getting 16 bytes of ciphertext. ... PaddingMode.None for both encrypting and decrypting algorithm object. ... ToBase64 in the encrypting method to get a string out of the encrypted ...
    (microsoft.public.dotnet.security)
  • Re: DES ECB Encryption cannot decrypt
    ... > padding, that is why you are getting 16 bytes of ciphertext. ... > PaddingMode.None for both encrypting and decrypting algorithm object. ... pass the string around and use FromBase64 in the decrypting method ...
    (microsoft.public.dotnet.security)
  • RSA encrypt/decrypt of byte array
    ... I'm encrypting and then decrypting a byte array using the ... The byte array is 52 bytes in length. ... I then pass this string along to the decryption function. ...
    (microsoft.public.dotnet.security)
  • Re: text encryption but with some requirememnts
    ... And if you want to change a text for encrypting purposes how do you know what characters are you allowed to use and which ones to avoid? ... In other words - encrypt string to byte array, convert byte array to base64 string. ...
    (microsoft.public.vb.general.discussion)
  • Re: text encryption but with some requirememnts
    ... And if you want to change a text for encrypting purposes how do you know what characters are you allowed to use and which ones to avoid? ... In other words - encrypt string to byte array, convert byte array to base64 string. ...
    (microsoft.public.vb.general.discussion)