Encryption/Decryption problems


I am trying to make a program that takes an encrypted file (DES) and decrypts the file.

I have managed to write a program that can encrypt and decrypt using standard DES. However, the encrypted files it produces contain NON alpha numeric characters in the file. I am still able to decrypt that file and get the correct original file, BUT I have then tested it with some test data that I have, which uses STANDARD DES IMPLEMENTATION and the sample encrypted data doesn't contain any NON alpha numeric data.

I am looking for A STANDARD DES (and 3DES) library for C++ that will take a file and encrypt or decrypt it, but not use NON alphanumeric characters.

Am I doing something wrong? or is it just how the DES is implemented in the library?

If you need anymore info let me know.

Who is Participating?
waysideConnect With a Mentor Commented:
> How do i declare bf, outf ? Are they of type FILE?

FILE *bf;
FILE *outf;

> Also what is Buf and BUFLEN?

These can be however big you want:

const int BUFLEN = 512;
char Buf[512];

The loop shoud be more like this, though:

     while(  ! feof( bf ) )
     {  int num_read = fread( Buf, BUFLEN, bf );  
          for(i=0;i<num_read;i++) printf( outf, "%2x", Buf[i] );  
     }  ;

> it takes sKey and sIV, which are both "const unsigned char*"

In your calling code, cast them to the appropriate type:

   longReturn = DES_FileHex(sFileOut.c_str(), sFileIn.c_str(),
          (const unsigned char *)sHexKey.c_str(), bEncrypt, sMode.c_str(),
          (const unsigned char *)sHexIV.c_str());
awesomefennisAuthor Commented:
Just a thought.....

could it be that because i am decrypting a whole file that is whay I am getting non alpha numeric characters. Whereas if I used another method within the library to just encrypt/decrypt bytes (for example), then I would not get non alpha numeric characters, and so I could use that to check against my test data, to make sure that it is using the same encryption implementation?

The output of DES is a stream of bytes.  These bytes can have any value, including ones that are not defined as ASCII printing characters.

