001: package net.sf.drftpd.util;
002:
003: //Just a drfptd package
004:
005: /**
006: * Blowfish.java version 1.00.00
007: *
008: * Code Written by k2r (k2r.contact@gmail.com)
009: *
010: * Tks to Mouser for his precious help.
011: * Tks to Murx for correct Padding and Long key.
012: *
013: * Use this code is very simple :
014: *
015: * Use "Encrypt" with the text to encrypt
016: * -> The function will encrypt and return the text with +OK at the biginning"
017: *
018: * Use "Decrypt" with the text to decrypt
019: * --> The text must include the +OK or mcps at the front"
020: *
021: * There are a good exemple in "Main" function
022: *
023: * To Use Key > 16 char, you must update two jar files in your jre or jdk.
024: * Java Cryptography Extension (JCE)
025: * Unlimited Strength Jurisdiction Policy Files 1.4.2
026: * http://java.sun.com/j2se/1.4.2/download.html#docs
027: * Update the two files in jre\lib\security
028: * -> local_policy.jar
029: * -> US_export_policy.jar
030: *
031: */
032:
033: import java.io.UnsupportedEncodingException;
034: import java.security.InvalidKeyException;
035:
036: import javax.crypto.*;
037: import javax.crypto.spec.*;
038:
039: public class Blowfish {
040:
041: /* Constructor of Blowfish class
042: * Key param
043: * */
044:
045: public Blowfish(String key) {
046: skeySpec = new SecretKeySpec(key.getBytes(), "Blowfish");
047: // Preparing Blowfish mode
048: try {
049: ecipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
050: } catch (Exception e) {
051: e.printStackTrace();
052: }
053: }
054:
055: /* Encrypt function */
056: public String Encrypt(String tocrypt) {
057:
058: // Mode cypher in Encrypt mode
059: try {
060: ecipher.init(Cipher.ENCRYPT_MODE, skeySpec);
061: } catch (InvalidKeyException e) {
062: e.printStackTrace();
063: }
064:
065: String REncrypt = "";
066: // Paddind the String
067: byte[] BEncrypt = tocrypt.getBytes();
068: int Taille = BEncrypt.length;
069: int Limit = 8 - (BEncrypt.length % 8);
070: byte[] buff = new byte[Taille + Limit];
071:
072: for (int i = 0; i < Taille; i++)
073: buff[i] = BEncrypt[i];
074:
075: for (int i = Taille; i < Taille + Limit; i++)
076: buff[i] = 0x0;
077:
078: try {
079: // Encrypt the padding string
080: byte[] encrypted = ecipher.doFinal(buff);
081: // B64 ENCRYPTION (mircryption needed)
082: REncrypt = bytetoB64(encrypted);
083: } catch (Exception e) {
084: e.printStackTrace();
085: }
086:
087: REncrypt = Begin.concat(REncrypt);
088: return REncrypt;
089: }
090:
091: /* Decrypt function */
092: public String Decrypt(String encrypt)
093: throws UnsupportedEncodingException {
094:
095: if (encrypt.startsWith("+OK ")) {
096: encrypt = encrypt.substring(4, encrypt.length());
097: }
098: if (encrypt.startsWith("mcps ")) {
099: encrypt = encrypt.substring(5, encrypt.length());
100: }
101:
102: // B64 DECRYPTION (mircryption needed)
103: byte[] Again = B64tobyte(encrypt);
104:
105: byte[] decrypted = null;
106:
107: try {
108: // Mode cypher in Decrypt mode
109: ecipher.init(Cipher.DECRYPT_MODE, skeySpec);
110: decrypted = ecipher.doFinal(Again);
111:
112: // Recup exact length
113: int leng = 0;
114: while (decrypted[leng] != 0x0) {
115: leng++;
116: }
117: byte[] Final = new byte[leng];
118: // Format & Limit the Result String
119: int i = 0;
120: while (decrypted[i] != 0x0) {
121: Final[i] = decrypted[i];
122: i++;
123: }
124: //Force again the encoding result string
125: return new String(Final, "8859_1");
126: } catch (Exception e) {
127: //return e.getMessage();
128: // Exception, not necessary padding, return directly
129: // The decypted string
130: return new String(decrypted, "8859_1");
131: }
132: }
133:
134: public static byte[] B64tobyte(String ec) {
135:
136: String dc = "";
137:
138: int k = -1;
139: while (k < (ec.length() - 1)) {
140:
141: int right = 0;
142: int left = 0;
143: int v = 0;
144: int w = 0;
145: int z = 0;
146:
147: for (int i = 0; i < 6; i++) {
148: k++;
149: v = B64.indexOf(ec.charAt(k));
150: right |= v << (i * 6);
151: }
152:
153: for (int i = 0; i < 6; i++) {
154: k++;
155: v = B64.indexOf(ec.charAt(k));
156: left |= v << (i * 6);
157: }
158:
159: for (int i = 0; i < 4; i++) {
160: w = ((left & (0xFF << ((3 - i) * 8))));
161: z = w >> ((3 - i) * 8);
162: if (z < 0) {
163: z = z + 256;
164: }
165: dc += (char) z;
166: }
167:
168: for (int i = 0; i < 4; i++) {
169: w = ((right & (0xFF << ((3 - i) * 8))));
170: z = w >> ((3 - i) * 8);
171: if (z < 0) {
172: z = z + 256;
173: }
174: dc += (char) z;
175: }
176: }
177:
178: byte[] Result = new byte[1024];
179: try {
180: // Force the encoding result string
181: Result = dc.getBytes("8859_1");
182: } catch (UnsupportedEncodingException e) {
183: e.printStackTrace();
184: }
185: return Result;
186: }
187:
188: public static String bytetoB64(byte[] ec) {
189:
190: String dc = "";
191:
192: int left = 0;
193: int right = 0;
194: int k = -1;
195: int v;
196:
197: while (k < (ec.length - 1)) {
198: k++;
199: v = ec[k];
200: if (v < 0)
201: v += 256;
202: left = v << 24;
203: k++;
204: v = ec[k];
205: if (v < 0)
206: v += 256;
207: left += v << 16;
208: k++;
209: v = ec[k];
210: if (v < 0)
211: v += 256;
212: left += v << 8;
213: k++;
214: v = ec[k];
215: if (v < 0)
216: v += 256;
217: left += v;
218:
219: k++;
220: v = ec[k];
221: if (v < 0)
222: v += 256;
223: right = v << 24;
224: k++;
225: v = ec[k];
226: if (v < 0)
227: v += 256;
228: right += v << 16;
229: k++;
230: v = ec[k];
231: if (v < 0)
232: v += 256;
233: right += v << 8;
234: k++;
235: v = ec[k];
236: if (v < 0)
237: v += 256;
238: right += v;
239:
240: for (int i = 0; i < 6; i++) {
241: dc += B64.charAt(right & 0x3F);
242: right = right >> 6;
243: }
244:
245: for (int i = 0; i < 6; i++) {
246: dc += B64.charAt(left & 0x3F);
247: left = left >> 6;
248: }
249: }
250: return dc;
251: }
252:
253: private static String Begin = "+OK ";
254: private static String B64 = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
255: private Cipher ecipher;
256: private SecretKeySpec skeySpec;
257: }
|