Click here to Skip to main content
Click here to Skip to main content

RC6 encryption and decryption

By , 14 Jul 2002
 

Sample Image -
screenshot.jpg

Introduction

RC6 is an evolutionary improvement of RC5, designed to meet the requirements of the Advanced Encryption Standard (AES). Like RC5, RC6 makes essential use of data-dependent rotations. New features of RC6 include the use of four working registers instead of two, and the inclusion of integer multiplication as an additional primitive operation. The use of multiplication greatly increases the diffusion achieved per round, allowing for greater security, fewer rounds, and increased throughput. I found an article about it online and fulfilled the algorithm using C++ for fun. Hope it'd be helpful to some interested people.

Details of RC6

Like RC5, RC6 is a fully parameterized family of encryption algorithms. A version of RC6 is more accurately specified as RC6-w/r/b where the word size is w bits, encryption consists of a nonnegative number of rounds r, and b denotes the length of the encryption key in bytes. Since the AES submission is targeted at w = 32 and r = 20, we shall use RC6 as shorthand to refer to such versions. When any other value of w or r is intended in the text, the parameter values will be specified as RC6-w/r. Of particular relevance to the AES effort will be the versions of RC6 with 16-, 24-, and 32-byte keys. For all variants, RC6-w/r/b operates on units of four w-bit words using the following six basic operations. The base-two logarithm of w will be denoted by lgw.

  • a + b: integer addition modulo 2^w
  • a - b: integer subtraction modulo 2^w
  • a @ b: bitwise exclusive-or of w-bit words
  • a * b: integer multiplication modulo 2^w
  • a <<< b: rotate the w-bit word a to the left by the amount given by the least significant lgw bits of b
  • a >>> b: rotate the w-bit word a to the right by the amount given by the least significant lgw bits of b

Note that in the description of RC6 the term "round" is somewhat analogous to the usual DES-like idea of a round: half of the data is updated by the other half; and the two are then swapped. In RC5, the term "half-round" was used to describe this style of action, and an RC5 round was deemed to consist of two half-rounds. This seems to have become a potential cause of confusion, and so RC6 reverts to using the term "round" in the more established way.

To get the detailed algorithm description of RC6-w/r/b. Please read the article "The RC6 Block Cipher" by Ronald L. Rivest, M.J.B. Robshaw, R. Sidney and, Y.L. Yin.

Details of Code

In my program, I fulfilled RC6-32/16. Since the integer addition, subtraction and multiplication don't exceed 2^32 in my program, I don't let their results modulo 2^32 like the operations described above. Anyway, the encryption and decryption go well.

I wrapped the bits rotation operations in two functions DWORD CHexDoc::LeftRotate(DWORD dwVar, DWORD dwOffset) and DWORD CHexDoc::RightRotate(DWORD dwVar, DWORD dwOffset).

DWORD CHexDoc::LeftRotate(DWORD dwVar, DWORD dwOffset)
{
    DWORD temp1, temp2;

    temp1 = dwVar >> (W - dwOffset);
    temp2 = dwVar << dwOffset;
    temp2 = temp2 | temp1;

    return temp2;
}

DWORD CHexDoc::RightRotate(DWORD dwVar, DWORD dwOffset)
{
    DWORD temp1, temp2;

    temp1 = dwVar << (W - dwOffset);
    temp2 = dwVar >> dwOffset;
    temp2 = temp2 | temp1;

    return temp2;
}

The key generation part is like

