KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ejbca > util > StringTools


1 /*************************************************************************
2  * *
3  * EJBCA: The OpenSource Certificate Authority *
4  * *
5  * This software is free software; you can redistribute it and/or *
6  * modify it under the terms of the GNU Lesser General Public *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or any later version. *
9  * *
10  * See terms of license at gnu.org. *
11  * *
12  *************************************************************************/

13  
14 package org.ejbca.util;
15
16 import java.io.UnsupportedEncodingException JavaDoc;
17 import java.security.InvalidAlgorithmParameterException JavaDoc;
18 import java.security.InvalidKeyException JavaDoc;
19 import java.security.NoSuchAlgorithmException JavaDoc;
20 import java.security.NoSuchProviderException JavaDoc;
21 import java.security.spec.InvalidKeySpecException JavaDoc;
22 import java.util.regex.Pattern JavaDoc;
23
24 import javax.crypto.BadPaddingException;
25 import javax.crypto.Cipher;
26 import javax.crypto.IllegalBlockSizeException;
27 import javax.crypto.NoSuchPaddingException;
28 import javax.crypto.SecretKeyFactory;
29 import javax.crypto.spec.IvParameterSpec;
30 import javax.crypto.spec.PBEKeySpec;
31 import javax.crypto.spec.SecretKeySpec;
32
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.log4j.Logger;
35 import org.bouncycastle.crypto.Digest;
36 import org.bouncycastle.crypto.PBEParametersGenerator;
37 import org.bouncycastle.crypto.digests.SHA256Digest;
38 import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
39 import org.bouncycastle.crypto.params.KeyParameter;
40 import org.bouncycastle.crypto.params.ParametersWithIV;
41 import org.bouncycastle.util.encoders.Hex;
42
43 /**
44  * This class implements some utility functions that are useful when handling Strings.
45  *
46  * @version $Id: StringTools.java,v 1.5.6.1 2007/03/08 09:57:22 anatom Exp $
47  */

