0

I have access to some VC++ source code for which I am trying to convert to VB.NET. I previously asked a question regarding bit shifting, and although the answers given made sense and seemed rather simple to convert over to VB.NET, I am having difficulty getting things to work out. Here is some VC++ code that I am needing to convert to VB.NET:

#define bitShift(_val) \
((u64)(((((u64)_val) & 0xff00000000000000ull) >> 56) | \
       ((((u64)_val) & 0x00ff000000000000ull) >> 40) | \
       ((((u64)_val) & 0x0000ff0000000000ull) >> 24) | \
       ((((u64)_val) & 0x000000ff00000000ull) >> 8 ) | \
       ((((u64)_val) & 0x00000000ff000000ull) << 8 ) | \
       ((((u64)_val) & 0x0000000000ff0000ull) << 24) | \
       ((((u64)_val) & 0x000000000000ff00ull) << 40) | \
       ((((u64)_val) & 0x00000000000000ffull) << 56)))

Now, the returned value will be used as the counter for AES decryption in CTR Mode. The following VC++ code is used to calculate the counter:

u8 counter[16];

*(u64 *)(counter + 0) = bitShift(i);
*(u64 *)(counter + 8) = 0;

This is where I am currently at with the VB.NET code:

Public Function SwapBits(ByVal value As Int64) As Int64
    Dim uvalue As UInt64 = CULng(value)
    Dim swapped As UInt64 = ((&HFF00000000000000UL) And (uvalue >> 56) Or _
                            (&HFF000000000000L) And (uvalue >> 40) Or _
                            (&HFF0000000000L) And (uvalue >> 24) Or _
                            (&HFF00000000L) And (uvalue >> 8) Or _
                            (&HFF000000UI) And (uvalue << 8) Or _
                            (&HFF0000) And (uvalue << 24) Or _
                            (&HFF00) And (uvalue << 40) Or _
                            (&HFF) And (uvalue << 56))

    Return CLng(swapped)
End Function

Here is the code used to create the counter:

Dim blocks As Integer = file_size / 16

For i As Integer = 0 To blocks - 1
    Dim buffer As Byte() = New Byte(15) {}
    Array.Copy(BitConverter.GetBytes(SwapBits(CULng(i))), 0, buffer, 0, 8)

    'AES decryption takes place after this...

The counter is 16 bytes, but only the first 8 bytes are encrypted using AES 128 bit EBC and then XOR'd with the current encrypted block of data which is also 16 bytes (AES CTR Mode). I can get the code to run without any errors, but the output of decrypted data is incorrect which leads me to believe I am not calculating the counter which is being used for encryption correctly.

Once again, any help is obviously appreciated, and thanks in advance!

EDIT: Current SwapBits function... still not right though

Public Function SwapBits(ByVal uvalue As UInt64) As UInt64
    Dim swapped As UInt64 = ((((uvalue) And &HFF00000000000000) >> 56) Or _
                            (((uvalue) And &HFF000000000000) >> 40) Or _
                            (((uvalue) And &HFF0000000000) >> 24) Or _
                            (((uvalue) And &HFF00000000) >> 8) Or _
                            (((uvalue) And &HFF000000) << 8) Or _
                            (((uvalue) And &HFF0000) << 24) Or _
                            (((uvalue) And &HFF00) << 40) Or _
                            (((uvalue) And &HFF) << 56))

    Return swapped
End Function

This actually causes an "Arithmetic operation resulted in an overflow." error when uvalue reaches a value of 128. When the value of 1 is passed to SwapBits, my return value = 72057594037927936. My interpretation of the VC++ code is that my counter should simply be a 16 byte array incrementing by 1 each time. For example, if

uvalue = 1

then my counter needs to be

0000000100000000

if

uvalue = 25

then my counter needs to be

0000002500000000

etc, etc... Or I am misinterpreting something somewhere?

Jay
  • 885
  • 1
  • 7
  • 9
  • Try grouping each And expression together with parentheses since that's the way the C++ code is written. – tinstaafl Jan 20 '14 at 04:07
  • @tinstaafl, still get the same incorrect output. Thanks for the suggestion though. – Jay Jan 20 '14 at 04:39
  • One other thing I noticed the hex numbers in the c++ code are all cast the same, but you've got them being cast differently in the vb code. By not casting them all the same they'll have different bit counts. – tinstaafl Jan 20 '14 at 04:43
  • Still get the same outcome. The first 16 bytes in hexadecimal should read "00 00 00 52 45 17 AF E5 00 00 00 00 45 17 AF E5" and I get "06 8E B4 6B 33 B7 7F E7 93 1A 45 E1 24 6C F5 01". Starting to wonder if the counter actually isn't being calculated incorrectly and that maybe something else is going wrong. – Jay Jan 20 '14 at 05:05
  • looking at your code again it looks to me that you have the hex numbers and the uvalue backwards. Try shifting the hex number and ANDing with the uvlaue – tinstaafl Jan 20 '14 at 06:49
  • The function SwapBits in VB.NET is always returning 0 which is why the decryption fails. Anyone know the VB.NET conversion of bitShift above? – Jay Jan 20 '14 at 06:53
  • @tinstaafl I have already tried that, current code for the SwapBits function is in my edited question above. – Jay Jan 20 '14 at 07:06

