001    package railo.runtime.crypt;
002    
003    import java.security.MessageDigest;
004    import java.util.Random;
005    
006    import railo.runtime.exp.ExceptionHandler;
007    
008    
009    /**
010     * implementation of the Blowfish encryption
011     */
012    public final class Blowfish {
013            private static class BlowfishCBC extends BlowfishECB {
014    
015                    long m_lCBCIV;
016    
017                    public long getCBCIV() {
018                            return m_lCBCIV;
019                    }
020    
021                    public void getCBCIV(byte dest[]) {
022                            Blowfish.longToByteArray(m_lCBCIV, dest, 0);
023                    }
024    
025                    public void setCBCIV(long lNewCBCIV) {
026                            m_lCBCIV = lNewCBCIV;
027                    }
028    
029                    public void setCBCIV(byte newCBCIV[]) {
030                            m_lCBCIV = Blowfish.byteArrayToLong(newCBCIV, 0);
031                    }
032    
033                    public void cleanUp() {
034                            m_lCBCIV = 0L;
035                            super.cleanUp();
036                    }
037    
038                    private long encryptBlockCBC(long lPlainblock) {
039                            lPlainblock ^= m_lCBCIV;
040                            lPlainblock = super.encryptBlock(lPlainblock);
041                            return m_lCBCIV = lPlainblock;
042                    }
043    
044                    private long decryptBlockCBC(long lCipherblock) {
045                            long lTemp = lCipherblock;
046                            lCipherblock = super.decryptBlock(lCipherblock);
047                            lCipherblock ^= m_lCBCIV;
048                            m_lCBCIV = lTemp;
049                            return lCipherblock;
050                    }
051    
052                    public void encrypt(byte inbuffer[], byte outbuffer[]) {
053                            int nLen = inbuffer.length;
054                            for(int nI = 0; nI < nLen; nI += 8) {
055                                    long lTemp = Blowfish.byteArrayToLong(inbuffer, nI);
056                                    lTemp = encryptBlockCBC(lTemp);
057                                    Blowfish.longToByteArray(lTemp, outbuffer, nI);
058                            }
059    
060                    }
061    
062                    public void encrypt(byte buffer[]) {
063                            int nLen = buffer.length;
064                            for(int nI = 0; nI < nLen; nI += 8) {
065                                    long lTemp = Blowfish.byteArrayToLong(buffer, nI);
066                                    lTemp = encryptBlockCBC(lTemp);
067                                    Blowfish.longToByteArray(lTemp, buffer, nI);
068                            }
069    
070                    }
071    
072                    public void encrypt(int inbuffer[], int outbuffer[]) {
073                            int nLen = inbuffer.length;
074                            for(int nI = 0; nI < nLen; nI += 2) {
075                                    long lTemp = Blowfish.intArrayToLong(inbuffer, nI);
076                                    lTemp = encryptBlockCBC(lTemp);
077                                    Blowfish.longToIntArray(lTemp, outbuffer, nI);
078                            }
079    
080                    }
081    
082                    public void encrypt(int buffer[]) {
083                            int nLen = buffer.length;
084                            for(int nI = 0; nI < nLen; nI += 2) {
085                                    long lTemp = Blowfish.intArrayToLong(buffer, nI);
086                                    lTemp = encryptBlockCBC(lTemp);
087                                    Blowfish.longToIntArray(lTemp, buffer, nI);
088                            }
089    
090                    }
091    
092                    public void encrypt(long inbuffer[], long outbuffer[]) {
093                            int nLen = inbuffer.length;
094                            for(int nI = 0; nI < nLen; nI++)
095                                    outbuffer[nI] = encryptBlockCBC(inbuffer[nI]);
096    
097                    }
098    
099                    public void encrypt(long buffer[]) {
100                            int nLen = buffer.length;
101                            for(int nI = 0; nI < nLen; nI++)
102                                    buffer[nI] = encryptBlockCBC(buffer[nI]);
103    
104                    }
105    
106                    public void decrypt(byte inbuffer[], byte outbuffer[]) {
107                            int nLen = inbuffer.length;
108                            for(int nI = 0; nI < nLen; nI += 8) {
109                                    long lTemp = Blowfish.byteArrayToLong(inbuffer, nI);
110                                    lTemp = decryptBlockCBC(lTemp);
111                                    Blowfish.longToByteArray(lTemp, outbuffer, nI);
112                            }
113    
114                    }
115    
116                    public void decrypt(byte buffer[]) {
117                            int nLen = buffer.length;
118                            for(int nI = 0; nI < nLen; nI += 8) {
119                                    long lTemp = Blowfish.byteArrayToLong(buffer, nI);
120                                    lTemp = decryptBlockCBC(lTemp);
121                                    Blowfish.longToByteArray(lTemp, buffer, nI);
122                            }
123    
124                    }
125    
126                    public void decrypt(int inbuffer[], int outbuffer[]) {
127                            int nLen = inbuffer.length;
128                            for(int nI = 0; nI < nLen; nI += 2) {
129                                    long lTemp = Blowfish.intArrayToLong(inbuffer, nI);
130                                    lTemp = decryptBlockCBC(lTemp);
131                                    Blowfish.longToIntArray(lTemp, outbuffer, nI);
132                            }
133    
134                    }
135    
136                    public void decrypt(int buffer[]) {
137                            int nLen = buffer.length;
138                            for(int nI = 0; nI < nLen; nI += 2) {
139                                    long lTemp = Blowfish.intArrayToLong(buffer, nI);
140                                    lTemp = decryptBlockCBC(lTemp);
141                                    Blowfish.longToIntArray(lTemp, buffer, nI);
142                            }
143    
144                    }
145    
146                    public void decrypt(long inbuffer[], long outbuffer[]) {
147                            int nLen = inbuffer.length;
148                            for(int nI = 0; nI < nLen; nI++)
149                                    outbuffer[nI] = decryptBlockCBC(inbuffer[nI]);
150    
151                    }
152    
153                    public void decrypt(long buffer[]) {
154                            int nLen = buffer.length;
155                            for(int nI = 0; nI < nLen; nI++)
156                                    buffer[nI] = decryptBlockCBC(buffer[nI]);
157    
158                    }
159    
160                    public BlowfishCBC(byte bfkey[]) {
161                            super(bfkey);
162                            setCBCIV(0L);
163                    }
164    
165                    public BlowfishCBC(byte bfkey[], long lInitCBCIV) {
166                            super(bfkey);
167                            setCBCIV(lInitCBCIV);
168                    }
169    
170                    public BlowfishCBC(byte bfkey[], byte initCBCIV[]) {
171                            super(bfkey);
172                            setCBCIV(initCBCIV);
173                    }
174            }
175    
176            private static class BlowfishECB {
177    
178                    public static final int MAXKEYLENGTH = 56;
179                    public static final int BLOCKSIZE = 8;
180                    static final int PBOX_ENTRIES = 18;
181                    static final int SBOX_ENTRIES = 256;
182                    int m_pbox[];
183                    int m_sbox1[];
184                    int m_sbox2[];
185                    int m_sbox3[];
186                    int m_sbox4[];
187                    static final int pbox_init[] = {
188                            0x243f6a88, 0x85a308d3, 0x13198a2e, 0x3707344, 0xa4093822, 0x299f31d0, 0x82efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 
189                            0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
190                    };
191                    static final int sbox_init_1[] = {
192                            0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 
193                            0x801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0xd95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 
194                            0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 
195                            0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 
196                            0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 
197                            0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 
198                            0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 
199                            0xf6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 
200                            0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 
201                            0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 
202                            0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x75372c9, 0x80991b7b, 
203                            0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x4c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 
204                            0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 
205                            0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 
206                            0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 
207                            0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 
208                            0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 
209                            0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 
210                            0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 
211                            0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 
212                            0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 
213                            0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 
214                            0x250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 
215                            0x207d5ba2, 0x2e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 
216                            0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x8ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 
217                            0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x8ba4799, 0x6e85076a
218                    };
219                    static final int sbox_init_2[] = {
220                            0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 
221                            0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 
222                            0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x21ecc5e, 0x9686b3f, 0x3ebaefc9, 
223                            0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 
224                            0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 
225                            0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0xfd0030e, 0xecc8c73e, 0xa4751e41, 
226                            0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 
227                            0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 
228                            0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 
229                            0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 
230                            0x43556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 
231                            0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 
232                            0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 
233                            0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x18cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 
234                            0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 
235                            0x334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 
236                            0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 
237                            0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0xe358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 
238                            0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 
239                            0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 
240                            0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 
241                            0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x95bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 
242                            0x58428d2a, 0xc55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 
243                            0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 
244                            0x9e447a2e, 0xc3453484, 0xfdd56705, 0xe1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 
245                            0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
246                    };
247                    static final int sbox_init_3[] = {
248                            0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 
249                            0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 
250                            0xbfbc09ec, 0x3bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 
251                            0xa2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 
252                            0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 
253                            0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 
254                            0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 
255                            0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x4272f70, 0x80bb155c, 0x5282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 
256                            0x7f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 
257                            0xdff8e8a3, 0x1f636c1b, 0xe12b4c2, 0x2e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 
258                            0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 
259                            0xc39dfd27, 0xf33e8d1e, 0xa476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 
260                            0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 
261                            0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 
262                            0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x6a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 
263                            0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0xa121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 
264                            0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 
265                            0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 
266                            0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 
267                            0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 
268                            0xe85a1f02, 0x9f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0xba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 
269                            0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0xde6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 
270                            0xf0177a28, 0xc0f586e0, 0x6058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 
271                            0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 
272                            0xed545578, 0x8fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 
273                            0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
274                    };
275                    static final int sbox_init_4[] = {
276                            0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 
277                            0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 
278                            0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 
279                            0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 
280                            0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 
281                            0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x22b8b51, 0x96d5ac3a, 0x17da67d, 0xd1cf3ed6, 0x7c7d2d28, 
282                            0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 
283                            0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x3a16125, 0x564f0bd, 
284                            0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 
285                            0x3563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 
286                            0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 
287                            0x69852dfd, 0x9072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 
288                            0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 
289                            0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x115af84, 
290                            0xe1b00428, 0x95983a1d, 0x6b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x11a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 
291                            0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 
292                            0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 
293                            0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0xf91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 
294                            0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 
295                            0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0xfe3f11d, 
296                            0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 
297                            0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 
298                            0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 
299                            0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 
300                            0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x2fb8a8c, 0x1c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 
301                            0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
302                    };
303    
304                    public void cleanUp() {
305                            for(int nI = 0; nI < 18; nI++)
306                                    m_pbox[nI] = 0;
307    
308                            for(int nI = 0; nI < 256; nI++)
309                                    m_sbox1[nI] = m_sbox2[nI] = m_sbox3[nI] = m_sbox4[nI] = 0;
310    
311                    }
312    
313                    public static boolean selfTest() {
314                            byte testKey1[] = {
315                                    28, 88, 127, 28, 19, -110, 79, -17
316                            };
317                            int tv_p1[] = {
318                                    0x30553228, 0x6d6f295a
319                            };
320                            int tv_c1[] = {
321                                    0x55cb3774, 0xd13ef201
322                            };
323                            int tv_t1[] = new int[2];
324                            String sTestKey2 = "Who is John Galt?";
325                            byte testKey2[] = sTestKey2.getBytes();
326                            int tv_p2[] = {
327                                    0xfedcba98, 0x76543210
328                            };
329                            int tv_c2[] = {
330                                    0xcc91732b, 0x8022f684
331                            };
332                            int tv_t2[] = new int[2];
333                            BlowfishECB testbf1 = new BlowfishECB(testKey1);
334                            testbf1.encrypt(tv_p1, tv_t1);
335                            if(tv_t1[0] != tv_c1[0] || tv_t1[1] != tv_c1[1])
336                                    return false;
337                            testbf1.decrypt(tv_t1);
338                            if(tv_t1[0] != tv_p1[0] || tv_t1[1] != tv_p1[1])
339                                    return false;
340                            BlowfishECB testbf2 = new BlowfishECB(testKey2);
341                            testbf2.encrypt(tv_p2, tv_t2);
342                            if(tv_t2[0] != tv_c2[0] || tv_t2[1] != tv_c2[1])
343                                    return false;
344                            testbf2.decrypt(tv_t2);
345                            return tv_t2[0] == tv_p2[0] && tv_t2[1] == tv_p2[1];
346                    }
347    
348                    protected long encryptBlock(long lPlainBlock) {
349                            int nHi = Blowfish.longHi32(lPlainBlock);
350                            int nLo = Blowfish.longLo32(lPlainBlock);
351                            int sbox1[] = m_sbox1;
352                            int sbox2[] = m_sbox2;
353                            int sbox3[] = m_sbox3;
354                            int sbox4[] = m_sbox4;
355                            int pbox[] = m_pbox;
356                            nHi ^= pbox[0];
357                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[1];
358                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[2];
359                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[3];
360                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[4];
361                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[5];
362                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[6];
363                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[7];
364                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[8];
365                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[9];
366                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[10];
367                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[11];
368                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[12];
369                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[13];
370                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[14];
371                            nLo ^= (sbox1[nHi >>> 24] + sbox2[nHi >>> 16 & 0xff] ^ sbox3[nHi >>> 8 & 0xff]) + sbox4[nHi & 0xff] ^ pbox[15];
372                            nHi ^= (sbox1[nLo >>> 24] + sbox2[nLo >>> 16 & 0xff] ^ sbox3[nLo >>> 8 & 0xff]) + sbox4[nLo & 0xff] ^ pbox[16];
373                            return Blowfish.makeLong(nHi, nLo ^ pbox[17]);
374                    }
375    
376                    protected long decryptBlock(long lCipherBlock) {
377                            int nHi = Blowfish.longHi32(lCipherBlock);
378                            int nLo = Blowfish.longLo32(lCipherBlock);
379                            nHi ^= m_pbox[17];
380                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[16];
381                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[15];
382                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[14];
383                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[13];
384                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[12];
385                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[11];
386                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[10];
387                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[9];
388                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[8];
389                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[7];
390                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[6];
391                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[5];
392                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[4];
393                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[3];
394                            nLo ^= (m_sbox1[nHi >>> 24] + m_sbox2[nHi >>> 16 & 0xff] ^ m_sbox3[nHi >>> 8 & 0xff]) + m_sbox4[nHi & 0xff] ^ m_pbox[2];
395                            nHi ^= (m_sbox1[nLo >>> 24] + m_sbox2[nLo >>> 16 & 0xff] ^ m_sbox3[nLo >>> 8 & 0xff]) + m_sbox4[nLo & 0xff] ^ m_pbox[1];
396                            return Blowfish.makeLong(nHi, nLo ^ m_pbox[0]);
397                    }
398    
399                    public void encrypt(byte inbuffer[], byte outbuffer[]) {
400                            int nLen = inbuffer.length;
401                            for(int nI = 0; nI < nLen; nI += 8) {
402                                    long lTemp = Blowfish.byteArrayToLong(inbuffer, nI);
403                                    lTemp = encryptBlock(lTemp);
404                                    Blowfish.longToByteArray(lTemp, outbuffer, nI);
405                            }
406    
407                    }
408    
409                    public void encrypt(byte buffer[]) {
410                            int nLen = buffer.length;
411                            for(int nI = 0; nI < nLen; nI += 8) {
412                                    long lTemp = Blowfish.byteArrayToLong(buffer, nI);
413                                    lTemp = encryptBlock(lTemp);
414                                    Blowfish.longToByteArray(lTemp, buffer, nI);
415                            }
416    
417                    }
418    
419                    public void encrypt(int inbuffer[], int outbuffer[]) {
420                            int nLen = inbuffer.length;
421                            for(int nI = 0; nI < nLen; nI += 2) {
422                                    long lTemp = Blowfish.intArrayToLong(inbuffer, nI);
423                                    lTemp = encryptBlock(lTemp);
424                                    Blowfish.longToIntArray(lTemp, outbuffer, nI);
425                            }
426    
427                    }
428    
429                    public void encrypt(int buffer[]) {
430                            int nLen = buffer.length;
431                            for(int nI = 0; nI < nLen; nI += 2) {
432                                    long lTemp = Blowfish.intArrayToLong(buffer, nI);
433                                    lTemp = encryptBlock(lTemp);
434                                    Blowfish.longToIntArray(lTemp, buffer, nI);
435                            }
436    
437                    }
438    
439                    public void encrypt(long inbuffer[], long outbuffer[]) {
440                            int nLen = inbuffer.length;
441                            for(int nI = 0; nI < nLen; nI++)
442                                    outbuffer[nI] = encryptBlock(inbuffer[nI]);
443    
444                    }
445    
446                    public void encrypt(long buffer[]) {
447                            int nLen = buffer.length;
448                            for(int nI = 0; nI < nLen; nI++)
449                                    buffer[nI] = encryptBlock(buffer[nI]);
450    
451                    }
452    
453                    public void decrypt(byte inbuffer[], byte outbuffer[]) {
454                            int nLen = inbuffer.length;
455                            for(int nI = 0; nI < nLen; nI += 8) {
456                                    long lTemp = Blowfish.byteArrayToLong(inbuffer, nI);
457                                    lTemp = decryptBlock(lTemp);
458                                    Blowfish.longToByteArray(lTemp, outbuffer, nI);
459                            }
460    
461                    }
462    
463                    public void decrypt(byte buffer[]) {
464                            int nLen = buffer.length;
465                            for(int nI = 0; nI < nLen; nI += 8) {
466                                    long lTemp = Blowfish.byteArrayToLong(buffer, nI);
467                                    lTemp = decryptBlock(lTemp);
468                                    Blowfish.longToByteArray(lTemp, buffer, nI);
469                            }
470    
471                    }
472    
473                    public void decrypt(int inbuffer[], int outbuffer[]) {
474                            int nLen = inbuffer.length;
475                            for(int nI = 0; nI < nLen; nI += 2) {
476                                    long lTemp = Blowfish.intArrayToLong(inbuffer, nI);
477                                    lTemp = decryptBlock(lTemp);
478                                    Blowfish.longToIntArray(lTemp, outbuffer, nI);
479                            }
480    
481                    }
482    
483                    public void decrypt(int buffer[]) {
484                            int nLen = buffer.length;
485                            for(int nI = 0; nI < nLen; nI += 2) {
486                                    long lTemp = Blowfish.intArrayToLong(buffer, nI);
487                                    lTemp = decryptBlock(lTemp);
488                                    Blowfish.longToIntArray(lTemp, buffer, nI);
489                            }
490    
491                    }
492    
493                    public void decrypt(long inbuffer[], long outbuffer[]) {
494                            int nLen = inbuffer.length;
495                            for(int nI = 0; nI < nLen; nI++)
496                                    outbuffer[nI] = decryptBlock(inbuffer[nI]);
497    
498                    }
499    
500                    public void decrypt(long buffer[]) {
501                            int nLen = buffer.length;
502                            for(int nI = 0; nI < nLen; nI++)
503                                    buffer[nI] = decryptBlock(buffer[nI]);
504    
505                    }
506    
507    
508                    public BlowfishECB(byte bfkey[]) {
509                            m_pbox = new int[18];
510                            for(int nI = 0; nI < 18; nI++)
511                                    m_pbox[nI] = pbox_init[nI];
512    
513                            m_sbox1 = new int[256];
514                            m_sbox2 = new int[256];
515                            m_sbox3 = new int[256];
516                            m_sbox4 = new int[256];
517                            for(int nI = 0; nI < 256; nI++) {
518                                    m_sbox1[nI] = sbox_init_1[nI];
519                                    m_sbox2[nI] = sbox_init_2[nI];
520                                    m_sbox3[nI] = sbox_init_3[nI];
521                                    m_sbox4[nI] = sbox_init_4[nI];
522                            }
523    
524                            int nLen = bfkey.length;
525                            if(nLen == 0)
526                                    return;
527                            int nKeyPos = 0;
528                            int nBuild = 0;
529                            for(int nI = 0; nI < 18; nI++) {
530                                    for(int nJ = 0; nJ < 4; nJ++) {
531                                            nBuild = nBuild << 8 | bfkey[nKeyPos] & 0xff;
532                                            if(++nKeyPos == nLen)
533                                                    nKeyPos = 0;
534                                    }
535    
536                                    m_pbox[nI] ^= nBuild;
537                            }
538    
539                            long lZero = 0L;
540                            for(int nI = 0; nI < 18; nI += 2) {
541                                    lZero = encryptBlock(lZero);
542                                    m_pbox[nI] = (int)(lZero >>> 32);
543                                    m_pbox[nI + 1] = (int)(lZero & 0xffffffffL);
544                            }
545    
546                            for(int nI = 0; nI < 256; nI += 2) {
547                                    lZero = encryptBlock(lZero);
548                                    m_sbox1[nI] = (int)(lZero >>> 32);
549                                    m_sbox1[nI + 1] = (int)(lZero & 0xffffffffL);
550                            }
551    
552                            for(int nI = 0; nI < 256; nI += 2) {
553                                    lZero = encryptBlock(lZero);
554                                    m_sbox2[nI] = (int)(lZero >>> 32);
555                                    m_sbox2[nI + 1] = (int)(lZero & 0xffffffffL);
556                            }
557    
558                            for(int nI = 0; nI < 256; nI += 2) {
559                                    lZero = encryptBlock(lZero);
560                                    m_sbox3[nI] = (int)(lZero >>> 32);
561                                    m_sbox3[nI + 1] = (int)(lZero & 0xffffffffL);
562                            }
563    
564                            for(int nI = 0; nI < 256; nI += 2) {
565                                    lZero = encryptBlock(lZero);
566                                    m_sbox4[nI] = (int)(lZero >>> 32);
567                                    m_sbox4[nI + 1] = (int)(lZero & 0xffffffffL);
568                            }
569    
570                    }
571            }
572    
573    
574            private BlowfishCBC m_bfish;
575            private static Random m_rndGen = new Random();
576            static final char HEXTAB[] = {
577                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
578                    'a', 'b', 'c', 'd', 'e', 'f'
579            };
580    
581            public Blowfish(String password) {
582                    MessageDigest digest = null;
583                    try {
584                            digest = MessageDigest.getInstance("SHA1");
585                            digest.update(password.getBytes());
586                    }
587                    catch(Exception e) {
588                            ExceptionHandler.printStackTrace(e);
589                    }
590                    m_bfish = new BlowfishCBC(digest.digest(), 0L);
591                    digest.reset();
592            }
593    
594            public String encryptString(String sPlainText) {
595                    long lCBCIV;
596                    synchronized(m_rndGen) {
597                            lCBCIV = m_rndGen.nextLong();
598                    }
599                    return encStr(sPlainText, lCBCIV);
600            }
601    
602            private String encStr(String sPlainText, long lNewCBCIV) {
603                    int nStrLen = sPlainText.length();
604                    byte buf[] = new byte[(nStrLen << 1 & -8) + 8];
605                    int nPos = 0;
606                    for(int nI = 0; nI < nStrLen; nI++) {
607                            char cActChar = sPlainText.charAt(nI);
608                            buf[nPos++] = (byte)(cActChar >> 8 & 0xff);
609                            buf[nPos++] = (byte)(cActChar & 0xff);
610                    }
611    
612                    byte bPadVal = (byte)(buf.length - (nStrLen << 1));
613                    while(nPos < buf.length) 
614                            buf[nPos++] = bPadVal;
615                    m_bfish.setCBCIV(lNewCBCIV);
616                    m_bfish.encrypt(buf);
617                    byte newCBCIV[] = new byte[8];
618                    longToByteArray(lNewCBCIV, newCBCIV, 0);
619                    return bytesToBinHex(newCBCIV, 0, 8) + bytesToBinHex(buf, 0, buf.length);
620            }
621    
622            public String decryptString(String sCipherText) {
623                    int nLen = sCipherText.length() >> 1 & -8;
624                    if(nLen < 8)
625                            return null;
626                    byte cbciv[] = new byte[8];
627                    int nNumOfBytes = binHexToBytes(sCipherText, cbciv, 0, 0, 8);
628                    if(nNumOfBytes < 8)
629                            return null;
630                    m_bfish.setCBCIV(cbciv);
631                    if((nLen -= 8) == 0)
632                            return "";
633                    byte buf[] = new byte[nLen];
634                    nNumOfBytes = binHexToBytes(sCipherText, buf, 16, 0, nLen);
635                    if(nNumOfBytes < nLen)
636                            return null;
637                    m_bfish.decrypt(buf);
638                    int nPadByte = buf[buf.length - 1] & 0xff;
639                    if(nPadByte > 8 || nPadByte < 0)
640                            nPadByte = 0;
641                    nNumOfBytes -= nPadByte;
642                    if(nNumOfBytes < 0)
643                            return "";
644                    return byteArrayToUNCString(buf, 0, nNumOfBytes);
645            }
646    
647            public void destroy() {
648                    m_bfish.cleanUp();
649            }
650    
651            private static long byteArrayToLong(byte buffer[], int nStartIndex) {
652                    return (long)buffer[nStartIndex] << 56 | (buffer[nStartIndex + 1] & 255L) << 48 | (buffer[nStartIndex + 2] & 255L) << 40 | (buffer[nStartIndex + 3] & 255L) << 32 | (buffer[nStartIndex + 4] & 255L) << 24 | (buffer[nStartIndex + 5] & 255L) << 16 | (buffer[nStartIndex + 6] & 255L) << 8 | buffer[nStartIndex + 7] & 255L;
653            }
654    
655            private static void longToByteArray(long lValue, byte buffer[], int nStartIndex) {
656                    buffer[nStartIndex] = (byte)(int)(lValue >>> 56);
657                    buffer[nStartIndex + 1] = (byte)(int)(lValue >>> 48 & 255L);
658                    buffer[nStartIndex + 2] = (byte)(int)(lValue >>> 40 & 255L);
659                    buffer[nStartIndex + 3] = (byte)(int)(lValue >>> 32 & 255L);
660                    buffer[nStartIndex + 4] = (byte)(int)(lValue >>> 24 & 255L);
661                    buffer[nStartIndex + 5] = (byte)(int)(lValue >>> 16 & 255L);
662                    buffer[nStartIndex + 6] = (byte)(int)(lValue >>> 8 & 255L);
663                    buffer[nStartIndex + 7] = (byte)(int)lValue;
664            }
665    
666            private static long intArrayToLong(int buffer[], int nStartIndex) {
667                    return (long)buffer[nStartIndex] << 32 | buffer[nStartIndex + 1] & 0xffffffffL;
668            }
669    
670            private static void longToIntArray(long lValue, int buffer[], int nStartIndex) {
671                    buffer[nStartIndex] = (int)(lValue >>> 32);
672                    buffer[nStartIndex + 1] = (int)lValue;
673            }
674    
675            private static long makeLong(int nLo, int nHi) {
676                    return (long)nHi << 32 | nLo & 0xffffffffL;
677            }
678    
679            private static int longLo32(long lVal) {
680                    return (int)lVal;
681            }
682    
683            private static int longHi32(long lVal) {
684                    return (int)(lVal >>> 32);
685            }
686    
687            private static String bytesToBinHex(byte data[], int nStartPos, int nNumOfBytes) {
688                    StringBuffer sbuf = new StringBuffer();
689                    sbuf.setLength(nNumOfBytes << 1);
690                    int nPos = 0;
691                    for(int nI = 0; nI < nNumOfBytes; nI++) {
692                            sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] >> 4 & 0xf]);
693                            sbuf.setCharAt(nPos++, HEXTAB[data[nI + nStartPos] & 0xf]);
694                    }
695    
696                    return sbuf.toString();
697            }
698    
699            private static int binHexToBytes(String sBinHex, byte data[], int nSrcPos, int nDstPos, int nNumOfBytes) {
700                    int nStrLen = sBinHex.length();
701                    int nAvailBytes = nStrLen - nSrcPos >> 1;
702                    if(nAvailBytes < nNumOfBytes)
703                            nNumOfBytes = nAvailBytes;
704                    int nOutputCapacity = data.length - nDstPos;
705                    if(nNumOfBytes > nOutputCapacity)
706                            nNumOfBytes = nOutputCapacity;
707                    int nResult = 0;
708                    for(int nI = 0; nI < nNumOfBytes; nI++) {
709                            byte bActByte = 0;
710                            boolean blConvertOK = true;
711                            for(int nJ = 0; nJ < 2; nJ++) {
712                                    bActByte <<= 4;
713                                    char cActChar = sBinHex.charAt(nSrcPos++);
714                                    if(cActChar >= 'a' && cActChar <= 'f') {
715                                            bActByte |= (byte)(cActChar - 97) + 10;
716                                            continue;
717                                    }
718                                    if(cActChar >= '0' && cActChar <= '9')
719                                            bActByte |= (byte)(cActChar - 48);
720                                    else
721                                            blConvertOK = false;
722                            }
723    
724                            if(blConvertOK) {
725                                    data[nDstPos++] = bActByte;
726                                    nResult++;
727                            }
728                    }
729    
730                    return nResult;
731            }
732    
733            private static String byteArrayToUNCString(byte data[], int nStartPos, int nNumOfBytes) {
734                    nNumOfBytes &= -2;
735                    int nAvailCapacity = data.length - nStartPos;
736                    if(nAvailCapacity < nNumOfBytes)
737                            nNumOfBytes = nAvailCapacity;
738                    StringBuffer sbuf = new StringBuffer();
739                    sbuf.setLength(nNumOfBytes >> 1);
740                    int nSBufPos = 0;
741                    for(; nNumOfBytes > 0; nNumOfBytes -= 2) {
742                            sbuf.setCharAt(nSBufPos++, (char)(data[nStartPos] << 8 | data[nStartPos + 1] & 0xff));
743                            nStartPos += 2;
744                    }
745    
746                    return sbuf.toString();
747            }
748    }