Understanding Blowfish

  

One of the most common symmetric block ciphers that I have seen implemented in Java is Blowfish . Blowfish and Twofish (Twofish is the version after Blowfish) were invented by one of the most famous cryptography authors, Bruce Schneier. The JDK 1.4 supports Blowfish, which is a non-patented and free algorithm to use.

Note  

Ron Rivest has been mentioned constantly throughout this book. Another legend of cryptography is Bruce Schneier, who invented Blowfish and Twofish. Bruce Schneier is the CEO of Counterpane Technologies (see http://www.counterpane.com) . He is also the author of Applied Crytography , which is a good source of his algorithms and more.

A block cipher

Blowfish is a block cipher that takes a variable-length key from 32 bits to 448 bits. Since the key can be varied from a low to a high range, it is ideal for exporting at the low range and using the high range of keys in the United States. Blowfish can be executed in all 4-cipher modes of "ECB," "OFB," "CBC," and "CFB." The algorithm can execute in a pure block mode or a stream mode with the "CFB" and "OFB." The padding scheme that Blowfish can use when some is required is the "PKCS5Padding." When Blowfish is executing in "CFB8" mode and no padding is needed, the algorithm can be used in a no-padding mode executed as "NoPadding."

Cross-Reference  

Blowfish can operate in "ECB," "OFB," "CBC," and "CFB" modes. see Chapter 13 for more on these modes.

Blowfish will execute 16 rounds on every block. The 16 rounds are the exact same operations for every block that is normally in a for loop. There are 4 S-boxes that are used of the size 8 x 32, which means 8 bits in and 32 bits out. The S-boxes are used in the function f of the cipher. Another variable that is important to the algorithm is 18 32-bit subkeys that are designated as the variable p , which is an array of 18 integers and is known as a subkey . A subkey is a permutation of the original key used to help eliminate patterns in the encryption results. The Blowfish algorithm uses 64-bit blocks as input to generate a 64-bit output, when not using a stream mode.

Generating subkeys and S-boxes

When the Blowfish algorithm initializes, it generates the subkeys and S-boxes. The P-array and S-boxes will be initialized with fractional pieces of . The subkeys in the P-array are XORed with the byte array containing the key. The key is a byte array generated from a Blowfish javax.crypto.KeyGenerator class. The KeyGenerator returns a javax.crypto.SecretKey class. The SecretKey class contains an array of random bytes. The size of the random bytes is based on the size passed in the KeyGenerator's init method. The SecretKey's getEncoded method returns the key byte array. After the P-array is updated, an initial block of zeros will be encrypted with the current S-boxes and subkeys. The encrypted block will be updated into the S-boxes and subkeys. After the P-array and S-boxes are permutated, the algorithm is ready for encryption or decryption.

Figure 14-2 demonstrates the encryption process, and Figure 14-3 demonstrates the decryption process. The only difference between the two processes is the indexing of the P-array subkeys. Encrypting will be XORed with the subkeys going in a positive sequence, and the decryption will do the reverse.

click to expand
Figure 14-2: Blowfish encryption
click to expand
Figure 14-3: Blowfish decryption
Note  

Like most block ciphers, the function f executes the S-boxes and performs an arithmetic function of the results.

Many ciphers break apart the 64-bit block into a left and a right side and XOR the results together. The basic operation is executed 16 times and is mostly a matter of the left block being XORed into the subkey, and the right side having the function executed on it with the S-boxes and then being XORed with itself. The left block and right block are swapped, and the same operation happens a total of 16 times. When the rounds are complete, there are two arrays of the subkeys that haven't been used yet, and they will be XORed into the blocks. The two 32-bit blocks will then be combined to form the 64-bit block, and the encryption or decryption has been accomplished.

Reading a plaintext file

Listing 14-2 demonstrates the Blowfish algorithm reading a plaintext file and encrypting it into a ciphertext file. The JDK 1.4 provides a javax.crypto.CipherInputStream and javax.crypto.CipherOutputStream . The CipherInputStream will combine the FileInputStream with the functionality of the Cipher class. When reading a file, the input data can be encrypted or decrypted while being read. The stream will be decrypted or encrypted based on the cipher instance that the CipherInputStream was initialized with during its creation. The cipher itself does not change; the stream is just given the functionality of the cipher without making extra calls to decrypt or encrypt after reading the file. The CipherOutputStream can execute the cipher functionality while writing to a file. The cipher engine is not changed at all; it doesn't become a stream cipher, it merely executes on the file I/O.

Listing 14-2: The TestBFCipher class: A Blowfish example
start example
 package com.richware.chap14;     import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.interfaces.*; import java.security.spec.*; import javax.crypto.*; import sun.misc.*;     /**  * Class TestBFCipher  * Description: This is an example to  * test the Blowfish cipher.  *  * Copyright:    Copyright (c) 2002 Wiley Publishing, Inc.  * @author Rich Helton <rhelton@richware.com>  * @version 1.0    * DISCLAIMER: Please refer to the disclaimer at the beginning of this  book.  */ public final class TestBFCipher  {   /**    * Constructor TestRSACipher    */   public TestBFCipher() {}       /**    * Method main    *    * @param args none    *    */   public static void main(String[] args)    {     try      {       String localDirectory  = System.getProperty("user.dir");       System.out.println("Changing directory to Chapter 11");        System.setProperty("user.dir",localDirectory +  "\com\richware\chap11\");       localDirectory  = System.getProperty("user.dir");       if((args[0] == null)   (args[1] == null){          System.out.println("This application requires an input file and  output file");           System.out.println("as arguments");        }           String localInputFile  = localDirectory + args[0];       System.out.println("Openining Chapter 14 plus the input file as an  argument: " + localInputFile);        String localOutputFile  = localDirectory + args[1];       System.out.println("Openining Chapter 14 plus the output file as  an argument: " + localOutputFile);            /*        * Generate a Blowfish Key        */       System.out.println("Generating a Blowfish key...This could take  several minutes");           KeyGenerator keyGenerator =         KeyGenerator.getInstance("Blowfish");           /*        * Set the key Size        * Blowfish can be from 32 bits to 448 bits        */       keyGenerator.init(128);           Key secretKey = keyGenerator.generateKey();           System.out.println("Done generating the key.");           /*        * Blowfish modes        * Blowfish/CFB/NoPadding        * Blowfish/OFB/NoPadding        * Blowfish/ECB/PKCS5Padding        * Blowfish/CBC/PKCS5Padding        */           // Create a cipher using that key to initialize it       Cipher cipherOut =         Cipher.getInstance("Blowfish/CFB/NoPadding");           cipherOut.init(Cipher.ENCRYPT_MODE, secretKey);           /*        * Create a base-64 encoder for displaying binary data.        */       BASE64Encoder encoder = new BASE64Encoder();           /*        * When the CFB or OFB is used        * IV needs to passed as well as key        * Unless it is hardcoded in the algorithm        */           /*        * Get IV        * if not in CFB or OFB,        * returns null        */       byte iv[] = cipherOut.getIV();       if (iv != null)        {         System.out           .println("Initialization Vector of the Cipher:\n"                    + encoder.encode(iv));       }           /*        * Get the Input File Stream        */       FileInputStream fin = new FileInputStream(localInputFile);        /*        * Start that CipherOutputStream        * The Stream will encrypt while        * writing        */       FileOutputStream   fout  =         new FileOutputStream(localOutputFile);       CipherOutputStream cout  = new CipherOutputStream(fout,                                    cipherOut);       int                input = 0;           while ((input = fin.read()) != -1)        {         cout.write(input);       }           fin.close();       cout.close();     }         /*      * Catches      */     catch (Exception ex)      {       ex.printStackTrace();     }   } } 
end example
 

Listing 14-2 also comments on the four operational modes that Blowfish supports. The cipher modes of operation are "Blowfish/CFB/NoPadding," "Blowfish/OFB/NoPadding," "Blowfish/ECB/PKCS5Padding," and "Blowfish/CBC/PKCS5Padding." If only "Blowfish" is passed in, the default mode is "Blowfish/ECB/PKCS5Padding." The OFB and CFB use an initialization vector (IV) for operation and, when these modes are used, the IV needs to be maintained . If the IV is generated at random, and the key is generated at random, these two variables need to be saved in a secure location to be able to decrypt the file.

A test run with the input file as

 Blowfish Cipher Engines are great. 

gives an out put that looks like

 ROt=mI'^T_Z_e!Yc_"lN 
  


Java Security Solutions
Java Security Solutions
ISBN: 0764549286
EAN: 2147483647
Year: 2001
Pages: 222

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net