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