void CHexDoc::KeyGen(DWORD dwKey)
{
    DWORD P32 = 0xB7E15163;
    DWORD Q32 = 0x9E3779B9;
    DWORD i, A, B;
    DWORD dwByteOne, dwByteTwo, dwByteThree, dwByteFour;

    dwByteOne = dwKey >> 24;
    dwByteTwo = dwKey >> 8;
    dwByteTwo = dwByteTwo & 0x0010;
    dwByteThree = dwKey << 8;
    dwByteThree = dwByteThree & 0x0100;
    dwByteFour = dwKey << 24;

    dwKey = dwByteOne | dwByteTwo | dwByteThree
        | dwByteFour;

    m_dwS[0] = P32;

    for(i = 1; i < 2 * R + 4; i++)
        m_dwS[i] = m_dwS[i - 1] + Q32;

    i = A = B = 0;

    int v = 3 * max(1, 2 * R + 4);

    for(int s = 1; s <= v; s++)
    {
        A = m_dwS[i] = LeftRotate(m_dwS[i] + A + B, 
            OffsetAmount(3));
        B = dwKey = LeftRotate(dwKey + A + B, 
            OffsetAmount(A + B));

        i = (i + 1) % (2 * R + 4);
    }
}

Finally, the core parts of encryption and decryption are as following:

// encrypt the file
void CHexDoc::EncodeFile()
{
    DWORD* pdwTemp;

    for(UINT i = 0; i < m_nDocLength; i += 16)
    {
        pdwTemp = (DWORD*)&m_pFileData[i];

        pdwTemp[0] = (pdwTemp[0] - m_dwS[2 * R + 2]);
        pdwTemp[2] = (pdwTemp[2] - m_dwS[2 * R + 3]);

        for(int j = R; j >= 1; j--)
        {
            DWORD temp = pdwTemp[3];
            pdwTemp[3] = pdwTemp[2];
            pdwTemp[2] = pdwTemp[1];
            pdwTemp[1] = pdwTemp[0];
            pdwTemp[0] = temp;

            DWORD t = 
                LeftRotate((pdwTemp[1] * (2 * pdwTemp[1] + 1)),
                OffsetAmount((DWORD)(log((double)W)/log(2.0))));
            DWORD u = 
                LeftRotate((pdwTemp[3] * (2 * pdwTemp[3] + 1)),
                OffsetAmount((DWORD)(log((double)W)/log(2.0))));
            pdwTemp[0] =
                (RightRotate((pdwTemp[0] - m_dwS[2 * j]),
                OffsetAmount(u))) ^ t;
            pdwTemp[2] = 
                (RightRotate((pdwTemp[2] - m_dwS[2 * j + 1]),
                OffsetAmount(t))) ^ u;
        }

        pdwTemp[1] = (pdwTemp[1] - m_dwS[0]);
        pdwTemp[3] = (pdwTemp[3] - m_dwS[1]);
    }
    pdwTemp = NULL;
    SetModifiedFlag(TRUE);

    POSITION pos = GetFirstViewPosition();
    while(pos != NULL)
    {
        CView* pView = GetNextView(pos);
        pView->RedrawWindow();
    }
}

// decrypt the file
void CHexDoc::DecodeFile()
{
    DWORD* pdwTemp;

    for(UINT i = 0; i < m_nDocLength; i += 16)
    {
        pdwTemp = (DWORD*)&m_pFileData[i];

        pdwTemp[1] = (pdwTemp[1] + m_dwS[0]);
        pdwTemp[3] = (pdwTemp[3] + m_dwS[1]);

        for(int j = 1; j <= R; j++)
        {
            DWORD t = 
                LeftRotate((pdwTemp[1] * (2 * pdwTemp[1] + 1)),
                OffsetAmount((DWORD)(log((double)W)/log(2.0))));
            DWORD u = 
                LeftRotate((pdwTemp[3] * (2 * pdwTemp[3] + 1)),
                OffsetAmount((DWORD)(log((double)W)/log(2.0))));
            pdwTemp[0] = 
                (LeftRotate(pdwTemp[0] ^ t, OffsetAmount(u)) +
                m_dwS[2 * j]);
            pdwTemp[2] = 
                (LeftRotate(pdwTemp[2] ^ u, OffsetAmount(t)) +
                m_dwS[2 * j + 1]);

            DWORD temp = pdwTemp[0];
            pdwTemp[0] = pdwTemp[1];
            pdwTemp[1] = pdwTemp[2];
            pdwTemp[2] = pdwTemp[3];
            pdwTemp[3] = temp;
        }

        pdwTemp[0] = (pdwTemp[0] + m_dwS[2 * R + 2]);
        pdwTemp[2] = (pdwTemp[2] + m_dwS[2 * R + 3]);
    }
    pdwTemp = NULL;
    SetModifiedFlag(TRUE);

    POSITION pos = GetFirstViewPosition();
    while(pos != NULL)
    {
        CView* pView = GetNextView(pos);
        pView->RedrawWindow();
    }
}

