Hi Wei,
As requested.
Is it possible to specify a ChannelSwitch as the sink in the filter?
Jeff
On 3/2/09, Wei Dai <[email protected]> wrote:
> Hi, I'm having trouble reproducing the problem you're having. Can you send
> me the complete test code?
>
> --------------------------------------------------
> From: "Jeffrey Walton" <[email protected]>
> Sent: Monday, March 02, 2009 4:14 PM
> To: "Crypto++" <[email protected]>
> Subject: Crypto++ 5.6, CCM Mode, Decryption/Verification
>
> >
> >
> > Hi All/Wei,
> >
> > Sorry to be wearing out the list today. I'm catching some odd
> > behavior, part of which is surely due to my mistakes. But if I make
> > the mistake, others will also since there is nothing special about me
> > (theory of mediocrity).
> >
> > // Cipher text generated as follows
> > string adata="Authenticated";
> > string pdata="Authenticated Encryption";
> > string cipher;
> >
> > CCM< AES, 96 >::Encryption e;
> > AuthenticatedEncryptionFilter ef( e,
> > new StringSink( cipher )
> > ); // AuthenticatedEncryptionFilter
> >
> > Taking default values, I expect to get either 1) authenticated data or
> > 2) decrypted and authenticated data:
> >
> > CCM< AES >::Decryption d;
> > AuthenticatedDecryptionFilter df( d,
> > new StringSink( recovered )
> > ); // AuthenticatedDecryptionFilter
> >
> > df.Put( cipher.c_str(), cipher.length() );
> > df.MessageEnd();
> >
> > When I inspected recovered, I found I had a truncated string from the
> > default (encrypted and authenticated) channel.
> > Presented: "Authenticated Encryption"
> > Recovered: "Authenticated Encryp"
> >
> > The problem was that the encryptor specified a 96 bit tag, and the
> > decryptor took a default tag length. I expected that since the tag
> > length was encoded through the formatting function, the tag length
> > used to encrypt would be available.
> >
> > First Observation: Is there any way to protect me from myself?
> >
> > Next issue: I am able to extract the encrypted data from the default
> > channel, but upon calling MessageEnd(), the filter throws "message
> > length does not match that given in SpecifyDataLengths". So I get the
> > data and the exception is thrown.
> >
> > Any ideas on how to feed the cipher text into the decryptor and call
> > MessageEnd() without an exception? I've tried specifying flags,
> > pading, and PutChannel(...).
> >
> > CCM< AES, 96 >::Encryption e;
> > e.SetKeyWithIV( key, sizeof(key), iv );
> > ...
> > AuthenticatedEncryptionFilter ef( e,
> > new StringSink( cipher )
> > ); // AuthenticatedEncryptionFilter
> >
> > // Add ADATA and PDATA
> > ef.MessageEnd();
> > ...
> >
> > CCM< AES, 96 >::Decryption d;
> > d.SetKeyWithIV( key, sizeof(key), iv );
> >
> > AuthenticatedDecryptionFilter df( d,
> > new StringSink( recovered )
> > ); // AuthenticatedDecryptionFilter
> >
> > df.Put( cipher.c_str(), cipher.length() );
> > df.MessageEnd( );
> >
> > Jeff
> >
> > > >
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the "Crypto++ Users"
Google Group.
To unsubscribe, send an email to [email protected].
More information about Crypto++ and this group is available at
http://www.cryptopp.com.
-~----------~----~----~----~------~----~------~--~---
// Driver.cpp
//
#include "stdafx.h"
#include "osrng.h"
using CryptoPP::AutoSeededRandomPool;
#include <iostream>
using std::cout;
using std::cerr;
#include <string>
using std::string;
using std::auto_ptr;
#include "hex.h"
using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;
#include "cryptlib.h"
using CryptoPP::BufferedTransformation;
using CryptoPP::AuthenticatedSymmetricCipher;
#include "filters.h"
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::AuthenticatedEncryptionFilter;
using CryptoPP::AuthenticatedDecryptionFilter;
#include "channels.h"
using CryptoPP::ChannelSwitch;
#include "aes.h"
using CryptoPP::AES;
#include "ccm.h"
using CryptoPP::CCM;
#include "assert.h"
int main(int argc, char* argv[])
{
AutoSeededRandomPool prng;
byte key[ AES::DEFAULT_KEYLENGTH ];
// prng.GenerateBlock( key, sizeof(key) );
memset( key, '4', sizeof(key) );
byte iv[ AES::BLOCKSIZE ];
// prng.GenerateBlock( iv, sizeof(iv) );
memset( iv, '8', sizeof(iv) );
string adata="Authenticated", pdata="Authenticated Encryption";
string cipher, encoded;
string recovered, radata, rpdata;
/*********************************\
\*********************************/
try
{
CCM< AES, 96 >::Encryption e;
e.SetKeyWithIV( key, sizeof(key), iv );
e.SpecifyDataLengths( adata.length(), pdata.length(), 0 );
AuthenticatedEncryptionFilter ef( e,
new StringSink( cipher )
); // AuthenticatedEncryptionFilter
// AuthenticatedEncryptionFilter::ChannelPut
// defines two channels: "" (empty) and "AAD"
// channel "" is encrypted and authenticated
// channel "AAD" is authenticated
ef.ChannelPut( "AAD", (const byte*)adata.c_str(), adata.length() );
// ef.ChannelMessageEnd("AAD");
ef.ChannelPut( "", (const byte*)pdata.c_str(), pdata.length() );
// ef.ChannelMessageEnd("");
ef.MessageEnd();
}
catch( CryptoPP::InvalidArgument& e )
{
cerr << "Caught InvalidArgument..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
/*********************************\
\*********************************/
//if( cipher.length() > 1 )
//{
// // Attack the first and last byte
// cipher[ 0 ] |= 0x0F;
// cipher[ cipher.length()-1 ] |= 0x0F;
//}
/*********************************\
\*********************************/
try
{
CCM< AES, 96 >::Decryption d;
d.SetKeyWithIV( key, sizeof(key), iv );
// d.SpecifyDataLengths( adata.length(), pdata.length(), 0 );
AuthenticatedDecryptionFilter df( d, new StringSink( recovered ) );
df.Put( (const byte *)cipher.c_str(), cipher.length() );
df.MessageEnd();
rpdata = recovered;
// TODO: Switch channels and retrieve AAD
recovered.clear();
//df.SetRetrievalChannel( "AAD" );
//df.GetNextMessage();
//adata = recovered;
//////////////////////////////
// Try a ChannelSwitch
//////////////////////////////
//StringSink ADataSink( radata );
//StringSink PDataSink( rpdata );
//auto_ptr<ChannelSwitch> channels( new ChannelSwitch );
//channels->AddRoute( "AAD", ADataSink,
BufferedTransformation::NULL_CHANNEL );
//channels->AddRoute( "", PDataSink,
BufferedTransformation::NULL_CHANNEL );
//AuthenticatedDecryptionFilter df( d, channels );
//df.Put( (const byte *)cipher.c_str(), cipher.length() );
//df.MessageEnd();
//////////////////////////////
// Try discrete Channels
//////////////////////////////
//df.ChannelPut( "", (const byte *)cipher.c_str(), cipher.length() );
//df.ChannelMessageEnd( "" );
//rpdata = recovered;
//recovered.clear();
//df.ChannelPut( "AAD", (const byte *)cipher.c_str(), cipher.length() );
//df.ChannelMessageEnd( "AAD" );
//radata = recovered;
// df.MessageEnd();
}
catch( CryptoPP::InvalidArgument& e )
{
cerr << "Caught InvalidArgument..." << endl;
cerr << e.what() << endl;
cerr << endl;
}
/*********************************\
\*********************************/
cout << "adata length: " << adata.length() << endl;
cout << "pdata length: " << pdata.length() << endl;
cout << "cipher length: " << cipher.length() << endl;
cout << "recovered adata length: " << radata.length() << endl;
cout << "recovered pdata length: " << rpdata.length() << endl;
cout << endl;
cout << "adata: " << adata << endl;
cout << "pdata: " << pdata << endl;
cout << "recovered adata: " << radata << endl;
cout << "recovered pdata: " << rpdata << endl;
cout << endl;
return 0;
}