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

Reply via email to