It's traditional to print out this stream as hexadecimal digits, that transforms the data into just the characters 0 to 9 and A to F, with maybe a end-of-line every 64 characters.   This makes the file human-readable, but also it's twice as long.  (Each 8 bit byte gets mapped into two characters.   Then when you feed this hex data to the un-DES code, you have to do a bit of extra work to convert hex back to bytes.  Just a line or three of code.

Now whether you keep the DES'ed data as pure binary or as hex is up to you.  If the encrypted data is never going to be seen by human eyes and isnt going though any medium that might mangle the binary data, then you can keep it as pure binary.

But if it has to be printed out, or sent thru e-mail in a message body, or though some other path that might mangle staright binary, you'd better convert it to hex.

To convert it to/from hex you can use printf() or sprintf() with the %x format spec, then use scanf(0 or sscanf() on the receiving end.

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

awesomefennisAuthor Commented:
ok I am having a little problem understanding exactly what you are saying:

IU am trying to use the function DES_FileHex

THis is how the function is called in the header file:
long _stdcall DES_FileHex(const char *lpszFileOut, const char *lpszFileIn,
      const char *lpszKey, int bEncrypt,
      const char *lpszMode, const char *lpszIV);


Here is the code I have written that calls DES_FileHex

#include <stdio.h>
#include <iostream>
#include "diCryptoSys.h"
#include <string>
using namespace std;

int main()
      //Declaring Variables
      long longReturn; // Returns 0 if successful otherwise a non zero value
      long lngRet;    // Return Value from ErrorLookUp

      char sErrMsg[128]; //Error Message
      string sMode;  // Determines ECB or CBC mode.
      string sFileIn; //Full path name of input file
      string sFileOut; //Full path name of output file
      string sHexKey; //Key in hexadecimal
      string sHexIV; //Initialisation Vector in Hexadecimal
      char cAgain = 'Y'; //flag for decrypting more files
      char cCrypt;  //Character for encrypt or decrypt question
      bool bEncrypt; // flag to encrypt or decrypt
      string crypt; //holds the string "encrypt" or "decrypt"
      bool bInvalid;

//Continues to run decryption program until "n" is answered

      //Determine whether doing encryption or decryption and set crypt
      if (bEncrypt)
            crypt = "encrypt";
      else crypt = "decrypt";

      cout << "Enter the full path of the file you wish to " << crypt << ": " <<  endl
            << "E.g. c:\\file_location.txt" << endl;
      cin >> sFileIn;
      cout << "Enter the location you would like to save the " << crypt << "ed file to:" << endl
            << "E.g. c:\\new_location.txt" << endl;
      cin >> sFileOut;
      cout << "Enter the 16 character Key Value in Hexadecimal (E.g. 0987654321fedcba)" << endl;
      cin >> sHexKey;

      sMode = "CBC"; //Set for ECB mode
//      sHexIV = ""; //No IV value as ECB is used.

      cout << "Enter the Initialisation Vector: " << endl;
      cin >> sHexIV;

      //Takes encrypted file sFileIn and decrypts it to sFileOut
      longReturn = DES_FileHex(sFileOut.c_str(), sFileIn.c_str(),
            sHexKey.c_str(), bEncrypt, sMode.c_str(), sHexIV.c_str());

      //Display whether Decryption was Successful and Error Messages
      if (longReturn == 0)  
            cout << "The " << crypt << "ion was successful" << endl ;
            cout << "The Original file is located: " << sFileIn << endl;
            cout << "The " << crypt << "ed file is located: " << sFileOut << endl;      
            //Display error code and explanation for Failed Decryption
            cout << "The Decryption failed" ;
            lngRet = API_ErrorLookup(sErrMsg, 128, longReturn);
            cout << endl << "The error message is: " << sErrMsg << endl;
      return 0;


Any help would be really appreciated.

Usually DES or any other encrypted data is converted into Base64 encryption in order to be able to send it through a medium that requires printable characters.
For example, if you need to send this data through email, you would first do a DES encryption, then do a Base64 encryption.
On the other side, you would then do a Base64 decryption, and then do a DES decryption.
awesomefennisAuthor Commented:
so when I run DES_FileHEX it converts it to Base64. Is there a way of after running the function called DES_FileHEX, converting it back from BASE64??

If so, how would I do that? DO I need any special libraries?

My Scenario:
After running DES_FileHEX I have the encrypted file (for example) ina  location called c:\encrypted.txt

How can I then convert that encrypted.txt file out of BASE64?

I wasn't able to pull up the link you posted,  and I'm not familiar with DES_FileHEX, so I can't tell you if it's converting it to Base64 or not.
Usually this is a seperate process, or you have to explicitly give an option to have the data DES encrypted and Base64 encrypted.

Can you post a better linke for DES_FileHEX?
awesomefennisAuthor Commented:
Ooops sorry, I'm not sure what happened to that link.

This link should get you there.


If you need any more info let me know.
grg99Connect With a Mentor Commented:
Okay, let's start over:

*  The two functions you are calling are symmetrical-- the output of one goes into the input of the other.

*  You don't need to do ANYTHING to the intermediate encrypted file, unless one of the special cases below is true.
This intermediate file will be in some format.  The name kinda suggests the file gets encrypted into hex, perhaps printable hex, but you never know, some people think "hex" is a synonym for "binary".

*  The intermediate file you suggest has non-printable characters in it.  This suggests it is not what most of us would call hex, i.e.   76535467AB65432DE364536FA.

*  If you want to make this file READBLE TEXT for some reason, like just to look at it, or if it has to go though some visible medium, like you're going to print out the file onto paper and mail it or fax it to somebody, THEN you will want to convert this intermediate file to a readable format.  Two common ways of doing this are "Base64" and HEX.

Base64 is a bit more compact than HEX, as it encodes six bits of binary into ONE 8-bit printable character.
BUT it's kinda brain-dead, like it uses the character "space" to encode zeroes.  Which don't fax too well, and some
e-mail programs strip[ off trailing blanks, which isnt too helpful.

I woudl suggest plain old HEXADECIMAL.  For that you take each byte of the file and write out TWO characters.  The %x format in printf() does this very nicely for you.     The similar %x format for scanf does the reverse.    Voila.  Bob's your uncle.

To do these visible encodings you have to read the binary file, and write it out in the other format.  it could be as simple as:

bf = fopen( "binary.crp", "rb" );
outf = fopen( "readble.hex", "w" );

while(  ! feof( bf ) ) {  fread( Buf, BUFLEN, bf );  for(i=0;i<BUFLEN;i++) printf( outf, "%2x", Buf[i] );   }  ; close( outf, bf);

Hope this helps.

awesomefennisAuthor Commented:
thanks grg99, i think we are getting somewhere.

I think the file that gets encrypted and although it says HEX, it has "non readble" characters.

So I want to convert the ecnrypted file to HEXADECIMAL, so that I can use that and see if the encryption is giving me what I expect. As I have a list where given a KEY, and a INput, it will tell me what the DES encryption SHOULD be....so I would to make sure that this library I found does do STandard DES encryption. And the test value I have all are in readable characters, so I guess I will need to convert.

Ok, now I added the following (which is your code)

      bf = fopen( sFileOut.c_str(), "rb" );
      outf = fopen( "c:\readable_hex.txt", "w" );

      while(  ! feof( bf ) )
      {  fread( Buf, BUFLEN, bf );  
            for(i=0;i<BUFLEN;i++) printf( outf, "%2x", Buf[i] );  
      }  ;
      close( outf, bf);

I got the following errors:

C:\crypto_test\des.cpp(109) : error C2065: 'bf' : undeclared identifier
C:\crypto_test\des.cpp(109) : error C2440: '=' : cannot convert from 'struct _iobuf *' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
C:\crypto_test\des.cpp(110) : error C2065: 'outf' : undeclared identifier
C:\crypto_test\des.cpp(110) : error C2440: '=' : cannot convert from 'struct _iobuf *' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
C:\crypto_test\des.cpp(112) : error C2227: left of '->_flag' must point to class/struct/union
C:\crypto_test\des.cpp(112) : fatal error C1903: unable to recover from previous error(s); stopping compilation
Error executing cl.exe.


Some of them are obvious like bf and outf as I haven't declared them. But what do I declare them as, what are they?

I'm not sure what the "error C2440: '=' : cannot convert from 'struct _iobuf *' to 'int'" error is, but maybe it will go away if i declare bf and outf.

Many tHanks for all your help...im just really rusty and not really good with working with other peoples libraries...as can be seen.

Ah, yes, my code was just a rough cut, I assumed you were up to speed with fopen(), printf() etc.    You need to declare bf, outf, and Buf.    Details too mundane.

If you just want to SEE the file in HEX, you can use good old debug:

C:\DOC\grg>debug f.bat
0AEB:0100  53 65 74 20 54 68 65 4D-61 69 6E 44 69 72 3D 63   Set TheMainDir=c
0AEB:0110  3A 5C 74 65 73 74 0D 0A-53 65 74 20 54 68 65 42   :\test..Set TheB
0AEB:0120  61 63 6B 75 70 73 44 69-72 3D 25 54 68 65 4D 61   ackupsDir=%TheMa
0AEB:0130  69 6E 44 69 72 25 5C 42-61 63 6B 75 70 73 47 6F   inDir%\BackupsGo
0AEB:0140  48 65 72 65 0D 0A 53 65-74 20 54 68 65 46 69 6C   Here..Set TheFil
0AEB:0150  65 73 44 69 72 3D 25 54-68 65 4D 61 69 6E 44 69   esDir=%TheMainDi
0AEB:0160  72 25 5C 46 69 6C 65 73-41 63 63 75 6D 75 6C 61   r%\FilesAccumula
0AEB:0170  74 65 48 65 72 65 0D 0A-53 65 74 20 4D 61 78 46   teHere..Set MaxF
awesomefennisAuthor Commented:
well I want to see them in HEX, but I would prefer if when the file was encrypted it was just saved in HEX. as i need to run a few of these test cases against it, to make sure it is working.

SO I guess trying to convert it to HEX would be the best way....

How do i declare bf, outf ? Are they of type FILE?

Also what is Buf and BUFLEN?

Is there no easier way to convert the encrypted file to readble format like you said just using ABCDEF1234567890 ??

After all, the way that CryptoSYS has implemented DES may not be "correct" for my purposes, so I am only really trying to see that the files that are encrypted with my tool do actually encrypt  with standard implementation of DES.

Any help would be great.


awesomefennisAuthor Commented:
I am also looking in to running another function called DES_FileHEX.

However, the header file declares the function as:

long _stdcall DES_File(const char *sFileOut, const char *sFileIn,
      const unsigned char *sKey, int bEncrypt,
      const char *sMode, const unsigned char *sIV);

it takes sKey and sIV, which are both "const unsigned char*"

I am having difficulty trying to declare them and initalise them.

I keep getting error messages that "cannot convert parameter 3 from const* to "const unsigned char*"

I am completely clueless how to proceed.

MadAboutYouConnect With a Mentor Commented:
> I am having difficulty trying to declare them and initalise them.
> I keep getting error messages that "cannot convert parameter 3 from const*
> to "const unsigned char*"
> I am completely clueless how to proceed.

Some functions use 'unsigned char' rather than the [signed] 'char' type to minimize difficulities when applying bit, comparative and other mathematical operations to the byte values.   With extremely rare exceptions a byte is a byte, so casting between them is virtually always legitimate.  But the need to do so can be a pain.

In your code above, you could simply add the cast operator:   (const unsigned char*)
for the sKey and sIV parameters, to convert the "const char*" result of the std::string::c_str() function, like:

     //Takes encrypted file sFileIn and decrypts it to sFileOut
     longReturn = DES_FileHex(sFileOut.c_str(), sFileIn.c_str(),
          (const unsigned char*)sHexKey.c_str(), bEncrypt,
          sMode.c_str(), (const unsigned char *)sHexIV.c_str());

All Courses

From novice to tech pro — start learning today.