vb.netvisual-c++aescode-conversionaescryptoserviceprovider

AES 128 CTR Mode Bit Shifting to Create Counter


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?


Solution

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