Your problem is due to the fact that your "automatic" stream decryptor is reading the file from the very beginning. And due to the error in configuring encryptor, the first block can't be decrypted properly.

See the attached source code for correction. I've tested the corrected code under Cygwin with Crypto++ v5.5.1 and it worked properly.


Rash wrote:
Ok here is what I have been trying, Now the problem is I'm unable to
retrieve the first 5 bytes.
If the input is
"The library is an powerful and elegant tool for performing complex
cryptography"
I get the output as
"}ýŸ1/4 tÛ=rary is an powerful and elegant tool for performing complex
cryptography"

Here is what I did. help me to fix this problem
void encryptFile(const char* password, const char* inputFileName,
const char* outputFileName)
{
    byte pass[ AES::BLOCKSIZE ];	// digest of password
    byte iv[ 8 ];			// Initial Vector (IV)

    AutoSeededRandomPool rng;

    // digest password
    StringSource( password, true, new HashFilter(*(new SHA256), new
ArraySink(pass, AES::BLOCKSIZE)) );

    // random Initial Vector
    rng.GenerateBlock(iv, 8);

    // create object for encrypting
    AES::Encryption aesEncryption(pass,
CryptoPP::AES::DEFAULT_KEYLENGTH);
    CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption,
iv);

    StreamTransformationFilter *encryptor;
    encryptor = new StreamTransformationFilter(cbcEncryption, new
FileSink(outputFileName) );
    encryptor->Put(iv, 8);

    // "bind" a file and encrypt one
    FileSource(inputFileName, true, encryptor);
}

void decryptFile(const char* password, const char*inputFileName,const
char* outputFileName)
{
    byte pass[ AES::BLOCKSIZE ];
    byte iv[ 8 ];
    byte head_file[ 8 ];

    memset(iv, 0, 8 );
    try
	{
		StringSource( password, true, new HashFilter(*(new SHA256), new
ArraySink(pass,AES::BLOCKSIZE)) );

		CryptoPP::AES::Decryption aesDecryption(pass,
CryptoPP::AES::DEFAULT_KEYLENGTH);
		CryptoPP::CBC_Mode_ExternalCipher::Decryption
cbcDecryption( aesDecryption, iv );

		StreamTransformationFilter *decryptor;
                decryptor = new
StreamTransformationFilter(cbcDecryption, new
FileSink(outputFileName) );
		decryptor->Get( head_file, 8 );

		FileSource(inputFileName, true, decryptor);
	}
	catch(CryptoPP::Exception &e)
	{
		return;
	}
}

On Sep 2, 10:44 am, Rash <[EMAIL PROTECTED]> wrote:
  
I tried the following but I get the exception, "ciphertext block is
not a multiple of block size". Please help.
void decryptFile(const char* password, const char*inputFileName,const
char*outputFileName)
{
    byte pass[ AES::BLOCKSIZE ];
    byte iv[ 8 ];
    byte head_file[ 8 ];

    memset(iv, 0, 8);

    try
        {
                FileSource source(inputFileName, false);
                StringSource( password, true,new HashFilter(*(new MD5), new
                                ArraySink(pass, AES::BLOCKSIZE)) );

                CryptoPP::AES::Decryption aesDecryption(pass,
CryptoPP::AES::DEFAULT_KEYLENGTH);
                CryptoPP::CBC_Mode_ExternalCipher::Decryption
cbcDecryption( aesDecryption, iv );

                // get and encrypt first block
                source.Pump(8);
                source.Get(head_file, 8);

                // "bind" decryptor to output file
                source.Attach( new StreamTransformationFilter(cbcDecryption,
                                new FileSink((outputFileName) ) ));

                // push the rest data
                source.PumpAll();
        }
        catch(CryptoPP::Exception &e)
        {
                return ;
        }

}
Rash wrote:
    
Hello All,
  Following are my specifications to encrypt/decrypt files using
AES::CBC mode
      
Encrypt process:
1) 8 bytes random IV ( Initialization Vector ).
   Insert the 8 bytes random IV to the beginning of the data stream.
      
2) Key length with 16 bytes ( digest using MD5 ).
3) padding method compatible with RFC 2898.
4) Encrypt the file.
      
Decrypt process:
1) Read the first 8 bytes block and ignore it.
2) Digest the key using MD5.
3) Use the same padding method used when encrypting the file.
4) Decrypt the file.
      
To encrypt the file here is my code
void encryptFile(const char* password, const char* inputFileName,
const
char* outputFileName)
{
    byte pass[ AES::BLOCKSIZE ];   // digest of password
    byte iv[ 8 ];          // Initial Vector (IV)
      
    AutoSeededRandomPool rng;              // random number generator
   try
   {
           // digest password
           StringSource( password, true,new HashFilter(*(new MD5), new
                           ArraySink(pass, AES::BLOCKSIZE)) );
      
           // random Initial Vector
           rng.GenerateBlock(iv, 8);
      
           // create object for encrypting
           AES::Encryption aesEncryption(pass,
CryptoPP::AES::DEFAULT_KEYLENGTH);
           CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption,
iv);
      
           StreamTransformationFilter *encryptor;
           encryptor = new StreamTransformationFilter(cbcEncryption, new
FileSink(outputFileName) );
      
           encryptor->Put(iv, 8);
      
           // "bind" a file and encrypt one
           FileSource(inputFileName, true, encryptor);
   }
   catch(CryptoPP::Exception &e)
   {
           return;
   }
}
void decryptFile(const char* password, const char*inputFileName,const
char*outputFileName)
{
   //help me to write the decrypt functionality
}
      
How do I decrypt the file? I'm unable to read the first 8 bytes block
and ignore it.
Please help me to write the decrypt function satisfying the above
specifications.
      