Conclusion

In the view window, I showed the Hex and Char content of the loaded file and their addresses. You can see the changes every time you encrypt/decrypt it. Thanks!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Mingming Lu
Web Developer
United States United States
Member
Hey you,
Out there in the cold,
Getting lonely, getting old,
Can you feel me?
Hey you,
Standing in the aisle,
With itchy feet and fading smile,
Can you feel me?
Hey you,
Don't help them to bury the light.
Don't give in without a fight.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalrc6 in jarmemberendra hermawan27 May '09 - 22:55 
help me please..anyone have source code "encryption sms rc6 in java (j2me)"
 
please send to me dexendra_sinting666@yahoo.co.id
 
thanksss!!!!
GeneralThe bug with overrunmembermircea13131325 Apr '09 - 1:24 
I've compiled the code in VS 2005. but if i try to encrypt a file whose length does not devide by 16 (DWORD) i canot decrypt it back.
this bug was mentioned in an previous post:
 
Load a short file with text which has a length not divisible by 16; debug using [View menu][debug windows][Memory] window to watch the buffer pdwTemp[0] in the CHexDoc::EncodeFile() function:
Set the window once you've stepped over this line:
pdwTemp = (DWORD*)&m_pFileData[i];
Then Step Out Of the function and watch as the code writes onto the FDFDFDFD marking the end of the buffer which belong to the system...
 
This is a consequence of the 4-DWORD-at-a-time access:
for(UINT i = 0; i < m_nDocLength; i += 16)
so you must make sure that the data you're encrypting is in a buffer with an extra 16 Bytes of 'space' after it to avoid overwriting memory.
Just how you implement this will depend on the application:
memcpy or CString::GetBufferSetLength(...) may be useful.
regards

 

Has anyone solved this ?
Thank you!
Questionis there a rc6 algorithm in vb.netmembermoonshaddow30 Oct '08 - 15:35 
i looked on the net and could not find anything
 
J.Hardy

GeneralHep block error...memberRoel Virgel L. Baldon6 Oct '08 - 23:28 
I have encountered a heap block error pointing to dbgheap.c _CrtIsMemoryBlock function.
 
I noticed that this only happened if the file is around 240KB or more.
Is this one of the limit of the application?
 
If not, can somebody please help me fix this error.
GeneralI have a errors, help me [modified]memberSrgteam22 Nov '07 - 14:58 
Hello to all,
I dowbload the source code of this project and opened im Visual Studio 2005, then i converted this project. (Visual Studio asked me) And when i start compiling i see one error:
 
In function CHexView::FormatLine
hexenc_src\hexencview.cpp(182) : error C2679: binary '+=' : no operator found which takes a right-hand operand of type 'BYTE [17]' (or there is no acceptable conversion)
 
