001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010:
011: package org.mmbase.util.transformers;
012:
013: import java.io.Reader;
014: import java.io.Writer;
015: import java.security.GeneralSecurityException;
016:
017: import javax.crypto.Cipher;
018: import javax.crypto.spec.SecretKeySpec;
019:
020: import org.mmbase.util.functions.Parameter;
021: import org.mmbase.util.functions.Parameters;
022: import org.mmbase.util.logging.Logger;
023: import org.mmbase.util.logging.Logging;
024:
025: /**
026: * This transformerfactory can encrypt and decrypt strings. The algorithm which is
027: * used for encryption/decryption is parameterized, and defaults to AES. Since
028: * these encryption algorithms return raw bytes, an encoding must be supplied
029: * which is used to convert bytes to characters: either hexadecimal encoding
030: * or base64.
031: * @author Sander de Boer
032: */
033:
034: public class EncryptionTransformerFactory implements
035: ParameterizedTransformerFactory<CharTransformer> {
036: private static final Logger log = Logging
037: .getLoggerInstance(EncryptionTransformerFactory.class);
038:
039: /**
040: * Encode a given array of bytes to a string, using the given format.
041: * This can be 'hex' or 'base64'.
042: */
043: public static String encode(byte input[], String format) {
044: if ("hex".equalsIgnoreCase(format)) {
045: Hex h = new Hex();
046: String output = h.transform(input);
047: return output;
048: } else if ("base64".equalsIgnoreCase(format)) {
049: Base64 b = new Base64();
050: String output = b.transform(input);
051: return output;
052: }
053: return "";
054: }
055:
056: /**
057: * Decode a given string to an array of bytes, using a given format.
058: * This can throw an 'IllegalArgumentException' when the given input
059: * string isn't correct according to the format.
060: */
061: public static byte[] decode(String input, String format)
062: throws IllegalArgumentException {
063: if ("hex".equalsIgnoreCase(format)) {
064: Hex h = new Hex();
065: byte[] output = h.transformBack(input);
066: return output;
067: } else if ("base64".equalsIgnoreCase(format)) {
068: Base64 b = new Base64();
069: byte[] output = b.transformBack(input);
070: return output;
071: }
072: return new byte[0];
073: }
074:
075: protected final static Parameter[] PARAMS = {
076: new Parameter<String>("key", String.class,
077: "1234567890abcdef"),
078: new Parameter<String>("format", String.class, "hex"),
079: new Parameter<String>("algorithm", String.class, "AES"),
080: new Parameter<String>("direction", String.class, "encrypt") };
081:
082: public Parameters createParameters() {
083: return new Parameters(PARAMS);
084: }
085:
086: /**
087: * Return a parameterized transformer, based on the given parameters. These can be the following:
088: * <ul>
089: * <li>algorithm, defaults to 'AES'</li>
090: * <li>direction, can be 'encrypt' or 'decrypt'</li>
091: * <li>format, can be 'base64' or 'hex'</li>
092: * <li>key, defaults to '1234567890abcdef' (NOTE: the length of this key must match the requirements set by the algorithm</li>
093: * </ul>
094: */
095: public CharTransformer createTransformer(Parameters parameters) {
096: String direction = (String) parameters.get("direction");
097: if ("encrypt".equalsIgnoreCase(direction)) {
098: return new Encryption((String) parameters.get("key"),
099: (String) parameters.get("format"),
100: (String) parameters.get("algorithm"));
101: } else if ("decrypt".equalsIgnoreCase(direction)) {
102: return new Decryption((String) parameters.get("key"),
103: (String) parameters.get("format"),
104: (String) parameters.get("algorithm"));
105: } else {
106: throw new UnsupportedOperationException(
107: "Unknown value for attribute 'direction', (known are 'encrypt' and 'decrypt')");
108: }
109: }
110:
111: class Encryption extends ReaderTransformer {
112: private String key;
113: private String format;
114: private String algorithm;
115:
116: Encryption(String key, String format, String algorithm) {
117: this .key = key;
118: this .format = format;
119: this .algorithm = algorithm;
120:
121: if ((!"base64".equalsIgnoreCase(format))
122: & (!"hex".equalsIgnoreCase(format))) {
123: throw new UnsupportedOperationException(
124: "Unknown value for attribute 'format', (known are 'base64' and 'hex')");
125: }
126: }
127:
128: public Writer transform(Reader r, Writer w) {
129: StringBuilder sb = new StringBuilder();
130:
131: try {
132: int i;
133: while ((i = r.read()) > -1) {
134: sb.append((char) i);
135: }
136: byte input[] = sb.toString().getBytes();
137:
138: byte[] secretKey = key.getBytes();
139: SecretKeySpec skeySpec = new SecretKeySpec(secretKey,
140: algorithm);
141:
142: Cipher cipher = Cipher.getInstance(algorithm);
143: cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
144: byte encrypted[] = cipher.doFinal(input);
145:
146: String output = encode(encrypted, format);
147:
148: w.write(output);
149: return w;
150:
151: } catch (IllegalArgumentException h) {
152: throw new UnsupportedOperationException(h.getMessage());
153: } catch (SecurityException g) {
154: throw new UnsupportedOperationException(g.getMessage());
155: } catch (GeneralSecurityException f) {
156: throw new UnsupportedOperationException(f.getMessage());
157: } catch (Exception e) {
158: log.error(e.getMessage() + Logging.stackTrace(e));
159: }
160: return w;
161: }
162: }
163:
164: class Decryption extends ReaderTransformer {
165: private String key;
166: private String format;
167: private String algorithm;
168:
169: Decryption(String key, String format, String algorithm) {
170: this .key = key;
171: this .format = format;
172: this .algorithm = algorithm;
173:
174: if ((!"base64".equalsIgnoreCase(format))
175: & (!"hex".equalsIgnoreCase(format))) {
176: throw new UnsupportedOperationException(
177: "Unknown value for attribute 'format', (known are 'base64' and 'hex')");
178: }
179: }
180:
181: public Writer transform(Reader r, Writer w) {
182: StringBuilder sb = new StringBuilder();
183:
184: try {
185: int i;
186: while ((i = r.read()) > -1) {
187: sb.append((char) i);
188: }
189:
190: byte[] input = decode(sb.toString(), format);
191:
192: byte[] secretKey = key.getBytes();
193: SecretKeySpec skeySpec = new SecretKeySpec(secretKey,
194: algorithm);
195:
196: Cipher cipher = Cipher.getInstance(algorithm);
197: cipher.init(Cipher.DECRYPT_MODE, skeySpec);
198: byte decrypted[] = cipher.doFinal(input);
199: String output = new String(decrypted);
200: w.write(output);
201: return w;
202:
203: } catch (IllegalArgumentException h) {
204: throw new UnsupportedOperationException(h.getMessage());
205: } catch (SecurityException g) {
206: throw new UnsupportedOperationException(g.getMessage());
207: } catch (GeneralSecurityException f) {
208: throw new UnsupportedOperationException(f.getMessage());
209: } catch (Exception e) {
210: log.error(e.getMessage() + Logging.stackTrace(e));
211: }
212: return w;
213: }
214: }
215: }
|