2 Answers2

1

Not sure what you're expecting from the C++ code. But when I use this:

#include <iostream>

using namespace std;

#define bitShift(_val) \
((unsigned __int64)(((((unsigned __int64)_val) & 0xff00000000000000ull) >> 56) | \
       ((((unsigned __int64)_val) & 0x00ff000000000000ull) >> 40) | \
       ((((unsigned __int64)_val) & 0x0000ff0000000000ull) >> 24) | \
       ((((unsigned __int64)_val) & 0x000000ff00000000ull) >> 8 ) | \
       ((((unsigned __int64)_val) & 0x00000000ff000000ull) << 8 ) | \
       ((((unsigned __int64)_val) & 0x0000000000ff0000ull) << 24) | \
       ((((unsigned __int64)_val) & 0x000000000000ff00ull) << 40) | \
       ((((unsigned __int64)_val) & 0x00000000000000ffull) << 56)))


int main()
{
    unsigned __int64 test = bitShift(25);
    return 0;
}

I get the exact same return value(1801439850948198400 || &H1900000000000000) as this:

Dim result As ULong = SwapBits(25)

Public Function SwapBits(ByVal uvalue As UInt64) As UInt64
    Dim swapped As UInt64 = ((((uvalue) And &HFF00000000000000UL) >> 56) Or _
                            (((uvalue) And &HFF000000000000UL) >> 40) Or _
                            (((uvalue) And &HFF0000000000UL) >> 24) Or _
                            (((uvalue) And &HFF00000000UL) >> 8) Or _
                            (((uvalue) And &HFF000000UL) << 8) Or _
                            (((uvalue) And &HFF0000UL) << 24) Or _
                            (((uvalue) And &HFF00UL) << 40) Or _
                            (((uvalue) And &HFFUL) << 56))

    Return swapped
End Function

I don't have much experience in C++, care to share what this is doing:

u8 counter[16]; 
*(u64 *)(counter + 0) = bitShift(i); 
*(u64 *)(counter + 8) = 0;

basically that section of code increments the first 8 bytes of counter by 1 each iteration 0f i, starting with the right most byte and expanding left for each carryover. For instance, if the counter reaches 999 counter[7] will hold 231(&HE7) and counter[6] 3(&H3) which when you look at the whole array gives, &H000000000003E7 which equals 999 decimal.

tinstaafl
  • 6,908
  • 2
  • 15
  • 22
  • This seems to be on the right track, due to the data type it was hard to recognize the counter incrementing by 1 each time it was called in a for loop. However, after some sleep and your post above it seems correct. I don't have much experience in C++, care to share what this is doing: 'u8 counter[16]; *(u64 *)(counter + 0) = bitShift(i); *(u64 *)(counter + 8) = 0;' – Jay Jan 20 '14 at 23:58
  • Do you have a link for the complete C++ source code? That snippet is too incomplete and kind of looks like pseudo-code. – tinstaafl Jan 21 '14 at 00:19
  • Here is a link to the entire function http://pastebin.com/zY4uhtQ2 All it is is AES encryption/decryption in ECB mode with a counter. The issue with VB.NET, is that the CryptoServiceProvider does not support CTR mode. The counter (8 bytes) is being calculated by the bitShift function in my original post. The encrypted data is passed to the decrypt function (16 byte blocks of data), the counter is calculated and then encrypted with the key, each encrypted byte is then XOR'd with each byte of the encrypted counter. I believe my counter is wrong, which results in the output being incorrect. – Jay Jan 21 '14 at 01:38
  • @user3126746 I added an explanation. – tinstaafl Jan 22 '14 at 17:20
  • although I am not getting the proper decrypted text, everything you have helped with has been spot on so I am going to accept your answer and would like to thank you for your help. When I do a BitConverter.GetBytes(SwapBits(CULng(i))) where i = 999 I get "00 00 00 00 00 00 03 E7" converted to hexadecimal as the output which is expected as you said. So the issue obviously lies elsewhere. Once again, thanks for your help and patience. – Jay Jan 23 '14 at 00:00
0

Something tells me conversion is better done using the GetBytes and ToUInt64() methods, a for loop and a temporary variable. It would be much easier to read and probably fast enough for most purposes.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263