48 public class StringTools {
49     private static Logger log = Logger.getLogger(StringTools.class);
50
51     // Characters that are not allowed in strings that may be stored in the db
52
private static final char[] stripChars = {
53         '\"', '\n', '\r', '\\', ';', '&', '!', '\0', '%', '`', '<', '>', '?',
54         '$', '~'
55     };
56     // Characters that are not allowed in strings that may be used in db queries
57
private static final char[] stripSqlChars = {
58         '\'', '\"', '\n', '\r', '\\', ';', '&', '|', '!', '\0', '%', '`', '<', '>', '?',
59         '$', '~'
60     };
61     // Characters that are allowed to escape in strings
62
private static final char[] allowedEscapeChars = {
63         ','
64     };
65     
66     private static final Pattern JavaDoc WS = Pattern.compile("\\s+");
67
68     /**
69      * Strips all special characters from a string by replacing them with a forward slash, '/'.
70      *
71      * @param str the string whose contents will be stripped.
72      *
73      * @return the stripped version of the input string.
74      */

75     public static String JavaDoc strip(String JavaDoc str) {
76         if (str == null) {
77             return null;
78         }
79         String JavaDoc ret = str;
80         for (int i = 0; i < stripChars.length; i++) {
81             if (ret.indexOf(stripChars[i]) > -1) {
82                 // If it is an escape char, we have to process manually
83
if (stripChars[i] == '\\') {
84                     // If it is an escaped char, allow it if it is an allowed escapechar
85
int index = ret.indexOf('\\');
86                     while (index > -1) {
87                         if (!isAllowed(ret.charAt(index+1))) {
88                             ret = StringUtils.overlay(ret,"/",index,index+1);
89                         }
90                         index = ret.indexOf('\\',index+1);
91                     }
92                 } else {
93                     ret = ret.replace(stripChars[i], '/');
94                 }
95             }
96         }
97         return ret;
98     } // strip
99
/**
100      * Checks if a string contains characters that would be stripped by 'strip'
101      *
102      * @param str the string whose contents would be stripped.
103      * @return true if some chars in the string would be stripped, false if not.
104      * @see #strip
105      */

106     public static boolean hasSqlStripChars(String JavaDoc str) {
107         if (str == null) {
108             return false;
109         }
110         String JavaDoc ret = str;
111         for (int i = 0; i < stripSqlChars.length; i++) {
112             if (ret.indexOf(stripSqlChars[i]) > -1) {
113                 // If it is an escape char, we have to process manually
114
if (stripSqlChars[i] == '\\') {
115                     // If it is an escaped char, allow it if it is an allowed escapechar
116
int index = ret.indexOf('\\');
117                     while (index > -1) {
118                         if (isAllowed(ret.charAt(index+1))) {
119                             return true;
120                         }
121                         index = ret.indexOf('\\',index+1);
122                     }
123                 } else {
124                     return true;
125                 }
126             }
127         }
128         return false;
129     } // hasSqlStripChars
130

131     /** Checks if a character is an allowed escape characted according to allowedEscapeChars
132      *
133      * @param ch the char to check
134      * @return true if char is an allowed escape character, false if now
135      */

136     private static boolean isAllowed(char ch) {
137         boolean allowed = false;
138         for (int j = 0; j < allowedEscapeChars.length; j++) {
139             if (ch == allowedEscapeChars[j]) {
140                 allowed = true;
141                 break;
142             }
143         }
144         return allowed;
145     }
146     
147     /**
148      * Strips all whitespace including space, tabs, newlines etc from the given string.
149      *
150      * @param str the string
151      * @return the string with all whitespace removed
152      * @since 2.1b1
153      */

154     public static String JavaDoc stripWhitespace(String JavaDoc str) {
155         if (str == null) {
156             return null;
157         }
158         return WS.matcher(str).replaceAll("");
159     }
160     
161     /** Converts an IP-address string to octets of binary ints.
162      * ip is of form a.b.c.d, i.e. at least four octets
163      * @param str string form of ip-address
164      * @return octets, null if input format is invalid
165      */

166     public static byte[] ipStringToOctets(String JavaDoc str) {
167         String JavaDoc[] toks = str.split("[.:]");
168         if (toks.length == 4) {
169             // IPv4 address
170
byte[] ret = new byte[4];
171             for (int i = 0;i<toks.length;i++) {
172                 int t = Integer.parseInt(toks[i]);
173                 if (t>255) {
174                     log.error("IPv4 address '"+str+"' contains octet > 255.");
175                     return null;
176                 }
177                 ret[i] = (byte)t;
178             }
179             return ret;
180         }
181         if (toks.length == 8) {
182             // IPv6 address
183
byte[] ret = new byte[16];
184             int ind = 0;
185             for (int i = 0;i<toks.length;i++) {
186                 int t = Integer.parseInt(toks[i]);
187                 if (t>0xFFFF) {
188                     log.error("IPv6 address '"+str+"' contains part > 0xFFFF.");
189                     return null;
190                 }
191                 int b1 = t & 0x00FF;
192                 ret[ind++] = (byte)b1;
193                 int b2 = t & 0xFF00;
194                 ret[ind++] = (byte)b2;
195             }
196         }
197         log.error("Not a IPv4 or IPv6 address.");
198         return null;
199     }
200     
201     /** Takes input and converts to Base64 on the format
202      * "B64:<base64 endoced string>", if the string is not null or empty.
203      *
204      * @param s String to base64 encode
205      * @return Base64 encoded string, or original string if it was null or empty
206      */

207     public static String JavaDoc putBase64String(String JavaDoc s) {
208         if (StringUtils.isEmpty(s)) {
209             return s;
210         }
211         if (s.startsWith("B64:")) {
212             // Only encode once
213
return s;
214         }
215         String JavaDoc n = null;
216         try {
217             // Since we used getBytes(s, "UTF-8") in this method, we must use UTF-8 when doing the reverse in another method
218
n="B64:"+new String JavaDoc(Base64.encode(s.getBytes("UTF-8"), false));
219         } catch (UnsupportedEncodingException JavaDoc e) {
220             // Do nothing
221
n=s;
222         }
223         return n;
224         
225     }
226
227     /** Takes input and converts from Base64 if the string begins with B64:, i.e. is on format
228      * "B64:<base64 endoced string>".
229      *
230      * @param s String to Base64 decode
231      * @return Base64 decoded string, or original string if it was not base 64 encoded
232      */

233     public static String JavaDoc getBase64String(String JavaDoc s) {
234         if (StringUtils.isEmpty(s)) {
235             return s;
236         }
237         String JavaDoc s1 = null;
238         if (s.startsWith("B64:")) {
239             s1 = s.substring(4);
240             String JavaDoc n = null;
241             try {
242                 // Since we used getBytes(s, "UTF-8") in the method putBase64String, we must use UTF-8 when doing the reverse
243
n = new String JavaDoc(Base64.decode(s1.getBytes("UTF-8")), "UTF-8");
244             } catch (UnsupportedEncodingException JavaDoc e) {
245                 n = s;
246             } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
247                 // We get this if we try to decode something that is not base 64
248
n = s;
249             }
250             return n;
251         }
252         return s;
253     }
254
255     /** Makes a string "hard" to read. Does not provide any real security, but at
256      * least lets you hide passwords so that people with no malicious content don't
257      * accidentaly stumble upon information they should not have.
258      *
259      * @param s string to obfuscate
260      * @return an obfuscated string
261      */

