001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.quercus.lib.mcrypt;
031:
032: import com.caucho.quercus.annotation.Optional;
033: import com.caucho.quercus.annotation.ReturnNullAsFalse;
034: import com.caucho.quercus.env.ArrayValue;
035: import com.caucho.quercus.env.ArrayValueImpl;
036: import com.caucho.quercus.env.StringValue;
037: import com.caucho.quercus.env.BooleanValue;
038: import com.caucho.quercus.env.Env;
039: import com.caucho.quercus.env.LongValue;
040: import com.caucho.quercus.env.Value;
041: import com.caucho.quercus.module.AbstractQuercusModule;
042: import com.caucho.util.L10N;
043: import com.caucho.util.RandomUtil;
044: import com.caucho.vfs.Path;
045:
046: import java.util.logging.Level;
047: import java.util.logging.Logger;
048:
049: /**
050: * PHP encryption
051: */
052: public class McryptModule extends AbstractQuercusModule {
053: private static final L10N L = new L10N(McryptModule.class);
054:
055: private static final Logger log = Logger
056: .getLogger(McryptModule.class.getName());
057:
058: public static final int MCRYPT_DEV_RANDOM = 0;
059: public static final int MCRYPT_DEV_URANDOM = 1;
060: public static final int MCRYPT_RAND = 2;
061:
062: public static final int MCRYPT_ENCRYPT = 0;
063: public static final int MCRYPT_DECRYPT = 1;
064:
065: public static final String MCRYPT_MODE_ECB = "ecb";
066: public static final String MCRYPT_MODE_CBC = "cbc";
067: public static final String MCRYPT_MODE_CFB = "cfb";
068: public static final String MCRYPT_MODE_OFB = "ofb";
069: public static final String MCRYPT_MODE_NOFB = "nofb";
070: public static final String MCRYPT_MODE_STREAM = "stream";
071:
072: public static final String MCRYPT_ARCFOUR = "arcfour";
073: public static final String MCRYPT_BLOWFISH = "blowfish";
074: public static final String MCRYPT_DES = "des";
075: public static final String MCRYPT_3DES = "tripledes";
076: public static final String MCRYPT_TRIPLEDES = "tripledes";
077: public static final String MCRYPT_RC4 = "RC4";
078: public static final String MCRYPT_RIJNDAEL_128 = "rijndael-128";
079: public static final String MCRYPT_RIJNDAEL_192 = "rijndael-192";
080: public static final String MCRYPT_RIJNDAEL_256 = "rijndael-256";
081:
082: public String[] getLoadedExtensions() {
083: return new String[] { "mcrypt" };
084: }
085:
086: /**
087: * Encrypt with cbc
088: */
089: public static StringValue mcrypt_cbc(Env env, String cipher,
090: byte[] key, byte[] data, int mode, @Optional
091: byte[] iv) {
092: try {
093: Mcrypt mcrypt = new Mcrypt(env, cipher, "cbc");
094:
095: mcrypt.init(key, iv);
096:
097: byte[] result;
098:
099: if (mode == MCRYPT_ENCRYPT)
100: result = mcrypt.encrypt(data);
101: else
102: result = mcrypt.decrypt(data);
103:
104: return env.createBinaryBuilder(result, 0, result.length);
105: } catch (Exception e) {
106: throw new RuntimeException(e);
107: }
108: }
109:
110: /**
111: * Encrypt with cfb
112: */
113: public static StringValue mcrypt_cfb(Env env, String cipher,
114: byte[] key, byte[] data, int mode, @Optional
115: byte[] iv) {
116: try {
117: Mcrypt mcrypt = new Mcrypt(env, cipher, "cfb");
118:
119: mcrypt.init(key, iv);
120:
121: byte[] result;
122:
123: if (mode == MCRYPT_ENCRYPT)
124: result = mcrypt.encrypt(data);
125: else
126: result = mcrypt.decrypt(data);
127:
128: return env.createBinaryBuilder(result, 0, result.length);
129: } catch (Exception e) {
130: throw new RuntimeException(e);
131: }
132: }
133:
134: /**
135: * Creates the IV vector.
136: */
137: public static StringValue mcrypt_create_iv(Env env, int size,
138: @Optional
139: int randomMode) {
140: StringValue bb = env.createBinaryBuilder(size);
141:
142: for (int i = 0; i < size; i++)
143: bb.appendByte((byte) RandomUtil.nextInt(256));
144:
145: return bb;
146: }
147:
148: /**
149: * Decrypt
150: */
151: public static StringValue mcrypt_decrypt(Env env, String cipher,
152: byte[] key, byte[] data, String mode, @Optional
153: byte[] iv) {
154: try {
155: Mcrypt mcrypt = new Mcrypt(env, cipher, mode);
156:
157: mcrypt.init(key, iv);
158:
159: byte[] result = mcrypt.decrypt(data);
160:
161: return env.createBinaryBuilder(result, 0, result.length);
162: } catch (Exception e) {
163: throw new RuntimeException(e);
164: }
165: }
166:
167: /**
168: * Encrypt with cfb
169: */
170: public static StringValue mcrypt_ecb(Env env, String cipher,
171: byte[] key, byte[] data, int mode, @Optional
172: byte[] iv) {
173: try {
174: Mcrypt mcrypt = new Mcrypt(env, cipher, "ecb");
175:
176: mcrypt.init(key, iv);
177:
178: byte[] result;
179:
180: if (mode == MCRYPT_ENCRYPT)
181: result = mcrypt.encrypt(data);
182: else
183: result = mcrypt.decrypt(data);
184:
185: return env.createBinaryBuilder(result, 0, result.length);
186: } catch (Exception e) {
187: throw new RuntimeException(e);
188: }
189: }
190:
191: /**
192: * Returns the algorithms name
193: */
194: public static String mcrypt_enc_get_algorithms_name(Mcrypt mcrypt) {
195: if (mcrypt != null)
196: return mcrypt.get_algorithms_name();
197: else
198: return "";
199: }
200:
201: /**
202: * Returns the block size
203: */
204: public static int mcrypt_enc_get_block_size(Mcrypt mcrypt) {
205: if (mcrypt != null)
206: return mcrypt.get_iv_size();
207: else
208: return 0;
209: }
210:
211: /**
212: * Returns the IV size
213: */
214: public static int mcrypt_enc_get_iv_size(Mcrypt mcrypt) {
215: if (mcrypt != null)
216: return mcrypt.get_iv_size();
217: else
218: return 0;
219: }
220:
221: /**
222: * Returns the key size
223: */
224: public static int mcrypt_enc_get_key_size(Mcrypt mcrypt) {
225: if (mcrypt != null)
226: return mcrypt.get_key_size();
227: else
228: return 0;
229: }
230:
231: /**
232: * Returns the mode name
233: */
234: public static String mcrypt_enc_get_modes_name(Mcrypt mcrypt) {
235: if (mcrypt != null)
236: return mcrypt.get_modes_name();
237: else
238: return null;
239: }
240:
241: /**
242: * Returns the supported key sizes
243: */
244: public static Value mcrypt_enc_get_supported_key_sizes(Mcrypt mcrypt) {
245: if (mcrypt != null)
246: return mcrypt.get_supported_key_sizes();
247: else
248: return BooleanValue.FALSE;
249: }
250:
251: /**
252: * Returns true for block encoding modes
253: */
254: public static boolean mcrypt_enc_is_block_algorithm(Mcrypt mcrypt) {
255: if (mcrypt != null)
256: return mcrypt.is_block_algorithm();
257: else
258: return false;
259: }
260:
261: /**
262: * Returns true for block encoding modes
263: */
264: public static boolean mcrypt_enc_is_block_algorithm_mode(
265: Mcrypt mcrypt) {
266: if (mcrypt != null)
267: return mcrypt.is_block_algorithm_mode();
268: else
269: return false;
270: }
271:
272: /**
273: * Returns true for block output modes
274: */
275: public static boolean mcrypt_enc_is_block_mode(Mcrypt mcrypt) {
276: if (mcrypt != null)
277: return mcrypt.is_block_mode();
278: else
279: return false;
280: }
281:
282: /**
283: * Returns true for block output modes
284: */
285: public static boolean mcrypt_enc_self_test(Mcrypt mcrypt) {
286: if (mcrypt != null)
287: return true;
288: else
289: return false;
290: }
291:
292: /**
293: * Encrypt
294: */
295: public static StringValue mcrypt_encrypt(Env env, String cipher,
296: byte[] key, byte[] data, String mode, @Optional
297: byte[] iv) {
298: try {
299: Mcrypt mcrypt = new Mcrypt(env, cipher, mode);
300:
301: mcrypt.init(key, iv);
302:
303: return env.createBinaryBuilder(mcrypt.encrypt(data));
304: } catch (Exception e) {
305: throw new RuntimeException(e);
306: }
307: }
308:
309: /**
310: * Initialize encrption
311: */
312: public static StringValue mcrypt_generic(Env env, Mcrypt mcrypt,
313: byte[] data) {
314: if (mcrypt == null)
315: return null;
316: else
317: return env.createBinaryBuilder(mcrypt.encrypt(data));
318: }
319:
320: /**
321: * Initialize encrption
322: */
323: public static boolean mcrypt_generic_deinit(Mcrypt mcrypt) {
324: if (mcrypt == null)
325: return false;
326: else
327: return mcrypt.deinit();
328: }
329:
330: /**
331: * Initialize encrption
332: */
333: public static Value mcrypt_generic_init(Mcrypt mcrypt, byte[] key,
334: byte[] iv) {
335: if (mcrypt == null)
336: return BooleanValue.FALSE;
337: else
338: return new LongValue(mcrypt.init(key, iv));
339: }
340:
341: /**
342: * Closes the module
343: */
344: public static boolean mcrypt_generic_end(Mcrypt mcrypt) {
345: if (mcrypt == null)
346: return false;
347: else {
348: mcrypt.close();
349:
350: return true;
351: }
352: }
353:
354: /*
355: * Returns the IV size.
356: */
357: public static Value mcrypt_get_block_size(Env env, String cipher,
358: String mode) {
359: try {
360: Mcrypt mcrypt = new Mcrypt(env, cipher, mode);
361:
362: return LongValue.create(mcrypt.get_block_size());
363: } catch (Exception e) {
364: log.log(Level.FINE, e.getMessage(), e);
365:
366: return BooleanValue.FALSE;
367: }
368: }
369:
370: /*
371: * Returns the cipher name.
372: */
373: @ReturnNullAsFalse
374: public static String mcrypt_get_cipher_name(Env env, String cipher) {
375: try {
376: Mcrypt mcrypt = new Mcrypt(env, cipher, "cbc");
377:
378: return mcrypt.get_algorithms_name();
379: } catch (Exception e) {
380: log.log(Level.FINE, e.getMessage(), e);
381:
382: return null;
383: }
384: }
385:
386: /*
387: * Returns the IV size.
388: */
389: public static Value mcrypt_get_iv_size(Env env, String cipher,
390: String mode) {
391: try {
392: Mcrypt mcrypt = new Mcrypt(env, cipher, mode);
393:
394: return LongValue.create(mcrypt.get_iv_size());
395: } catch (Exception e) {
396: log.log(Level.FINE, e.getMessage(), e);
397:
398: return BooleanValue.FALSE;
399: }
400: }
401:
402: /*
403: * Returns the key size.
404: */
405: public static Value mcrypt_get_key_size(Env env, String cipher,
406: String mode) {
407: try {
408: Mcrypt mcrypt = new Mcrypt(env, cipher, mode);
409:
410: return LongValue.create(mcrypt.get_key_size());
411: } catch (Exception e) {
412: log.log(Level.FINE, e.getMessage(), e);
413:
414: return BooleanValue.FALSE;
415: }
416: }
417:
418: private static final String[] ALGORITHMS = { MCRYPT_ARCFOUR,
419: MCRYPT_BLOWFISH, MCRYPT_DES, MCRYPT_3DES, MCRYPT_RC4,
420: MCRYPT_RIJNDAEL_128, MCRYPT_RIJNDAEL_192,
421: MCRYPT_RIJNDAEL_256 };
422:
423: /**
424: * Lists the available algorithms
425: */
426: public static Value mcrypt_list_algorithms(Env env) {
427: ArrayValue array = new ArrayValueImpl();
428:
429: for (int i = 0; i < ALGORITHMS.length; i++) {
430: try {
431: Mcrypt mcrypt = new Mcrypt(env, ALGORITHMS[i], "cbc");
432:
433: array.put(mcrypt.get_algorithms_name());
434: } catch (Throwable e) {
435: }
436: }
437:
438: return array;
439: }
440:
441: /**
442: * Lists the available modes.
443: */
444: public static Value mcrypt_list_modes(Env env) {
445: ArrayValue array = new ArrayValueImpl();
446:
447: array.put(MCRYPT_MODE_ECB);
448: array.put(MCRYPT_MODE_CBC);
449: array.put(MCRYPT_MODE_CFB);
450: array.put(MCRYPT_MODE_OFB);
451: array.put(MCRYPT_MODE_NOFB);
452:
453: return array;
454: }
455:
456: /**
457: * Closes the module
458: */
459: public static boolean mcrypt_module_close(Mcrypt mcrypt) {
460: if (mcrypt == null)
461: return false;
462: else {
463: mcrypt.close();
464:
465: return true;
466: }
467: }
468:
469: /**
470: * Returns the block size for an algorithm.
471: */
472: public static int mcrypt_module_get_algo_block_size(Env env,
473: String cipher, @Optional
474: String libDir) {
475: try {
476: Mcrypt mcrypt = new Mcrypt(env, cipher, "cbc");
477:
478: return mcrypt.get_block_size();
479: } catch (Exception e) {
480: env.error(e);
481:
482: return -1;
483: }
484: }
485:
486: /**
487: * Returns the key size for an algorithm.
488: */
489: public static int mcrypt_module_get_algo_key_size(Env env,
490: String cipher, @Optional
491: String libDir) {
492: try {
493: Mcrypt mcrypt = new Mcrypt(env, cipher, "cbc");
494:
495: return mcrypt.get_key_size();
496: } catch (Exception e) {
497: env.error(e);
498:
499: return -1;
500: }
501: }
502:
503: /**
504: * Returns the key size for an algorithm.
505: */
506: public static Value mcrypt_module_get_supported_key_sizes(Env env,
507: String cipher, @Optional
508: String libDir) {
509: try {
510: Mcrypt mcrypt = new Mcrypt(env, cipher, "cbc");
511:
512: return mcrypt.get_supported_key_sizes();
513: } catch (Exception e) {
514: env.error(e);
515:
516: return BooleanValue.FALSE;
517: }
518: }
519:
520: /**
521: * Returns true for block algorithms
522: */
523: public static boolean mcrypt_module_is_block_algorithm(Env env,
524: String cipher, @Optional
525: String libDir) {
526: try {
527: Mcrypt mcrypt = new Mcrypt(env, cipher, "cbc");
528:
529: return mcrypt.is_block_algorithm();
530: } catch (Exception e) {
531: env.error(e);
532:
533: return false;
534: }
535: }
536:
537: /**
538: * Returns true for block modes
539: */
540: public static boolean mcrypt_module_is_block_algorithm_mode(
541: Env env, String mode, @Optional
542: String libDir) {
543: try {
544: Mcrypt mcrypt = new Mcrypt(env, "des", mode);
545:
546: return mcrypt.is_block_algorithm_mode();
547: } catch (Exception e) {
548: env.error(e);
549:
550: return false;
551: }
552: }
553:
554: /**
555: * Returns true for block modes
556: */
557: public static boolean mcrypt_module_is_block_mode(Env env,
558: String mode, @Optional
559: String libDir) {
560: try {
561: Mcrypt mcrypt = new Mcrypt(env, "des", mode);
562:
563: return mcrypt.is_block_mode();
564: } catch (Exception e) {
565: env.error(e);
566:
567: return false;
568: }
569: }
570:
571: /**
572: * Returns true for block modes
573: */
574: public static boolean mcrypt_module_self_test(Env env,
575: String algorithm, Path libDir) {
576: try {
577: Mcrypt mcrypt = new Mcrypt(env, algorithm, "cbc");
578:
579: return true;
580: } catch (Exception e) {
581: env.error(e);
582:
583: return false;
584: }
585: }
586:
587: /**
588: * Open a new mcrypt object.
589: */
590: public static Value mcrypt_module_open(Env env, String algorithm,
591: Path algorithm_directory, String mode, Path mode_directory) {
592: try {
593: return env.wrapJava(new Mcrypt(env, algorithm, mode));
594: } catch (Exception e) {
595: env.error(e);
596:
597: return BooleanValue.FALSE;
598: }
599: }
600:
601: /**
602: * Encrypt with ofb
603: */
604: public static StringValue mcrypt_ofb(Env env, String cipher,
605: byte[] key, byte[] data, int mode, @Optional
606: byte[] iv) {
607: try {
608: Mcrypt mcrypt = new Mcrypt(env, cipher, "ofb");
609:
610: mcrypt.init(key, iv);
611:
612: byte[] result;
613:
614: if (mode == MCRYPT_ENCRYPT)
615: result = mcrypt.encrypt(data);
616: else
617: result = mcrypt.decrypt(data);
618:
619: return env.createBinaryBuilder(result);
620: } catch (Exception e) {
621: throw new RuntimeException(e);
622: }
623: }
624:
625: /**
626: * Initialize encrption
627: */
628: public static Value mdecrypt_generic(Env env, Mcrypt mcrypt,
629: byte[] data) {
630: if (mcrypt == null)
631: return BooleanValue.FALSE;
632: else
633: return env.createBinaryBuilder(mcrypt.decrypt(data));
634: }
635: }
|