Tell me please, what need to do?
 

 
Sorry for my English Smile | :)
GeneralPls Help~~;memberofuka14 Mar '06 - 22:07 
Im doing my FYP for the final year..My supervisor had asked me to include the encryption for the password that contained inside a text file.....
I had downloaded this source code and run it..but it shows me two errors..i don't know what's wrong with the code.....
below was the error that was pointed to....
Cry | :((
 
typedef UINT_PTR KSPIN_LOCK;
 
ofuka
GeneralDES cryptanalysis with 6 roundsmembernasor6 May '05 - 23:14 

Is there any body that has a code in C++ for differential attack on reduced DES to 6 rounds? If you have, please send me a copy of it, if possible for you.
 
Thanks a lot in advance.
Regards,
Nasoor

 
salame man be to yare ghadimi
GeneralRC3, RC4, RC5, RC6sussMansureh Shahraki3 Feb '05 - 6:00 
Dear all,
I am looking for good and complete tutorials about these cryptography algorithms:
RC3, RC4, RC5, RC6.
Would you please help me?
 
Mansureh (shahraki@rediffmail.com)
GeneralRe: RC3, RC4, RC5, RC6memberMingming Lu3 Feb '05 - 6:14 
you may wanna check out the book "Applied Cryptography, Second Edition: Protocols, Algorthms, and Source Code in C" by Bruce Schneier. It has the exhausted descriptions of many cryptography algorithms. BTW, google is another good way to meet your needs.
 
IS THERE ANYBODY OUT THERE?
QuestionPlease help me ?memberlonelywind198218 Mar '04 - 21:47 
I wrote again this code to Visual C# but my program only Encode, DeEncode is true with length of file mod 16 =0;
This is my code, please help me.
 
private void EncodeFile(string fileRead,string fileWrite)
{
FileStream sourceStream = new FileStream(fileRead, FileMode.Open, FileAccess.Read);
FileStream destinationStream = new FileStream(fileWrite, FileMode.Create, FileAccess.Write);
long TotalLen=sourceStream.Length;
int Len;
long rdLen=0;
int count=0;
byte[] bufferStream = new byte[4096] ;
UInt32[] Data=new UInt32[4];
byte[] buffer=new byte[16];


while(rdLen"<"TotalLen)
{
Len=sourceStream.Read(bufferStream,0,4096);

for(int i = 0; i < Len; i += 16)
{



Data[0]=BitConverter.ToUInt32(bufferStream,i+0);
Data[1]=BitConverter.ToUInt32(bufferStream,i+4);
Data[2]=BitConverter.ToUInt32(bufferStream,i+8);
Data[3]=BitConverter.ToUInt32(bufferStream,i+12);

Data[1]=(Data[1]+m_dwS[0]);
Data[3]=(Data[3]+m_dwS[1]);
 
for(int j = 1; j <= R; j++)
{
UInt32 t = LeftRotate((Data[1] * (2 * Data[1] + 1)),
OffsetAmount((UInt32)(Math.Log((double)W)/Math.Log(2.0))));
UInt32 u = LeftRotate((Data[3] * (2 * Data[3] + 1)),
OffsetAmount((UInt32)(Math.Log((double)W)/Math.Log(2.0))));

Data[0] = (LeftRotate(Data[0] ^ t, OffsetAmount(u)) + m_dwS[2 * j]);
Data[2] = (LeftRotate(Data[2] ^ u, OffsetAmount(t)) + m_dwS[2 * j + 1]);

UInt32 temp = Data[0];
Data[0] = Data[1];
Data[1] = Data[2];
Data[2] = Data[3];
Data[3] = temp;
}
Data[0] = (Data[0] + m_dwS[2 * R + 2]);
Data[2] = (Data[2] + m_dwS[2 * R + 3]);
count=0;
for(int index=0;index<16;index+=4)
{
buffer[index]=(byte)((Data[count]&0x000000FF)>>0);
buffer[index+1]=(byte)((Data[count]&0x0000FF00)>>8);
buffer[index+2]=(byte)((Data[count]&0x00FF0000)>>16);
buffer[index+3]=(byte)((Data[count]&0xFF000000)>>24);
count++;
}

 
Array.Copy(buffer,0,bufferStream,i,buffer.Length);
}
destinationStream.Write(bufferStream,0,Len);
rdLen=rdLen+Len;
}
}
 

private void DeEncodeFile(string fileRead,string fileWrite)
{
FileStream sourceStream = new FileStream(fileRead, FileMode.Open, FileAccess.Read);
FileStream destinationStream = new FileStream(fileWrite, FileMode.Create, FileAccess.Write);
long TotalLen=sourceStream.Length;
int Len;
long rdLen=0;
int count=0;
byte[] bufferStream = new byte[4096] ;
byte[] buffer=new byte[16];
UInt32[] Data=new UInt32[4];
while(rdLen"<"TotalLen)
{
Len=sourceStream.Read(bufferStream,0,4096);

for(int i = 0; i < Len; i += 16)
{
Data[0]=BitConverter.ToUInt32(bufferStream,i+0);
Data[1]=BitConverter.ToUInt32(bufferStream,i+4);
Data[2]=BitConverter.ToUInt32(bufferStream,i+8);
Data[3]=BitConverter.ToUInt32(bufferStream,i+12);

Data[0]=(Data[0]-m_dwS[2*R+2]);
Data[2]=(Data[2]-m_dwS[2*R+3]);

 
for(int j = R; j >=1; j--)
{
UInt32 temp = Data[3];
Data[3]=Data[2];
Data[2]=Data[1];
Data[1]=Data[0];
Data[0]=temp;
UInt32 t = LeftRotate((Data[1] * (2 * Data[1] + 1)),
OffsetAmount((UInt32)(Math.Log((double)W)/Math.Log(2.0))));
UInt32 u = LeftRotate((Data[3] * (2 * Data[3] + 1)),
OffsetAmount((UInt32)(Math.Log((double)W)/Math.Log(2.0))));
Data[0]=(RightRotate((Data[0]-m_dwS[2*j]),OffsetAmount(u)))^t;
Data[2]=(RightRotate((Data[2]-m_dwS[2*j+1]),OffsetAmount(t)))^u;

}
Data[1]=(Data[1]-m_dwS[0]);
Data[3]=(Data[3]-m_dwS[1]);
count=0;

for(int index=0;index<16;index+=4)
{

buffer[index]=(byte)((Data[count]&0x000000FF)>>0);
buffer[index+1]=(byte)((Data[count]&0x0000FF00)>>8);
buffer[index+2]=(byte)((Data[count]&0x00FF0000)>>16);
buffer[index+3]=(byte)((Data[count]&0xFF000000)>>24);
count++;
}
Array.Copy(buffer,0,bufferStream,i,buffer.Length);

}
destinationStream.Write(bufferStream,0,Len);
rdLen=rdLen+Len;
}
}
 

 
private void KeyGen(UInt32 dwKey)
{
UInt32 P32=0xB7E15163;
UInt32 Q32 = 0x9E3779B9;
UInt32 i,A, B;
UInt32 dwByteOne, dwByteTwo, dwByteThree, dwByteFour;

dwByteOne = dwKey >> 24;
dwByteTwo = dwKey >> 8;
dwByteTwo = dwByteTwo & 0x0010;
dwByteThree = dwKey << 8;
dwByteThree = dwByteThree & 0x0100;
dwByteFour = dwKey << 24;
 
dwKey = dwByteOne | dwByteTwo | dwByteThree | dwByteFour;
 
m_dwS[0] = P32;
for(i = 1; i < 2 * R + 4; i++)
m_dwS[i] = m_dwS[i - 1] + Q32;
 
A = B =i= 0;

int v = 3 * max(1, 2 * R + 4);
 
for(int s = 1; s <= v; s++)
{
A = m_dwS[i] = LeftRotate(m_dwS[i] + A + B, OffsetAmount(3));
B = dwKey = LeftRotate(dwKey + A + B, OffsetAmount(A + B));
 
i =( (i + 1) %((UInt32)(2 * R + 4)));
}
 
}

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 15 Jul 2002
Article Copyright 2002 by Mingming Lu
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid