Click here to Skip to main content
11,641,971 members (62,849 online)
Click here to Skip to main content

A C++ Implementation of the Blowfish Encryption/Decryption method

, 26 Sep 2001 Ms-PL 476.9K 10.2K 141
Rate this:
Please Sign up or sign in to vote.
An article presenting a C++ implementation of the Blowfish encryption/decryption method
<!-- Download Links --> <!-- Add the rest of your HTML here -->

Introduction

Blowfish is an encryption algorithm that can be used as a replacement for the DES or IDEA algorithms. It is a symmetric (i.e. uses the same secret key for both encryption and decryption) block cipher (encrypts data in 8-byte blocks) that uses a variable-length key, from 32 (4 bytes) bits to 448 bits (56 bytes). Blowfish was designed in 1993 by Bruce Schneier as an alternative to existing encryption algorithms. Designed with 32-bit instruction processors in mind, it is significantly faster than DES. Since its origin, it has been analyzed considerably. Blowfish is unpatented, license-free, and available free for all uses. The algorithm consists of two parts: a key-expansion part and a data-encryption part. Key expansion converts a variable key of at least 4 and at most 56 bytes into several subkey arrays totalling 4168 bytes. Blowfish has 16 rounds. Each round consists of a key-dependent permutation, and a key and data-dependent substitution. All operations are XORs and additions on 32-bit words. The only additional operations are four indexed array data lookups per round. Blowfish uses a large number of subkeys. These keys must be precomputed before any data encryption or decryption.

A more detailed article describing the Blowfish algorithm can be found at http://www.schneier.com/blowfish.html

The C++ implementation presented in this article was tested against the test vectors provided by Eric Young at http://www.counterpane.com/vectors.txt. The results were identical with one exception which in my opinion could be a typing error in the referenced Internet file.

Implementation

The public user interface of the CBlowfish class is given bellow:

class CBlowFish
{
public:
  //Constructor - Initialize the P and S boxes for a given Key
  CBlowFish(unsigned char* ucKey, size_t n, <BR>            const SBlock& roChain = SBlock(0UL,0UL));
  //Resetting the chaining block
  void ResetChain();
  // Encrypt/Decrypt Buffer in Place
  void Encrypt(unsigned char* buf, size_t n, int iMode=ECB);
  void Decrypt(unsigned char* buf, size_t n, int iMode=ECB);
  // Encrypt/Decrypt from Input Buffer to Output Buffer
  void Encrypt(const unsigned char* in, unsigned char* out, 
               size_t n, int iMode=ECB);
  void Decrypt(const unsigned char* in, unsigned char* out, 
               size_t n, int iMode=ECB);
};

In the constructor, a user-supplied key material of specified size is used to generate the subkey arrays. Also the chain block is initialized with the specified value.

The function ResetChain() is used to reset the chaining block before starting a new encryption or decryption operation.

The first variant of the Encrypt() function is used for in place encryption of a block of data of the specified size applying the specified operation mode. The block size should be a multiple of 8. This function can operate in the following modes: ECB, CBC or CFB. In ECB mode, chaining is not used. If the same block is encrypted twice with the same key, the resulting ciphertext blocks are the same. In CBC mode a ciphertext block is obtained by first XOR-ing the plaintext block with the previous ciphertext block, and encrypting the resulting value. In CFB mode a ciphertext block is obtained by encrypting the previous ciphertext block and XOR-ing the resulting value with the plaintext. The operation mode is specified in the iMode parameter with ECB being the default value. For the second variant of the Encrypt() function the encryption result is delivered in an output buffer.

The Decrypt() functions are the reverse of the Encrypt() functions presented above.

Usage Examples

The use of CBlowfish class is very easy. In the first code snippet example a key of 8 bytes in size is applied to an 8 byte block. The initial chain block is a null block. The block "aaaabbbb" is encrypted and then decrypted back.

try
{
  char szHex[17];
  //Initialization
  CBlowFish oBlowFish((unsigned char*)"abcdefgh", 8);
  char szDataIn[] = "aaaabbbb";
  char szDataOut[17] = "\0\0\0\0\0\0\0\0";
  //Encryption
  oBlowFish.Encrypt((unsigned char*)szDataIn, (unsigned char*)szDataOut, 8);
  CharStr2HexStr((unsigned char*)szDataIn, szHex, 8);
  cout << szHex << endl;
  CharStr2HexStr((unsigned char*)szDataOut, szHex, 8);
  cout << szHex << endl;
  memset(szDataIn, 0, 8);
  //Decryption
  oBlowFish.Decrypt((unsigned char*)szDataOut, (unsigned char*)szDataIn, 8);
  CharStr2HexStr((unsigned char*)szDataIn, szHex, 8);
  cout << szHex << endl;
}
catch(exception& roException)
{
  cout << roException.what() << endl;
}

In the next code snippet example a key of 16 bytes in size is applied to a larger block of data of 48 bytes size (the block of data size should be a multiple of the block size which is always 8 bytes). The initial chain block is a null block. The block "ababababccccccccababababccccccccababababcccccccc" is encrypted and then decrypted back in all the operation modes (ECB, CBC and CFB). Notice that for the chaining operating modes the chain block has to be reset before decrypting back.

try
{
  CBlowFish oBlowFish((unsigned char*)"1234567890123456", 16);
  char szDataIn1[49] = "ababababccccccccababababccccccccababababcccccccc";
  char szDataIn[49];
  char szDataOut[49];
  memset(szDataIn, 0, 49);
  memset(szDataOut, 0, 49);

  //Test ECB
  strcpy(szDataIn, szDataIn1);
  memset(szDataOut, 0, 49);
  oBlowFish.Encrypt((unsigned char*)szDataIn, 
                    (unsigned char*)szDataOut, 48, CBlowFish::ECB);
  memset(szDataIn, 0, 49);
  oBlowFish.Decrypt((unsigned char*)szDataOut, 
                    (unsigned char*)szDataIn, 48, CBlowFish::ECB);

  //Test CBC
  oBlowFish.ResetChain();
  strcpy(szDataIn, szDataIn1);
  memset(szDataOut, 0, 49);
  oBlowFish.Encrypt((unsigned char*)szDataIn, 
                    (unsigned char*)szDataOut, 48, CBlowFish::CBC);
  memset(szDataIn, 0, 49);
  oBlowFish.ResetChain();
  oBlowFish.Decrypt((unsigned char*)szDataOut, 
                    (unsigned char*)szDataIn, 48, CBlowFish::CBC);

  //Test CFB
  oBlowFish.ResetChain();
  strcpy(szDataIn, szDataIn1);
  memset(szDataOut, 0, 49);
  oBlowFish.Encrypt((unsigned char*)szDataIn, 
                    (unsigned char*)szDataOut, 48, CBlowFish::CFB);
  memset(szDataIn, 0, 49);
  oBlowFish.ResetChain();
  oBlowFish.Decrypt((unsigned char*)szDataOut, 
                    (unsigned char*)szDataIn, 48, CBlowFish::CFB);
  cout << endl;
}
catch(exception& roException)
{
  cout << "Exception: " 
       << roException.what() << endl;
}

I am interested in any opinions and new ideas about this implementation. The project Blowfish.zip attached to this article includes the source code of the presented CBlowfish class and some test code.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

