/* $Id: Blowfish.java,v 1.1 2004/01/19 02:03:50 rgrimm Exp $
*
* Ported to Java from the C-code reference implementation --part of
* the SSL implementation 0.6.6-- written by Eric Young (eay@mincom.oz.au).
*
* Copyright (C) 1995-2000 The Cryptix Foundation Limited.
* All rights reserved.
*
* Use, modification, copying and distribution of this software is subject
* the terms and conditions of the Cryptix General Licence. You should have
* received a copy of the Cryptix General Licence along with this library;
* if not, you can download a copy from http://www.cryptix.org/ .
*/
package cryptix.jce.provider.cipher;
import java.security.InvalidKeyException;
import java.security.Key;
/**
* This class implements the Blowfish algorithm (standard, 16 round version).
* Blowfish is a symmetric block cipher, with a 64-bit blocksize and a variable
* key length (between 40 and 448 bits inclusive, in 8-bit increments).
* <p>
* References:<br>
* <ul>
* <li>Bruce Schneier,
* "Section 14.3 Blowfish,"
* Applied Cryptography, 2nd edition,
* John Wiley & Sons, 1996</li>
*
* <li>Bruce Schneier,
* <a href="http://www.counterpane.com/bfsverlag.html">
* Description of a New Variable-Length Key, 64-Bit Cipher (Blowfish)</a>,
* Fast Software Encryption Cambridge Security Workshop Proceedings,
* Springer-Verlag, 1004, pp 191-204.</li>
*
* <li><a href="http://www.counterpane.com/blowfish.html">
* http://www.counterpane.com/blowfish.html</a></li>
* </ul>
* <p>
* The implementation is heavily optimized (but we can still do better):<br>
* <ul>
* <li>The P-box and S-box data is encoded in a string to save on
* .class-file size</li>
* <li>P-box entries are stored in individual integers Pxx</li>
* <li>The loops have been unrolled
* <li>Encryption & decryption use the same algorithm</li>
* </ul>
* <p>
* Speed optimizations thanks to Peter Hjelt <mxv@iterate.com>.
* Additional speed and size optimizations by gelderen <gelderen@cryptix.org>.
*
* @version $Revision: 1.1 $
* @author Systemics Ltd.
* @author David Hopwood
* @author Jeroen C. van Gelderen (gelderen@cryptix.org)
* @author Raif S. Naffah (raif@cryptix.org)
*/
public final class Blowfish
extends BlockCipher
{
// Static variables and constants
// ...................................................................
/** Compressed initial values for the P-box and S-boxes */
private static final String
cP= "$?j\u0088\u0085\u00A3\u0008\u00D3\u0013\u0019\u008A.\u0003psD" +
"\u00A4\u00098\")\u009F1\u00D0\u0008.\u00FA\u0098\u00ECNl\u0089" +
"E(!\u00E68\u00D0\u0013w\u00BETf\u00CF4\u00E9\u000Cl\u00C0\u00AC" +
")\u00B7\u00C9|P\u00DD?\u0084\u00D5\u00B5\u00B5G\u0009\u0017\u0092" +
"\u0016\u00D5\u00D9\u0089y\u00FB\u001B",
cS= "\u00D11\u000B\u00A6\u0098\u00DF\u00B5\u00AC/\u00FDr\u00DB\u00D0" +
"\u001A\u00DF\u00B7\u00B8\u00E1\u00AF\u00EDj&~\u0096\u00BA|\u0090E" +
"\u00F1,\u007F\u0099$\u00A1\u0099G\u00B3\u0091l\u00F7\u0008\u0001" +
"\u00F2\u00E2\u0085\u008E\u00FC\u0016ci \u00D8qWNi\u00A4X\u00FE" +
"\u00A3\u00F4\u0093=~\r\u0095t\u008Fr\u008E\u00B6Xq\u008B\u00CDX" +
"\u0082\u0015J\u00EE{T\u00A4\u001D\u00C2ZY\u00B5\u009C0\u00D59*\u00F2"+
"`\u0013\u00C5\u00D1\u00B0#(`\u0085\u00F0\u00CAAy\u0018\u00B8\u00DB8" +
"\u00EF\u008Ey\u00DC\u00B0`:\u0018\u000El\u009E\u000E\u008B\u00B0" +
"\u001E\u008A>\u00D7\u0015w\u00C1\u00BD1K'x\u00AF/\u00DAU`\\`\u00E6" +
"U%\u00F3\u00AAU\u00AB\u0094WH\u0098bc\u00E8\u0014@U\u00CA9j*\u00AB" +
"\u0010\u00B6\u00B4\u00CC\\4\u0011A\u00E8\u00CE\u00A1T\u0086\u00AF|r" +
"\u00E9\u0093\u00B3\u00EE\u0014\u0011co\u00BC*+\u00A9\u00C5]t\u00181" +
"\u00F6\u00CE\\>\u0016\u009B\u0087\u0093\u001E\u00AF\u00D6\u00BA3l$" +
"\u00CF\\z2S\u0081(\u0095\u0086w;\u008FH\u0098kK\u00B9\u00AF\u00C4" +
"\u00BF\u00E8\u001Bf(!\u0093a\u00D8\t\u00CC\u00FB!\u00A9\u0091H|" +
"\u00AC`]\u00EC\u00802\u00EF\u0084]]\u00E9\u0085u\u00B1\u00DC\u0002"+
"\u00EBe\u001B\u0088#\u0089>\u0081\u00D3\u0096\u00AC\u00C5\u000Fmo" +
"\u00F3\u0083\u00F4B9.\u000BD\u0082\u00A4\u0084 \u0004i\u00C8\u00F0J" +
"\u009E\u001F\u009B^!\u00C6hB\u00F6\u00E9l\u009Ag\u000C\u009Ca\u00AB" +
"\u00D3\u0088\u00F0jQ\u00A0\u00D2\u00D8T/h\u0096\u000F\u00A7(\u00ABQ3"+
"\u00A3n\u00EF\u000Bl\u0013z;\u00E4\u00BA;\u00F0P~\u00FB*\u0098\u00A1"+
"\u00F1e\u001D9\u00AF\u0001vf\u00CAY>\u0082C\u000E\u0088\u008C\u00EE" +
"\u0086\u0019Eo\u009F\u00B4}\u0084\u00A5\u00C3;\u008B^\u00BE\u00E0ou" +
"\u00D8\u0085\u00C1 s@\u001AD\u009FV\u00C1j\u00A6N\u00D3\u00AAb6?w" +
"\u0006\u001B\u00FE\u00DFrB\u009B\u0002=7\u00D0\u00D7$\u00D0\n\u0012H"+
"\u00DB\u000F\u00EA\u00D3I\u00F1\u00C0\u009B\u0007Sr\u00C9\u0080" +
"\u0099\u001B{%\u00D4y\u00D8\u00F6\u00E8\u00DE\u00F7\u00E3\u00FEP" +
"\u001A\u00B6yL;\u0097l\u00E0\u00BD\u0004\u00C0\u0006\u00BA\u00C1" +
"\u00A9O\u00B6@\u009F`\u00C4^\\\u009E\u00C2\u0019j$ch\u00FBo\u00AF>lS"+
"\u00B5\u00139\u00B2\u00EB;R\u00ECom\u00FCQ\u001F\u009B0\u0095,\u00CC"+
"\u0081ED\u00AF^\u00BD\t\u00BE\u00E3\u00D0\u0004\u00DE3J\u00FDf\u000F"+
"(\u0007\u0019.K\u00B3\u00C0\u00CB\u00A8WE\u00C8t\u000F\u00D2\u000B_9"+
"\u00B9\u00D3\u00FB\u00DBUy\u00C0\u00BD\u001A`2\n\u00D6\u00A1\u0000" +
"\u00C6@,ryg\u009F%\u00FE\u00FB\u001F\u00A3\u00CC\u008E\u00A5\u00E9" +
"\u00F8\u00DB2\"\u00F8<u\u0016\u00DF\u00FDak\u0015/P\u001E\u00C8" +
"\u00AD\u0005R\u00AB2=\u00B5\u00FA\u00FD#\u0087`S1{H>\u0000\u00DF" +
"\u0082\u009E\\W\u00BB\u00CAo\u008C\u00A0\u001A\u0087V.\u00DF\u0017i" +
"\u00DB\u00D5B\u00A8\u00F6(~\u00FF\u00C3\u00ACg2\u00C6\u008COUsi['" +
"\u00B0\u00BB\u00CAX\u00C8\u00E1\u00FF\u00A3]\u00B8\u00F0\u0011\u00A0"+
"\u0010\u00FA=\u0098\u00FD!\u0083\u00B8J\u00FC\u00B5l-\u00D1\u00D3[" +
"\u009AS\u00E4y\u00B6\u00F8Ee\u00D2\u008EI\u00BCK\u00FB\u0097\u0090" +
"\u00E1\u00DD\u00F2\u00DA\u00A4\u00CB~3b\u00FB\u0013A\u00CE\u00E4" +
"\u00C6\u00E8\u00EF \u00CA\u00DA6wL\u0001\u00D0~\u009E\u00FE+\u00F1" +
"\u001F\u00B4\u0095\u00DB\u00DAM\u00AE\u0090\u0091\u0098\u00EA\u00AD" +
"\u008Eqk\u0093\u00D5\u00A0\u00D0\u008E\u00D1\u00D0\u00AF\u00C7%" +
"\u00E0\u008E<[/\u008Eu\u0094\u00B7\u008F\u00F6\u00E2\u00FB\u00F2" +
"\u0012+d\u0088\u0088\u00B8\u0012\u0090\r\u00F0\u001CO\u00AD^\u00A0h" +
"\u008F\u00C3\u001C\u00D1\u00CF\u00F1\u0091\u00B3\u00A8\u00C1\u00AD//"+
"\"\u0018\u00BE\u000E\u0017w\u00EAu-\u00FE\u008B\u0002\u001F\u00A1" +
"\u00E5\u00A0\u00CC\u000F\u00B5ot\u00E8\u0018\u00AC\u00F3\u00D6\u00CE"+
"\u0089\u00E2\u0099\u00B4\u00A8O\u00E0\u00FD\u0013\u00E0\u00B7|\u00C4"+
";\u0081\u00D2\u00AD\u00A8\u00D9\u0016_\u00A2f\u0080\u0095w\u0005" +
"\u0093\u00CCs\u0014!\u001A\u0014w\u00E6\u00AD ew\u00B5\u00FA\u0086" +
"\u00C7TB\u00F5\u00FB\u009D5\u00CF\u00EB\u00CD\u00AF\u000C{>\u0089" +
"\u00A0\u00D6A\u001B\u00D3\u00AE\u001E~I\u0000%\u000E- q\u00B3^\"h" +
"\u0000\u00BBW\u00B8\u00E0\u00AF$d6\u009B\u00F0\t\u00B9\u001EUc\u0091"+
"\u001DY\u00DF\u00A6\u00AAx\u00C1C\u0089\u00D9ZS\u007F }[\u00A2\u0002"+
"\u00E5\u00B9\u00C5\u0083&\u0003vb\u0095\u00CF\u00A9\u0011\u00C8" +
"\u0019hNsJA\u00B3G-\u00CA{\u0014\u00A9J\u001BQ\u0000R\u009AS)\u0015" +
"\u00D6\u000FW?\u00BC\u009B\u00C6\u00E4+`\u00A4v\u0081\u00E6t\u0000" +
"\u0008\u00BAo\u00B5W\u001B\u00E9\u001F\u00F2\u0096\u00ECk*\r\u00D9" +
"\u0015\u00B6ce!\u00E7\u00B9\u00F9\u00B6\u00FF4\u0005.\u00C5\u0085VdS"+
"\u00B0-]\u00A9\u009F\u008F\u00A1\u0008\u00BAG\u0099n\u0085\u0007j" +
"Kzp\u00E9\u00B5\u00B3)D\u00DBu\t.\u00C4\u0019\u00ADn\u00A6\u00B0" +
"I\u00A7\u00DF}\u009C\u00EE`\u00B8\u008F\u00ED\u00B2f\u00EC\u00AA" +
"\u008Cqi\u009A\u0017\u00FFVdRl\u00C2\u00B1\u009E\u00E1\u00196\u0002" +
"\u00A5u\tL)\u00A0Y\u0013@\u00E4\u0018:>?T\u0098\u009A[B\u009Dek" +
"\u008F\u00E4\u00D6\u0099\u00F7?\u00D6\u00A1\u00D2\u009C\u0007\u00EF" +
"\u00E80\u00F5M-8\u00E6\u00F0%]\u00C1L\u00DD \u0086\u0084p\u00EB&c" +
"\u0082\u00E9\u00C6\u0002\u001E\u00CC^\thk?>\u00BA\u00EF\u00C9<\u0097"+
"\u0018\u0014kjp\u00A1h\u007F5\u0084R\u00A0\u00E2\u0086\u00B7\u009CS" +
"\u0005\u00AAP\u00077>\u0007\u0084\u001C\u007F\u00DE\u00AE\\\u008E}D" +
"\u00ECW\u0016\u00F2\u00B8\u00B0:\u00DA7\u00F0P\u000C\r\u00F0\u001C" +
"\u001F\u0004\u0002\u0000\u00B3\u00FF\u00AE\u000C\u00F5\u001A<\u00B5t"+
"\u00B2%\u0083zX\u00DC\t!\u00BD\u00D1\u0091\u0013\u00F9|\u00A9/\u00F6"+
"\u00942Gs\"\u00F5G\u0001:\u00E5\u00E5\u00817\u00C2\u00DA\u00DC\u00C8"+
"\u00B5v4\u009A\u00F3\u00DD\u00A7\u00A9DaF\u000F\u00D0\u0003\u000E" +
"\u00EC\u00C8\u00C7>\u00A4u\u001EA\u00E28\u00CD\u0099;\u00EA\u000E/" +
"2\u0080\u00BB\u00A1\u0018>\u00B31NT\u008B8Om\u00B9\u0008oB\r\u0003" +
"\u00F6\n\u0004\u00BF,\u00B8\u0012\u0090$\u0097|yVy\u00B0r\u00BC" +
"\u00AF\u0089\u00AF\u00DE\u009Aw\u001F\u00D9\u0093\u0008\u0010\u00B3" +
"\u008B\u00AE\u0012\u00DC\u00CF?.U\u0012r\u001F.kq$P\u001A\u00DD" +
"\u00E6\u009F\u0084\u00CD\u0087zXG\u0018t\u0008\u00DA\u0017\u00BC" +
"\u009F\u009A\u00BC\u00E9K}\u008C\u00ECz\u00EC:\u00DB\u0085\u001D" +
"\u00FAc\tCf\u00C4d\u00C3\u00D2\u00EF\u001C\u0018G2\u0015\u00D9\u0008"+
"\u00DDC;7$\u00C2\u00BA\u0016\u0012\u00A1MC*e\u00C4QP\u0094\u0000" +
"\u0002\u0013:\u00E4\u00DDq\u00DF\u00F8\u009E\u00101NU\u0081\u00ACw" +
"\u00D6_\u0011\u0019\u009B\u00045V\u00F1\u00D7\u00A3\u00C7k<\u0011" +
"\u0018;Y$\u00A5\t\u00F2\u008F\u00E6\u00ED\u0097\u00F1\u00FB\u00FA" +
"\u009E\u00BA\u00BF,\u001E\u0015<n\u0086\u00E3Ep\u00EA\u00E9o\u00B1" +
"\u0086\u000E^\nZ>*\u00B3w\u001F\u00E7\u001CN=\u0006\u00FA)e\u00DC" +
"\u00B9\u0099\u00E7\u001D\u000F\u0080>\u0089\u00D6Rf\u00C8%.L\u00C9x" +
"\u009C\u0010\u00B3j\u00C6\u0015\u000E\u00BA\u0094\u00E2\u00EAx\u00A5"+
"\u00FC<S\u001E\n-\u00F4\u00F2\u00F7N\u00A76\u001D+=\u00199&\u000F" +
"\u0019\u00C2y`R#\u00A7\u0008\u00F7\u0013\u0012\u00B6\u00EB\u00AD" +
"\u00FEn\u00EA\u00C3\u001Ff\u00E3\u00BCE\u0095\u00A6{\u00C8\u0083" +
"\u00B1\u007F7\u00D1\u0001\u008C\u00FF(\u00C32\u00DD\u00EF\u00BElZ" +
"\u00A5eX!\u0085h\u00AB\u0098\u0002\u00EE\u00CE\u00A5\u000F\u00DB/" +
"\u0095;*\u00EF}\u00AD[n/\u0084\u0015!\u00B6()\u0007ap\u00EC\u00DDGu" +
"a\u009F\u0015\u0010\u0013\u00CC\u00A80\u00EBa\u00BD\u0096\u00034" +
"\u00FE\u001E\u00AA\u0003c\u00CF\u00B5s\\\u0090Lp\u00A29\u00D5\u009E" +
"\u009E\u000B\u00CB\u00AA\u00DE\u0014\u00EE\u00CC\u0086\u00BC`b," +
"\u00A7\u009C\u00AB\\\u00AB\u00B2\u00F3\u0084nd\u008B\u001E\u00AF" +
"\u0019\u00BD\u00F0\u00CA\u00A0#i\u00B9eZ\u00BBP@hZ2<*\u00B4\u00B31" +
"\u009E\u00E9\u00D5\u00C0!\u00B8\u00F7\u009BT\u000B\u0019\u0087_" +
"\u00A0\u0099\u0095\u00F7\u0099~b=}\u00A8\u00F87\u0088\u009A\u0097" +
"\u00E3-w\u0011\u00ED\u0093_\u0016h\u0012\u0081\u000E5\u0088)\u00C7" +
"\u00E6\u001F\u00D6\u0096\u00DE\u00DF\u00A1xX\u00BA\u0099W\u00F5" +
"\u0084\u00A5\u001B\"rc\u009B\u0083\u00C3\u00FF\u001A\u00C2F\u0096" +
"\u00CD\u00B3\n\u00EBS.0T\u008F\u00D9H\u00E4m\u00BC1(X\u00EB\u00F2" +
"\u00EF4\u00C6\u00FF\u00EA\u00FE(\u00EDa\u00EE|<s]J\u0014\u00D9\u00E8"+
"d\u00B7\u00E3B\u0010]\u0014 >\u0013\u00E0E\u00EE\u00E2\u00B6\u00A3" +
"\u00AA\u00AB\u00EA\u00DBlO\u0015\u00FA\u00CBO\u00D0\u00C7B\u00F4B" +
"\u00EFj\u00BB\u00B5eO;\u001DA\u00CD!\u0005\u00D8\u001Ey\u009E\u0086" +
"\u0085M\u00C7\u00E4KGj=\u0081bP\u00CFb\u00A1\u00F2[\u008D&F\u00FC" +
"\u0088\u0083\u00A0\u00C1\u00C7\u00B6\u00A3\u007F\u0015$\u00C3i\u00CB"+
"t\u0092G\u0084\u008A\u000BV\u0092\u00B2\u0085\t[\u00BF\u0000\u00AD" +
"\u0019H\u009D\u0014b\u00B1t#\u0082\u000E\u0000XB\u008D*\u000CU\u00F5"+
"\u00EA\u001D\u00AD\u00F4>#?pa3r\u00F0\u0092\u008D\u0093~A\u00D6_" +
"\u00EC\u00F1l\";\u00DB|\u00DE7Y\u00CB\u00EEt`@\u0085\u00F2\u00A7" +
"\u00CEw2n\u00A6\u0007\u0080\u0084\u0019\u00F8P\u009E\u00E8\u00EF" +
"\u00D8Ua\u00D9\u00975\u00A9i\u00A7\u00AA\u00C5\u000C\u0006\u00C2Z" +
"\u0004\u00AB\u00FC\u0080\u000B\u00CA\u00DC\u009EDz.\u00C3E4\u0084" +
"\u00FD\u00D5g\u0005\u000E\u001E\u009E\u00C9\u00DBs\u00DB\u00D3\u0010"+
"U\u0088\u00CDg_\u00DAy\u00E3gC@\u00C5\u00C44eq>8\u00D8=(\u00F8\u009E"+
"\u00F1m\u00FF \u0015>!\u00E7\u008F\u00B0=J\u00E6\u00E3\u009F+\u00DB" +
"\u0083\u00AD\u00F7\u00E9=Zh\u0094\u0081@\u00F7\u00F6L&\u001C\u0094i)"+
"4A\u0015 \u00F7v\u0002\u00D4\u00F7\u00BC\u00F4k.\u00D4\u00A2\u0000h" +
"\u00D4\u0008$q3 \u00F4jC\u00B7\u00D4\u00B7P\u0000a\u00AF\u001E9" +
"\u00F6.\u0097$EF\u0014!Ot\u00BF\u008B\u0088@M\u0095\u00FC\u001D" +
"\u0096\u00B5\u0091\u00AFp\u00F4\u00DD\u00D3f\u00A0/E\u00BF\u00BC\t" +
"\u00EC\u0003\u00BD\u0097\u0085\u007F\u00ACm\u00D01\u00CB\u0085\u0004"+
"\u0096\u00EB'\u00B3U\u00FD9A\u00DA%G\u00E6\u00AB\u00CA\n\u009A(Px%S" +
"\u0004)\u00F4\n,\u0086\u00DA\u00E9\u00B6m\u00FBh\u00DC\u0014b\u00D7H"+
"i\u0000h\u000E\u00C0\u00A4'\u00A1\u008D\u00EEO?\u00FE\u00A2\u00E8" +
"\u0087\u00AD\u008C\u00B5\u008C\u00E0\u0006z\u00F4\u00D6\u00B6\u00AA" +
"\u00CE\u001E|\u00D37_\u00EC\u00CEx\u00A3\u0099@k*B \u00FE\u009E5" +
"\u00D9\u00F3\u0085\u00B9\u00EE9\u00D7\u00AB;\u0012N\u008B\u001D" +
"\u00C9\u00FA\u00F7Km\u0018V&\u00A3f1\u00EA\u00E3\u0097\u00B2:n\u00FA"+
"t\u00DD[C2hA\u00E7\u00F7\u00CAx \u00FB\u00FB\n\u00F5N\u00D8\u00FE" +
"\u00B3\u0097E@V\u00AC\u00BAH\u0095'US:: \u0083\u008D\u0087\u00FEk" +
"\u00A9\u00B7\u00D0\u0096\u0095KU\u00A8g\u00BC\u00A1\u0015\u009AX" +
"\u00CC\u00A9)c\u0099\u00E1\u00DB3\u00A6*JV?1%\u00F9^\u00F4~\u001C" +
"\u0090)1|\u00FD\u00F8\u00E8\u0002\u0004'/p\u0080\u00BB\u0015\\\u0005"+
"(,\u00E3\u0095\u00C1\u0015H\u00E4\u00C6m\"H\u00C1\u0013?\u00C7\u000F"+
"\u0086\u00DC\u0007\u00F9\u00C9\u00EEA\u0004\u001F\u000F@Gy\u00A4]" +
"\u0088n\u00172_Q\u00EB\u00D5\u009B\u00C0\u00D1\u00F2\u00BC\u00C1" +
"\u008FA\u00115d%{x4`*\u009C`\u00DF\u00F8\u00E8\u00A3\u001Fcl\u001B" +
"\u000E\u0012\u00B4\u00C2\u0002\u00E12\u009E\u00AFfO\u00D1\u00CA" +
"\u00D1\u0081\u0015k#\u0095\u00E03>\u0092\u00E1;$\u000Bb\u00EE\u00BE" +
"\u00B9\"\u0085\u00B2\u00A2\u000E\u00E6\u00BA\r\u0099\u00DEr\u000C" +
"\u008C-\u00A2\u00F7(\u00D0\u0012xE\u0095\u00B7\u0094\u00FDd}\u0008b" +
"\u00E7\u00CC\u00F5\u00F0TI\u00A3o\u0087}H\u00FA\u00C3\u009D\u00FD'" +
"\u00F3>\u008D\u001E\nGcA\u0099.\u00FFt:on\u00AB\u00F4\u00F8\u00FD7" +
"\u00A8\u0012\u00DC`\u00A1\u00EB\u00DD\u00F8\u0099\u001B\u00E1L\u00DB"+
"nk\r\u00C6{U\u0010mg,7'e\u00D4;\u00DC\u00D0\u00E8\u0004\u00F1)\r" +
"\u00C7\u00CC\u0000\u00FF\u00A3\u00B59\u000F\u0092i\u000F\u00ED\u000B"+
"f{\u009F\u00FB\u00CE\u00DB}\u009C\u00A0\u0091\u00CF\u000B\u00D9" +
"\u0015^\u00A3\u00BB\u0013/\u0088Q[\u00AD${\u0094y\u00BFv;\u00D6" +
"\u00EB79.\u00B3\u00CC\u0011Yy\u0080&\u00E2\u0097\u00F4.1-hB\u00AD" +
"\u00A7\u00C6j+;\u0012uL\u00CCx.\u00F1\u001Cj\u0012B7\u00B7\u0092Q" +
"\u00E7\u0006\u00A1\u00BB\u00E6K\u00FBcP\u001Ak\u0010\u0018\u0011" +
"\u00CA\u00ED\u00FA=%\u00BD\u00D8\u00E2\u00E1\u00C3\u00C9DB\u0016Y\n" +
"\u0012\u0013\u0086\u00D9\u000C\u00ECn\u00D5\u00AB\u00EA*d\u00AFgN" +
"\u00DA\u0086\u00A8_\u00BE\u00BF\u00E9\u0088d\u00E4\u00C3\u00FE\u009D"+
"\u00BC\u0080W\u00F0\u00F7\u00C0\u0086`x{\u00F8`\u0003`M\u00D1\u00FD" +
"\u0083F\u00F68\u001F\u00B0wE\u00AE\u0004\u00D76\u00FC\u00CC\u0083Bk3"+
"\u00F0\u001E\u00ABq\u00B0\u0080A\u0087<\u0000^_w\u00A0W\u00BE\u00BD" +
"\u00E8\u00AE$UFB\u0099\u00BFX.aNX\u00F4\u008F\u00F2\u00DD\u00FD" +
"\u00A2\u00F4t\u00EF8\u0087\u0089\u00BD\u00C2Sf\u00F9\u00C3\u00C8" +
"\u00B3\u008Et\u00B4u\u00F2UF\u00FC\u00D9\u00B9z\u00EB&a\u008B\u001D" +
"\u00DF\u0084\u0084j\u000Ey\u0091_\u0095\u00E2FnY\u008E \u00B4Wp" +
"\u008C\u00D5U\u0091\u00C9\u0002\u00DEL\u00B9\u000B\u00AC\u00E1\u00BB"+
"\u0082\u0005\u00D0\u0011\u00A8bHut\u00A9\u009E\u00B7\u007F\u0019" +
"\u00B6\u00E0\u00A9\u00DC\tf-\t\u00A1\u00C42F3\u00E8Z\u001F\u0002\t" +
"\u00F0\u00BE\u008CJ\u0099\u00A0%\u001Dn\u00FE\u0010\u001A\u00B9=" +
"\u001D\u000B\u00A5\u00A4\u00DF\u00A1\u0086\u00F2\u000F(h\u00F1i" +
"\u00DC\u00B7\u00DA\u0083W9\u0006\u00FE\u00A1\u00E2\u00CE\u009BO" +
"\u00CD\u007FRP\u0011^\u0001\u00A7\u0006\u0083\u00FA\u00A0\u0002" +
"\u00B5\u00C4\r\u00E6\u00D0'\u009A\u00F8\u008C'w?\u0086A\u00C3`L" +
"\u0006a\u00A8\u0006\u00B5\u00F0\u0017z(\u00C0\u00F5\u0086\u00E0" +
"\u0000`X\u00AA0\u00DC}b\u0011\u00E6\u009E\u00D7#8\u00EAcS\u00C2" +
"\u00DD\u0094\u00C2\u00C2\u00164\u00BB\u00CB\u00EEV\u0090\u00BC\u00B6"+
"\u00DE\u00EB\u00FC}\u00A1\u00CEY\u001Dvo\u0005\u00E4\tK|\u0001\u0088"+
"9r\n=|\u0092|$\u0086\u00E3r_rM\u009D\u00B9\u001A\u00C1[\u00B4\u00D3" +
"\u009E\u00B8\u00FC\u00EDTUx\u0008\u00FC\u00A5\u00B5\u00D8=|\u00D3M" +
"\u00AD\u000F\u00C4\u001EP\u00EF^\u00B1a\u00E6\u00F8\u00A2\u0085" +
"\u0014\u00D9lQ\u0013<o\u00D5\u00C7\u00E7V\u00E1N\u00C46*\u00BF\u00CE"+
"\u00DD\u00C6\u00C87\u00D7\u009A24\u0092c\u0082\u0012g\u000E\u00FA" +
"\u008E@`\u0000\u00E0:9\u00CE7\u00D3\u00FA\u00F5\u00CF\u00AB\u00C2w7Z"+
"\u00C5-\u001B\\\u00B0g\u009EO\u00A37B\u00D3\u0082'@\u0099\u00BC" +
"\u009B\u00BE\u00D5\u0011\u008E\u009D\u00BF\u000Fs\u0015\u00D6-\u001C"+
"~\u00C7\u0000\u00C4{\u00B7\u008C\u001Bk!\u00A1\u0090E\u00B2n\u00B1" +
"\u00BEj6n\u00B4WH\u00AB/\u00BC\u0094ny\u00C6\u00A3v\u00D2eI\u00C2" +
"\u00C8S\u000F\u00F8\u00EEF\u008D\u00DE}\u00D5s\n\u001DL\u00D0M\u00C6"+
")9\u00BB\u00DB\u00A9\u00BAFP\u00AC\u0095&\u00E8\u00BE^\u00E3\u0004" +
"\u00A1\u00FA\u00D5\u00F0j-Q\u009Ac\u00EF\u008C\u00E2\u009A\u0086" +
"\u00EE\"\u00C0\u0089\u00C2\u00B8C$.\u00F6\u00A5\u001E\u0003\u00AA" +
"\u009C\u00F2\u00D0\u00A4\u0083\u00C0a\u00BA\u009B\u00E9jM\u008F" +
"\u00E5\u0015P\u00BAd[\u00D6(&\u00A2\u00F9\u00A7::\u00E1K\u00A9\u0095"+
"\u0086\u00EFUb\u00E9\u00C7/\u00EF\u00D3\u00F7R\u00F7\u00DA?\u0004oiw"+
"\u00FA\nY\u0080\u00E4\u00A9\u0015\u0087\u00B0\u0086\u0001\u009B\t" +
"\u00E6\u00AD;>\u00E5\u0093\u00E9\u0090\u00FDZ\u009E4\u00D7\u0097," +
"\u00F0\u00B7\u00D9\u0002+\u008BQ\u0096\u00D5\u00AC:\u0001}\u00A6}" +
"\u00D1\u00CF>\u00D6|}-(\u001F\u009F%\u00CF\u00AD\u00F2\u00B8\u009BZ" +
"\u00D6\u00B4rZ\u0088\u00F5L\u00E0)\u00ACq\u00E0\u0019\u00A5\u00E6G" +
"\u00B0\u00AC\u00FD\u00ED\u0093\u00FA\u009B\u00E8\u00D3\u00C4\u008D(;"+
"W\u00CC\u00F8\u00D5f)y\u0013.(x_\u0001\u0091\u00EDu`U\u00F7\u0096" +
"\u000ED\u00E3\u00D3^\u008C\u0015\u0005m\u00D4\u0088\u00F4m\u00BA" +
"\u0003\u00A1a%\u0005d\u00F0\u00BD\u00C3\u00EB\u009E\u0015<\u0090W" +
"\u00A2\u0097'\u001A\u00EC\u00A9:\u0007*\u001B?m\u009B\u001Ec!\u00F5" +
"\u00F5\u009Cf\u00FB&\u00DC\u00F3\u0019u3\u00D9(\u00B1U\u00FD\u00F5" +
"\u0003V4\u0082\u008A\u00BA<\u00BB(Qw\u0011\u00C2\n\u00D9\u00F8\u00AB"+
"\u00CCQg\u00CC\u00AD\u0092_M\u00E8\u0017Q80\u00DC\u008E7\u009DXb" +
"\u0093 \u00F9\u0091\u00EAz\u0090\u00C2\u00FB>{\u00CEQ!\u00CEdwO" +
"\u00BE2\u00A8\u00B6\u00E3~\u00C3)=FH\u00DESid\u0013\u00E6\u0080" +
"\u00A2\u00AE\u0008\u0010\u00DDm\u00B2$i\u0085-\u00FD\t\u0007!f\u00B3"+
"\u009AF\ndE\u00C0\u00DDXl\u00DE\u00CF\u001C \u00C8\u00AE[\u00BE" +
"\u00F7\u00DD\u001BX\u008D@\u00CC\u00D2\u0001\u007Fk\u00B4\u00E3" +
"\u00BB\u00DD\u00A2j~:Y\u00FFE>5\nD\u00BC\u00B4\u00CD\u00D5r\u00EA" +
"\u00CE\u00A8\u00FAd\u0084\u00BB\u008Df\u0012\u00AE\u00BF<oG\u00D2" +
"\u009B\u00E4cT/]\u009E\u00AE\u00C2w\u001B\u00F6Ncpt\u000E\r\u008D" +
"\u00E7[\u0013W\u00F8r\u0016q\u00AFS}]@@\u00CB\u0008N\u00B4\u00E2" +
"\u00CC4\u00D2Fj\u0001\u0015\u00AF\u0084\u00E1\u00B0\u0004(\u0095" +
"\u0098:\u001D\u0006\u00B8\u009F\u00B4\u00CEn\u00A0Ho?;\u00825 \u00AB"+
"\u0082\u0001\u001A\u001DK'r'\u00F8a\u0015`\u00B1\u00E7\u0093?\u00DC" +
"\u00BB:y+4E%\u00BD\u00A0\u00889\u00E1Q\u00CEyK/2\u00C9\u00B7\u00A0" +
"\u001F\u00BA\u00C9\u00E0\u001C\u00C8~\u00BC\u00C7\u00D1\u00F6\u00CF" +
"\u0001\u0011\u00C3\u00A1\u00E8\u00AA\u00C7\u001A\u0090\u0087I\u00D4O"+
"\u00BD\u009A\u00D0\u00DA\u00DE\u00CB\u00D5\n\u00DA8\u00039\u00C3*" +
"\u00C6\u00916g\u008D\u00F91|\u00E0\u00B1+O\u00F7\u009EY\u00B7C\u00F5"+
"\u00BB:\u00F2\u00D5\u0019\u00FF'\u00D9E\u009C\u00BF\u0097\",\u0015" +
"\u00E6\u00FC*\u000F\u0091\u00FCq\u009B\u0094\u0015%\u00FA\u00E5" +
"\u0093a\u00CE\u00B6\u009C\u00EB\u00C2\u00A8dY\u0012\u00BA\u00A8" +
"\u00D1\u00B6\u00C1\u0007^\u00E3\u0005j\u000C\u0010\u00D2Pe\u00CB" +
"\u0003\u00A4B\u00E0\u00ECn\u000E\u0016\u0098\u00DB;L\u0098\u00A0" +
"\u00BE2x\u00E9d\u009F\u001F\u00952\u00E0\u00D3\u0092\u00DF\u00D3" +
"\u00A04+\u0089q\u00F2\u001E\u001B\ntAK\u00A34\u008C\u00C5\u00BEq " +
"\u00C3v2\u00D8\u00DF5\u009F\u008D\u009B\u0099/.\u00E6\u000BoG\u000F" +
"\u00E3\u00F1\u001D\u00E5L\u00DAT\u001E\u00DA\u00D8\u0091\u00CEby" +
"\u00CF\u00CD>~o\u0016\u0018\u00B1f\u00FD,\u001D\u0005\u0084\u008F" +
"\u00D2\u00C5\u00F6\u00FB\"\u0099\u00F5#\u00F3W\u00A62v#\u0093\u00A8" +
"51V\u00CC\u00CD\u0002\u00AC\u00F0\u0081bZu\u00EB\u00B5n\u00166\u0097"+
"\u0088\u00D2s\u00CC\u00DE\u0096b\u0092\u0081\u00B9I\u00D0LP\u0090" +
"\u001Bq\u00C6V\u0014\u00E6\u00C6\u00C7\u00BD2z\u0014\nE\u00E1\u00D0" +
"\u0006\u00C3\u00F2{\u009A\u00C9\u00AAS\u00FDb\u00A8\u000F\u0000" +
"\u00BB%\u00BF\u00E25\u00BD\u00D2\u00F6q\u0012i\u0005\u00B2\u0004" +
"\u0002\"\u00B6\u00CB\u00CF|\u00CDv\u009C+S\u0011>\u00C0\u0016@\u00E3"+
"\u00D38\u00AB\u00BD`%G\u00AD\u00F0\u00BA8 \u009C\u00F7F\u00CEvw" +
"\u00AF\u00A1\u00C5 u``\u0085\u00CB\u00FEN\u008A\u00E8\u008D\u00D8z" +
"\u00AA\u00F9\u00B0L\u00F9\u00AA~\u0019H\u00C2\\\u0002\u00FB\u008A" +
"\u008C\u0001\u00C3j\u00E4\u00D6\u00EB\u00E1\u00F9\u0090\u00D4\u00F8i"+
"\u00A6\\\u00DE\u00A0?\t%-\u00C2\u0008\u00E6\u009F\u00B7Na2\u00CEw" +
"\u00E2[W\u008F\u00DF\u00E3:\u00C3r\u00E6";
/** Self eplanatory constants */
private static final int
ROUNDS = 16,
BLOCK_SIZE = 8,
MIN_USER_KEY_LENGTH = 40/8, // given in bytes from a value in bits
MAX_USER_KEY_LENGTH = 448/8; // given in bytes from a value in bits
/** P-box and S-boxes */
private static final int[]
sP = new int[ROUNDS+2],
sS = new int[1024];
/**
* Expand the compressed (see above) data into the P-box and S-boxes.
*
* We use the lower 8 bits of every character. Every four characters
* make up one 32-bit integer.
*
* FIXME: Encoding this in 7-bits per byte would be better because of Sun's
* internal .class file's UTF8 format. This requires a special decoder...
* Still this is better than Cryptix IJCE 3.0.3 for which the .class
* file was 61KB (this one yields 11KB). --gelderen
*/
static
{
for(int i=0, j=0; i<sP.length; i++)
sP[i] = (cP.charAt(j++) << 24) |
(cP.charAt(j++) << 16) |
(cP.charAt(j++) << 8) |
(cP.charAt(j++) );
for(int i=0, j=0; i<sS.length; i++)
sS[i] = (cS.charAt(j++) << 24) |
(cS.charAt(j++) << 16) |
(cS.charAt(j++) << 8) |
(cS.charAt(j++) );
}
// Instance variables
// ...................................................................
/** P-box, used during key-setup */
private final int[] P = new int[ROUNDS + 2];
/**
* Individual ints representing the session key taken from int[] P.
* We use these as a speedup instead of the P-array itself.
*/
private int
K00, K01, K02, K03, K04, K05, K06, K07, K08,
K09, K10, K11, K12, K13, K14, K15, K16, K17;
/** 4 S-boxes */
private final int[]
S0 = new int[256],
S1 = new int[256],
S2 = new int[256],
S3 = new int[256];
// Constructor
// ...................................................................
public Blowfish()
{
super(BLOCK_SIZE);
}
// BPI Methods
// ...................................................................
/**
* Initialize the object for encryption or decryption, given a Key.
* <p>
* This method expects a key with algorithm 'Blowfish' and
* format 'RAW'. Both are case insensitive.
* <p>
* FIXME: checks need overhaul (or moved out to superclass).
*
* @param key key
* @param decrypt true for decrypt mode, false for encrypt mode
*
* @throws InvalidKeyException when key==null or getAlgorithm()!=Blowfish
* or getFormat()!=RAW or getEncoded()==null or size<40 or
* size>448
*/
protected void coreInit(Key key, boolean decrypt)
throws InvalidKeyException
{
if( key==null )
throw new InvalidKeyException("Key missing");
if( !key.getAlgorithm().equalsIgnoreCase("Blowfish") )
throw new InvalidKeyException("Wrong algorithm: Blowfish required");
if( !key.getFormat().equalsIgnoreCase("RAW") )
throw new InvalidKeyException("Wrong format: RAW bytes needed");
byte[] userkey = key.getEncoded();
if(userkey == null)
throw new InvalidKeyException("RAW bytes missing");
int len = userkey.length ;
if(len < MIN_USER_KEY_LENGTH || len > MAX_USER_KEY_LENGTH)
throw new InvalidKeyException("Invalid user key length");
// Initialize ourselves (S0, S1, S2, S3) from the huge static S-box
System.arraycopy(sS, 0, S0, 0, 256);
System.arraycopy(sS, 256, S1, 0, 256);
System.arraycopy(sS, 512, S2, 0, 256);
System.arraycopy(sS, 768, S3, 0, 256);
// Initialize our P-box from the static copy
System.arraycopy(sP , 0, P , 0, ROUNDS+2);
// Merge key into P-box.
// Depends on correct key-size !!
int ri;
for (int i = 0, j = 0; i < ROUNDS + 2; i++)
{
ri = 0;
for (int k = 0; k < 4; k++)
{
ri = (ri << 8) | (userkey[j++] & 0xFF);
j %= len;
}
P[i] ^= ri;
}
// Generate the P-array & S-boxes
keyEncrypt(0, 0, P, 0);
for (int i = 2; i < ROUNDS + 2; i += 2)
keyEncrypt(P[i - 2], P[i - 1], P, i);
keyEncrypt(P[ROUNDS], P[ROUNDS + 1], S0, 0);
for (int i = 2; i < 256; i += 2)
keyEncrypt(S0[i - 2], S0[i - 1], S0, i);
keyEncrypt(S0[254], S0[255], S1, 0);
for (int i = 2; i < 256; i += 2)
keyEncrypt(S1[i - 2], S1[i - 1], S1, i);
keyEncrypt(S1[254], S1[255], S2, 0);
for (int i = 2; i < 256; i += 2)
keyEncrypt(S2[i - 2], S2[i - 1], S2, i);
keyEncrypt(S2[254], S2[255], S3, 0);
for (int i = 2; i < 256; i += 2)
keyEncrypt(S3[i - 2], S3[i - 1], S3, i);
// Store subkeys in individual instance variables for speedup
if(decrypt)
{
K00 = P[17]; K01 = P[16]; K02 = P[15]; K03 = P[14]; K04 = P[13];
K05 = P[12]; K06 = P[11]; K07 = P[10]; K08 = P[ 9]; K09 = P[ 8];
K10 = P[ 7]; K11 = P[ 6]; K12 = P[ 5]; K13 = P[ 4]; K14 = P[ 3];
K15 = P[ 2]; K16 = P[ 1]; K17 = P[ 0];
}
else
{
K00 = P[ 0]; K01 = P[ 1]; K02 = P[ 2]; K03 = P[ 3]; K04 = P[ 4];
K05 = P[ 5]; K06 = P[ 6]; K07 = P[ 7]; K08 = P[ 8]; K09 = P[ 9];
K10 = P[10]; K11 = P[11]; K12 = P[12]; K13 = P[13]; K14 = P[14];
K15 = P[15]; K16 = P[16]; K17 = P[17];
}
}
/**
* Encrypt or decrypt a single block of data.
*
* @param in array containing datablock to be encrypted
* @param inOffset where the datablock starts
* @param out array where the output is to be stored
* @param outOffset where the output should start
*/
protected void coreCrypt(byte[] in, int inOffset, byte[] out, int outOffset)
{
int L = (in[inOffset++] ) << 24 |
(in[inOffset++] & 0xFF) << 16 |
(in[inOffset++] & 0xFF) << 8 |
(in[inOffset++] & 0xFF);
int R = (in[inOffset++] ) << 24 |
(in[inOffset++] & 0xFF) << 16 |
(in[inOffset++] & 0xFF) << 8 |
(in[inOffset ] & 0xFF);
L ^= K00;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K01;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K02;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K03;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K04;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K05;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K06;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K07;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K08;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K09;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K10;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K11;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K12;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K13;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K14;
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ K15;
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ K16;
R ^= K17;
out[outOffset++] = (byte)(R >>> 24);
out[outOffset++] = (byte)(R >>> 16);
out[outOffset++] = (byte)(R >>> 8);
out[outOffset++] = (byte)(R );
out[outOffset++] = (byte)(L >>> 24);
out[outOffset++] = (byte)(L >>> 16);
out[outOffset++] = (byte)(L >>> 8);
out[outOffset ] = (byte)(L );
}
// Internals
// ...................................................................
/**
* Perform a Blowfish encryption.
*
* This method is only called by the <code>makeKey</code> method to
* generate the key schedule from user data. It outputs the result to an
* int array.
*
* @param L left half (32-bit) of the plain text block.
* @param R right half (32-bit) of the plain text block.
* @param out the int array where the result will be saved.
* @param outOff where the data starts in the byte array.
*/
private void keyEncrypt(int L, int R, int[] out, int outOff)
{
L ^= P[0];
for(int i = 0; i < ROUNDS; )
{
R ^= (((S0[L >>> 24] + S1[(L >>> 16) & 0xFF]) ^ S2[(L >>> 8) & 0xFF]) + S3[L & 0xFF]) ^ P[++i];
L ^= (((S0[R >>> 24] + S1[(R >>> 16) & 0xFF]) ^ S2[(R >>> 8) & 0xFF]) + S3[R & 0xFF]) ^ P[++i];
}
out[outOff++] = R ^ P[ROUNDS + 1];
out[outOff ] = L;
}
}