AES/CTR Mode

114 views
Skip to first unread message

Jeffrey Walton

unread,
Dec 15, 2007, 1:37:38 PM12/15/07
to Crypto++
Hi Eva,

Here is some code I prototyped a while back. It performs the
encryption/decryption in memory using random values. If you
modify it to work with streams and it breaks, I'd say you are
probably having CR/LF conversion issues.

I have not had time to look at CTR Mode to see if Resyncronize()
performs an XOR on the IV(nonce) and the Counter. I suspect you will
have to do it yourself:

CTR_Mode< AES >::Encryption encryptor;
encryptor.SetKeyWithIV( key, sizeof( key ), iv );

// ctr = {0,0,0,...} or {1,1,1,...}, etc
byte ctr[ AES::BLOCKSIZE ];
memset( ctr, counter, sizeof( ctr ) );

encryptor.Resynchronize( ctr );

Jeff

#include "aes.h"
#include "modes.h"
#include "filters.h"
#include "osrng.h"

#include <iostream>
#include <string>

using namespace CryptoPP;
using std::string;
using std::cout;
using std::endl;

bool Initialize( string& plain, string& cipher, string& recovered );

bool Encrypt( const string& plain, int counter, string& cipher );
bool Decrypt( const string& cipher, int counter, string& recovered );

const unsigned int ITERATIONS = 8;

const unsigned int BLOCKSIZE = 1024 * 64;
const unsigned int SUBBLOCKCOUNT = 4;
const unsigned int SUBBLOCKSIZE =
BLOCKSIZE / SUBBLOCKCOUNT;

byte key[ AES::DEFAULT_KEYLENGTH ];
byte iv[ AES::BLOCKSIZE ];

int main(int argc, char* argv[])
{
memset( key, 0x01, AES::DEFAULT_KEYLENGTH );
memset( iv, 0x01, AES::BLOCKSIZE );

string plain, cipher, recovered;

for( int i = 0; i < ITERATIONS; i++ )
{
Initialize( plain, cipher, recovered );

for( int j = 0; j < SUBBLOCKCOUNT; j++ )
{
string substring = plain.substr( j*SUBBLOCKSIZE, SUBBLOCKSIZE );

Encrypt( substring, j, cipher );
}

for( int j = 0; j < SUBBLOCKCOUNT; j++ )
{
string substring = cipher.substr( j*SUBBLOCKSIZE, SUBBLOCKSIZE );

Decrypt( substring, j, recovered );
}

if( plain == recovered )
{
cout << "Iteration " << i << " - OK" << endl;
}
else
{
cout << "Iteration " << i << " - Bad" << endl;
assert( false );
}
}

return 0;
}

bool Initialize( string& plain, string& cipher, string& recovered )
{
try
{
plain.clear();
cipher.clear();
recovered.clear();

AutoSeededRandomPool rng;
RandomNumberSource( rng, BLOCKSIZE, true,
new StringSink( plain )
);

assert( BLOCKSIZE == plain.size() );
}

catch( ... ) { return false; }

return true;
}

bool Encrypt( const string& plain, int counter, string& cipher )
{
try
{
CTR_Mode< AES >::Encryption encryptor;
encryptor.SetKeyWithIV( key, sizeof( key ), iv );

// ctr = {0,0,0,...} or {1,1,1,...}, etc
byte ctr[ AES::BLOCKSIZE ];
memset( ctr, counter, sizeof( ctr ) );

encryptor.Resynchronize( ctr );

StreamTransformationFilter stfaese( encryptor,
new StringSink( cipher ) );
stfaese.Put( (const byte*)plain.c_str(), plain.size() );
stfaese.MessageEnd();
}

catch( ... ) { return false; }

return true;
}

bool Decrypt( const string& cipher, int counter, string& recovered )
{
try
{
CTR_Mode< AES >::Decryption decryptor;
decryptor.SetKeyWithIV( key, sizeof( key ), iv );

// ctr = {0,0,0,...} or {1,1,1,...}, etc
byte ctr[ AES::BLOCKSIZE ];
memset( ctr, counter, sizeof( ctr ) );

decryptor.Resynchronize( ctr );

StreamTransformationFilter stfaesd( decryptor,
new StringSink( recovered ) );
stfaesd.Put( (const byte*)cipher.c_str(), cipher.size() );
stfaesd.MessageEnd();
}

catch( ... ) { return false; }

return true;
}

Jeffrey Walton

unread,
Dec 15, 2007, 8:02:01 PM12/15/07
to Crypto++
Hi Eva,

> I have not had time to look at CTR Mode to see if
> Resyncronize() performs an XOR on the IV(nonce)
> and the Counter.

Crypto++ handles the increment function over the entire blocksize. So
there is no need for the nonce/counter method. You will have to manage
getting the proper counter to the resyncronize function based on the
blocksize.

See http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf

Jeff

inline void CTR_ModePolicy::ProcessMultipleBlocks(
byte *output, const byte *input, size_t n)
{
unsigned int s = BlockSize(), j = 0;
for (unsigned int i=1; i<n; i++, j+=s)
IncrementCounterByOne
(m_counterArray + j + s, m_counterArray + j, s);
m_cipher->ProcessAndXorMultipleBlocks
(m_counterArray, input, output, n);
IncrementCounterByOne
(m_counterArray, m_counterArray + s*(n-1), s);
}

On 12/15/07, Jeffrey Walton <nolo...@gmail.com> wrote:
> Hi Eva,
>
> Here is some code I prototyped a while back. It performs the
> encryption/decryption in memory using random values. If you
> modify it to work with streams and it breaks, I'd say you are
> probably having CR/LF conversion issues.
>
> I have not had time to look at CTR Mode to see if Resyncronize()
> performs an XOR on the IV(nonce) and the Counter. I suspect you will
> have to do it yourself:
>
> CTR_Mode< AES >::Encryption encryptor;
> encryptor.SetKeyWithIV( key, sizeof( key ), iv );
>
> // ctr = {0,0,0,...} or {1,1,1,...}, etc
> byte ctr[ AES::BLOCKSIZE ];
> memset( ctr, counter, sizeof( ctr ) );
>
> encryptor.Resynchronize( ctr );
>
> Jeff
>

> [SNIP]

Reply all
Reply to author
Forward
0 new messages