Thanks in advance
      




  


--~--~---------~--~----~------------~-------~--~----~
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.
-~----------~----~----~----~------~----~------~--~---

#include <iostream>

#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/sha.h>
#include <cryptopp/osrng.h>
#include <cryptopp/files.h>
#include <cryptopp/filters.h>

USING_NAMESPACE(CryptoPP);
USING_NAMESPACE(std);

/**************************************************************/
  /* Code to illustrate usage of cryptographic primitives     */
  /* provided by Crypto++ library v5.5.1 of Wei Dai.          */
  /*                                                          */
  /* In particular, the program provides two functions:       */
  /*                                                          */
  /* 1. Encrypt a file (key based on password) with random IV;*/
  /*                                                          */
  /* 2. Decrypt previously encrypted file.                    */ 
  /*                                                          */
  /* Issue with the original code:                            */
  /*     - set IV in the encryptor but also used it as random */
  /*       prefix, so garbage was the 1st encrypted block;    */ 
  /*     - did not "fast-forward" the encrypted file past the */
  /*       first block (which was encrypted random garbage).  */
  /*                                                          */
  /* Corrections performed:                                   */
  /*     - fixed encryptor by leaving random block prefixed,  */
  /*       but removing redundancy (having it in encryptor);  */
  /*     - fixed decryptor (see the source code).             */
  /*                                                          */
  /*==========================================================*/
  /* Written by:                                              */
  /*                   Rash <[EMAIL PROTECTED]>            */
  /*                                                          */
  /* Modified by:                                             */
  /*                   Mouse <[EMAIL PROTECTED]>        */
  /*                   Sun Sep 2, 12:25:00 2007               */
  /*                                                          */
  /************************************************************/
  /*                                                          */
  /* Copyright (C) 2007 Rash  <[EMAIL PROTECTED]>          */
  /* Copyright (C) 2007 Mouse <[EMAIL PROTECTED]>       */
  /*                                                          */
  /************************************************************/

void encryptFile(const char* password, const char* inputFileName,
                 const char* outputFileName)
{
  byte pass[AES::BLOCKSIZE];    // digest of password
  byte iv[16];                  // Initial Vector (IV),  misused 
                                // by original author
  byte true_iv[16];             // real IV used - set to zero
  
  AutoSeededRandomPool rng;
  
  // digest password
  StringSource(password, true, 
               new HashFilter(*(new SHA256), 
                              new ArraySink(pass, AES::BLOCKSIZE)));
  
  // random Initial Vector
  rng.GenerateBlock(iv, 16);
  memset(true_iv, 0, 16);
  
  // create object for encrypting
  AES::Encryption aesEncryption(pass,
                                CryptoPP::AES::DEFAULT_KEYLENGTH);
  CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption,
                                                    true_iv);
  
  StreamTransformationFilter *encryptor;
  encryptor = new StreamTransformationFilter(cbcEncryption, 
                                             new FileSink(outputFileName) );

  encryptor->Put(iv, 16); // this prefixes the file with random block (not IV)
                 // Cryptographically it is equivalent to IV, so just as good
  
  // "bind" a file and encrypt one
  FileSource(inputFileName, true, encryptor);
}


void decryptFile(const char* password, const char*inputFileName,
                 const char* outputFileName)
{
  byte pass[AES::BLOCKSIZE];
  byte iv[16];        // here's 1st problem: AES IV is 16 bytes
  byte head_file[16]; // so must skip 16 bytes, not 8.

  memset(iv, 0, 16); // very correct - in fact the encryptor prefixes file
  // with a random block, so no need to pass the IV explicitly.

  try {
    StringSource(password, true, new HashFilter(*(new SHA256), new
                                                
ArraySink(pass,AES::BLOCKSIZE)));

    CryptoPP::AES::Decryption aesDecryption(pass,
                                            CryptoPP::AES::DEFAULT_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, 
iv);
    
    StreamTransformationFilter *decryptor;
    decryptor = new
      StreamTransformationFilter(cbcDecryption, new
                                 FileSink(outputFileName));

    
    // decryptor->Get(head_file, 16); // does not do anything useful, wrong here
    // We must somehow decrypt 1st block of the input file, without sending the
    // result into the output file.
    char garbage[16], iv_garbage[16]; // place for IV stuff
    ifstream inf;
    inf.open(inputFileName); inf.read(iv_garbage, 16); // absorb random prefix
    
    // Decrypt random prefix (with zero IV) to some dummy buffer to get
    // (a) decryptor state adjusted to IV, and
    // (b) file position pointer advanced to the past-IV spot.
    cbcDecryption.ProcessData((byte *)garbage, (const byte *)iv_garbage, 16);

    // NOW can run the decryption engine in "automatic" mode
    FileSource(inf, true, decryptor);

    inf.close(); // to be nice
  }
  catch(CryptoPP::Exception &e)
    {
      cerr << "Caught exception during decryption!" << endl;
      return;
    }
}

int main(int argc, char *argv[])
{
  const char *pwd  = "not-so-complicated parole";
  const char *pfn = "plain.txt";
  const char *cfn = "cipher.dat";
  const char *ofn = "plain2.txt";

  // Create test plaintext file "plain.txt"
  ofstream plain;
  plain.open(pfn);
  plain << "An excellent test of file encryption techniques.\n";
  plain << "This test will not demonstrate many tricks though.\n";
  plain.close();

  // Invoke encryptor to encrypt into "cipher.dat"
  encryptFile(pwd, pfn, cfn);

  // Invoke decryptor to decrypt into "plain2.txt"
  decryptFile(pwd, cfn, ofn);

  exit(0);
}

Reply via email to