Crypto++ Holds the Key to Encrypting Your C++ Application Data

Every programmer knows that the early development of the programmable electronic computer was largely spurred by the crypto-war between the British intelligence services and the German navy in WWII. Less known is that the infamous German Enigma cryptography machines were just a modification of off-the-shelf equipment used by banks in the mid-1930s to encode sensitive data about wire transfers.

Nowadays, the need to encode sensitive information is more important than ever. Consider devices such as USB thumb drives, which can store an entire CD’s worth of data in a package the size of a cigarette lighter. Can your data ever be safe if it can all be downloaded in a few clicks and then carried out the door? Encryption of your data gives you one more level of security beyond merely the physical. The good news is that you can encrypt regularly and painlessly with a C++ class library such as Crypto++.

Crypto++: Many Algorithms for Many Platforms

The Crypto++ library is unabashedly a best-of-breed creature: rather than re-implement many popular schemes, the Crypto++ project seeks to integrate them under a uniform framework based on simple abstract base classes. A complete list of features and ciphers would be too long to include here, but the following are a few I found important:

  • Symmetric block ciphers: including Advanced Encryption Standard (AES), Triple-DES, Blowfish, Skipjack, and many more
  • Generic cipher modes: ECB, CBC, CBC ciphertext stealing (CTS), CFB, OFB, counter mode (CTR)
  • Stream cipher modes: Panama, ARC4, SEAL, WAKE, WAKE-OFB, BlumBlumShub
  • Public-key cryptography: including RSA, DSA, ElGamal, Nyberg-Rueppel (NR), Rabin, Rabin-Williams (RW), and many others
  • Elliptic curve cryptography: doesn’t rely on large random prime numbers
  • One-way hash functions: such as SHA-1, MD5, RIPEMD, Panama, Whirlpool
  • Message Authentication Codes (MAC): based on MD5, HMAC, XOR, CBC, and others
  • Gzip: compression/decompression built-in
  • Prime number generation and verification
  • OS-independent wrappers: for timers, sockets, named pipes, random number generation, and crypto APIs

Crypto++ supports a wide variety of platforms, including Microsoft Visual C++ version 6.0, 7.0, 7.1, and 8.0, GCC 3.X and 4.0 for Unix and Windows, MacOS X, and Sun Solaris systems, to name a few. A Visual Studio .NET project file was included in Crypto++ 5.2.1 and imported into Visual Studio .NET 2003 without any problems. The project file creates cryptopp.dll, which is about 1.7MB in a DEBUG build. You may add #define CRYPTOPP_DEFAULT_NO_DLL to use a static library implementation rather than a DLL interface, if you desire.

Unlike many such libraries, the Crypto++ distro doesn’t include a lot of convoluted scripts and makefiles. In general, you can simply recompile the source code and make your own library.

Hello, Crypto++ Basic Encryption/Decryption

For a “Hello World” example, I wanted to build the simplest command-line-driven program that could encrypt and decrypt files. Basically, you pass it the following three files on the command line:

  1. The original file to encrypt
  2. The filename for encrypted output
  3. The filename for the result of roundtrip encryption/decryption

The program then prompts for a passphrase, which is used during the encryption/decryption. Let me dissect the code line-by-line to see how it’s done.

 1 // testcrypto.cpp
 4 #include "dll.h"
 5 #include "default.h"
 6 #include <iostream>
 9 #include <windows.h>
10 #endif
15 const int MAX_PHRASE_LENGTH=250;
17 void EncryptFile(const char *in,
                    const char *out,
                    const char *passPhrase);
18 void DecryptFile(const char *in,
                    const char *out,
                    const char *passPhrase);
21 int CRYPTOPP_CDECL main(int argc, char *argv[])
22 {
23    try
24    {
25       char passPhrase[MAX_PHRASE_LENGTH];
26       cout << "Passphrase: ";
27       cin.getline(passPhrase, MAX_PHRASE_LENGTH);
28       EncryptFile(argv[1], argv[2], passPhrase);
29       DecryptFile(argv[2], argv[3], passPhrase);
30    }
31    catch(CryptoPP::Exception &e)
32    {
33       cout << "nCryptoPP::Exception caught: "
              << e.what() << endl;
34       return -1;
35    }
36    catch(std::exception &e)
37    {
38       cout << "nstd::exception caught: " << e.what() << endl;
39       return -2;
40    }
41 }
44 void EncryptFile(const char *in,
                    const char *out,
                    const char *passPhrase)
45 {
46    FileSource f(in, true, new DefaultEncryptorWithMAC(passPhrase,
                   new FileSink(out)));
47 }
49 void DecryptFile(const char *in,
                    const char *out,
                    const char *passPhrase)
50 {
51    FileSource f(in, true,
         new DefaultDecryptorWithMAC(passPhrase, new FileSink(out)));
52 }
54 RandomPool & GlobalRNG()
55 {
56    static RandomPool randomPool;
57    return randomPool;
58 }
59 int (*AdhocTest)(int argc, char *argv[]) = NULL;

More by Author

Must Read