262     public static String JavaDoc obfuscate(String JavaDoc s)
263     {
264         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
265         byte[] b = s.getBytes();
266         
267         synchronized(buf)
268         {
269             buf.append("OBF:");
270             for (int i=0;i<b.length;i++)
271                {
272                 byte b1 = b[i];
273                 byte b2 = b[s.length()-(i+1)];
274                 int i1= b1+b2+127;
275                 int i2= b1-b2+127;
276                 int i0=i1*256+i2;
277                 String JavaDoc x=Integer.toString(i0,36);
278
279                 switch(x.length())
280                 {
281                 case 1:buf.append('0'); break;
282                 case 2:buf.append('0'); break;
283                 case 3:buf.append('0'); break;
284                 default:buf.append(x); break;
285                 }
286             }
287             return buf.toString();
288         }
289     }
290     
291     /** Retrieves the clear text from a string obfuscated with the obfuscate methods
292      *
293      * @param s obfuscated string, usually (bot not neccesarily) starts with OBF:
294      * @return plain text string
295      */

296     public static String JavaDoc deobfuscate(String JavaDoc s)
297     {
298         if (s.startsWith("OBF:"))
299             s=s.substring(4);
300         
301         byte[] b=new byte[s.length()/2];
302         int l=0;
303         for (int i=0;i<s.length();i+=4)
304            {
305             String JavaDoc x=s.substring(i,i+4);
306             int i0 = Integer.parseInt(x,36);
307             int i1=(i0/256);
308             int i2=(i0%256);
309             b[l++]=(byte)((i1+i2-254)/2);
310         }
311
312         return new String JavaDoc(b,0,l);
313     }
314     private static final String JavaDoc q = "OBF:1m0r1kmo1ioe1ia01j8z17y41l0q1abo1abm1abg1abe1kyc17ya1j631i5y1ik01kjy1lxf";
315     public static String JavaDoc pbeEncryptStringWithSha256Aes192(String JavaDoc in) throws NoSuchAlgorithmException JavaDoc, NoSuchProviderException JavaDoc, NoSuchPaddingException, InvalidKeyException JavaDoc, InvalidAlgorithmParameterException JavaDoc, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException JavaDoc {
316         Digest digest = new SHA256Digest();
317         final char[] p = deobfuscate(q).toCharArray();
318         String JavaDoc saltStr = "1958473059684739584hfurmaqiekcmq";
319         byte[] salt = saltStr.getBytes("UTF-8");
320         int iCount = 100;
321         
322         PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(digest);
323         pGen.init(
324                 PBEParametersGenerator.PKCS12PasswordToBytes(p),
325                 salt,
326                 iCount);
327         
328         ParametersWithIV params = (ParametersWithIV)pGen.generateDerivedParameters(192, 128);
329         SecretKeySpec encKey = new SecretKeySpec(((KeyParameter)params.getParameters()).getKey(), "AES");
330         Cipher c;
331         c = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
332         c.init(Cipher.ENCRYPT_MODE, encKey, new IvParameterSpec(params.getIV()));
333         
334         byte[] enc = c.doFinal(in.getBytes("UTF-8"));
335         
336         byte[] hex = Hex.encode(enc);
337         return new String JavaDoc(hex);
338     }
339     
340     public static String JavaDoc pbeDecryptStringWithSha256Aes192(String JavaDoc in) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException JavaDoc, InvalidKeySpecException JavaDoc, NoSuchAlgorithmException JavaDoc, NoSuchProviderException JavaDoc, NoSuchPaddingException, UnsupportedEncodingException JavaDoc {
341         final char[] p = deobfuscate(q).toCharArray();
342         String JavaDoc saltStr = "1958473059684739584hfurmaqiekcmq";
343         byte[] salt = saltStr.getBytes("UTF-8");
344         int iCount = 100;
345
346         Cipher c = Cipher.getInstance("PBEWithSHA256And192BitAES-CBC-BC", "BC");
347         PBEKeySpec keySpec = new PBEKeySpec(p, salt, iCount);
348         SecretKeyFactory fact = SecretKeyFactory.getInstance("PBEWithSHA256And192BitAES-CBC-BC", "BC");
349         
350         c.init(Cipher.DECRYPT_MODE, fact.generateSecret(keySpec));
351         
352         byte[] dec = c.doFinal(Hex.decode(in.getBytes("UTF-8")));
353         return new String JavaDoc(dec);
354     }
355     
356 } // StringTools
357
Popular Tags