George Anescu
Web Developer
Romania Romania
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionLittle Endian Pin
Mr. S13-Apr-06 10:36
memberMr. S13-Apr-06 10:36 
Generalproblem Pin
quistiun22-Mar-06 13:59
memberquistiun22-Mar-06 13:59 
GeneralRe: problem Pin
breakpoint23-Mar-06 21:17
memberbreakpoint23-Mar-06 21:17 
GeneralRe: problem Pin
quistiun24-Mar-06 14:41
memberquistiun24-Mar-06 14:41 
GeneralVery nice Pin
Jim Xochellis13-Mar-06 20:52
memberJim Xochellis13-Mar-06 20:52 
GeneralCommercial using of sources Pin
AndreyLG18-Jan-06 21:38
memberAndreyLG18-Jan-06 21:38 
GeneralKnown length of decrypted String Pin
cwanner19-Oct-05 9:25
membercwanner19-Oct-05 9:25 
GeneralRe: Known length of decrypted String Pin
NxTitle23-May-07 12:01
memberNxTitle23-May-07 12:01 
Generalneed a help on implement the code Pin
Torune2-Sep-05 16:06
memberTorune2-Sep-05 16:06 
GeneralRe: need a help on implement the code Pin
breakpoint9-Apr-06 1:45
memberbreakpoint9-Apr-06 1:45 
GeneralHelp with code Pin
Anonymous14-Jul-05 10:03
sussAnonymous14-Jul-05 10:03 
QuestionWhy not a simple string encoding version? Pin
chanon9-Jun-05 23:07
memberchanon9-Jun-05 23:07 
AnswerRe: Why not a simple string encoding version? Pin
Anonymous8-Sep-05 0:24
sussAnonymous8-Sep-05 0:24 
Generalbuffer length not x8 Pin
Boniolopez16-Apr-05 8:05
memberBoniolopez16-Apr-05 8:05 
GeneralRe: buffer length not x8 Pin
Nir Levy10-May-05 10:05
memberNir Levy10-May-05 10:05 
GeneralRe: buffer length not x8 Pin
Coruscant16-May-05 10:59
memberCoruscant16-May-05 10:59 
GeneralBlowfish patents Pin
manjunathG1-Apr-05 0:37
membermanjunathG1-Apr-05 0:37 
GeneralRe: Blowfish patents Pin
MoazReyad7-Apr-05 6:53
memberMoazReyad7-Apr-05 6:53 
QuestionNon symmetric encryption/decryption? Pin
Drew Emsley2-Dec-04 10:35
memberDrew Emsley2-Dec-04 10:35 
AnswerRe: Non symmetric encryption/decryption? Pin
florianpopa20109-May-05 21:18
memberflorianpopa20109-May-05 21:18 
GeneralCompile errors in ANSI C++, improvements to code Pin
SiemelNaran26-Nov-04 14:44
memberSiemelNaran26-Nov-04 14:44 
GeneralRe: Compile errors in ANSI C++, improvements to code Pin
ddogan4-Jan-07 11:25
memberddogan4-Jan-07 11:25 
GeneralDecryption problem in CBC mode Pin
necroleak24-Oct-04 0:14
membernecroleak24-Oct-04 0:14 
GeneralRe: Decryption problem in CBC mode Pin
necroleak1-Nov-04 21:20
membernecroleak1-Nov-04 21:20 
GeneralRe: Decryption problem in CBC mode Pin
SiemelNaran26-Nov-04 15:17
memberSiemelNaran26-Nov-04 15:17 
GeneralBorland C++ Pin
marius@quickweb.ro3-Oct-04 23:41
membermarius@quickweb.ro3-Oct-04 23:41 
GeneralRe: Borland C++ Pin
handlamp28-Oct-04 8:53
memberhandlamp28-Oct-04 8:53 
GeneralRe: Borland C++ Pin
handlamp28-Oct-04 10:02
memberhandlamp28-Oct-04 10:02 
GeneralRe: Borland C++ Pin
SiemelNaran26-Nov-04 15:22
memberSiemelNaran26-Nov-04 15:22 
GeneralLicense Pin
hmailserverdeveloper30-Aug-04 7:59
susshmailserverdeveloper30-Aug-04 7:59 
Generalproblem with implementation :( Pin
kanetheterrible13-Aug-04 4:55
memberkanetheterrible13-Aug-04 4:55 
GeneralRe: problem with implementation :( Pin
SiemelNaran26-Nov-04 15:48
memberSiemelNaran26-Nov-04 15:48 
Generalwhy VC++ Pin
Athar Hussain18-Jul-04 3:45
memberAthar Hussain18-Jul-04 3:45 
GeneralProblem with implementation Pin
Luc Amaury7-Apr-04 5:00
memberLuc Amaury7-Apr-04 5:00 
GeneralRe: Problem with implementation Pin
polynr698-Apr-04 4:37
memberpolynr698-Apr-04 4:37 
QuestionNeed a CString interface? Pin
Anonymous19-Mar-04 8:05
sussAnonymous19-Mar-04 8:05 
AnswerCString interface with 8 byte padding &lt;-- here Pin
polynr698-Apr-04 4:13
memberpolynr698-Apr-04 4:13 
GeneralRe: CString interface with 8 byte padding &lt;-- here Pin
Steve Guerreri27-Oct-04 11:32
memberSteve Guerreri27-Oct-04 11:32 
GeneralRe: CString interface with 8 byte padding &lt;-- here Pin
polynr6927-Oct-04 21:10
memberpolynr6927-Oct-04 21:10 
GeneralRe: CString interface with 8 byte padding &lt;-- here Pin
pku20095-Aug-08 16:37
memberpku20095-Aug-08 16:37 
AnswerI don't think so... Pin
Zigmar21-May-04 10:57
memberZigmar21-May-04 10:57 
GeneralRe: I don't think so... Pin
Coruscant16-May-05 6:51
memberCoruscant16-May-05 6:51 
Generalthread safe.... Pin
trook17-Mar-04 12:02
membertrook17-Mar-04 12:02 
GeneralRe: thread safe.... Pin
polynr6913-Apr-04 21:21
memberpolynr6913-Apr-04 21:21 
GeneralRe: thread safe.... Pin
SiemelNaran26-Nov-04 15:57
memberSiemelNaran26-Nov-04 15:57 
QuestionDifference with reference implementation? Pin
andru1233-Mar-04 3:46
memberandru1233-Mar-04 3:46 
GeneralI can't decrypt using this algo Pin
Anonymous31-Jan-04 9:51
sussAnonymous31-Jan-04 9:51 
Question8-byte padding? Pin
Jacques Cooper24-Dec-03 10:55
memberJacques Cooper24-Dec-03 10:55 
GeneralMultiple of 8 Problem Pin
Hermaphrodyte14-Dec-03 11:26
memberHermaphrodyte14-Dec-03 11:26 
GeneralConstructor question Pin
Hockey3-Dec-03 0:22
memberHockey3-Dec-03 0:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150731.1 | Last Updated 27 Sep 2001
Article Copyright 2001 by George Anescu
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid