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;
}
> 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]