Source Code Cross Referenced for Util.java in  » EJB-Server-JBoss-4.2.1 » security » org » jboss » security » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server JBoss 4.2.1 » security » org.jboss.security 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JBoss, Home of Professional Open Source.
003:         * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004:         * as indicated by the @author tags. See the copyright.txt file in the
005:         * distribution for a full listing of individual contributors.
006:         *
007:         * This is free software; you can redistribute it and/or modify it
008:         * under the terms of the GNU Lesser General Public License as
009:         * published by the Free Software Foundation; either version 2.1 of
010:         * the License, or (at your option) any later version.
011:         *
012:         * This software is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015:         * Lesser General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this software; if not, write to the Free
019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021:         */
022:        package org.jboss.security;
023:
024:        import java.io.Serializable;
025:        import java.io.UnsupportedEncodingException;
026:        import java.lang.reflect.Constructor;
027:        import java.lang.reflect.Method;
028:        import java.math.BigInteger;
029:        import java.security.GeneralSecurityException;
030:        import java.security.KeyException;
031:        import java.security.MessageDigest;
032:        import java.security.NoSuchAlgorithmException;
033:        import java.security.Provider;
034:        import java.security.Security;
035:        import java.security.SecureRandom;
036:        import java.util.ArrayList;
037:        import java.util.Random;
038:        import java.util.StringTokenizer;
039:
040:        import org.jboss.crypto.JBossSXProvider;
041:        import org.jboss.crypto.digest.DigestCallback;
042:        import org.jboss.logging.Logger;
043:
044:        /** Various security related utilities like MessageDigest
045:         factories, SecureRandom access, password hashing.
046:
047:         This product includes software developed by Tom Wu and Eugene
048:         Jhong for the SRP Distribution (http://srp.stanford.edu/srp/).
049:
050:         @author Scott.Stark@jboss.org
051:         @version $Revision: 59905 $
052:         */
053:        public class Util {
054:            private static Logger log = Logger.getLogger(Util.class);
055:            private static final int HASH_LEN = 20;
056:            public static final String BASE64_ENCODING = "BASE64";
057:            public static final String BASE16_ENCODING = "HEX";
058:            public static final String RFC2617_ENCODING = "RFC2617";
059:            /**
060:             The ASCII printable characters the MD5 digest maps to for RFC2617
061:             */
062:            private static char[] MD5_HEX = "0123456789abcdef".toCharArray();
063:
064:            private static SecureRandom psuedoRng;
065:            private static MessageDigest sha1Digest;
066:            private static boolean initialized;
067:
068:            public static void init() throws NoSuchAlgorithmException {
069:                if (initialized)
070:                    return;
071:                init(null);
072:            }
073:
074:            public static void init(byte[] prngSeed)
075:                    throws NoSuchAlgorithmException {
076:                // Get an instance of the SHA-1 digest
077:                sha1Digest = MessageDigest.getInstance("SHA");
078:                // Get a cryptographically strong pseudo-random generator
079:                psuedoRng = SecureRandom.getInstance("SHA1PRNG");
080:                if (prngSeed != null)
081:                    psuedoRng.setSeed(prngSeed);
082:                // Install the JBossSX security provider
083:                Provider provider = new JBossSXProvider();
084:                Security.addProvider(provider);
085:                initialized = true;
086:            }
087:
088:            public static MessageDigest newDigest() {
089:                MessageDigest md = null;
090:                try {
091:                    md = (MessageDigest) sha1Digest.clone();
092:                } catch (CloneNotSupportedException e) {
093:                }
094:                return md;
095:            }
096:
097:            public static MessageDigest copy(MessageDigest md) {
098:                MessageDigest copy = null;
099:                try {
100:                    copy = (MessageDigest) md.clone();
101:                } catch (CloneNotSupportedException e) {
102:                }
103:                return copy;
104:            }
105:
106:            public static Random getPRNG() {
107:                return psuedoRng;
108:            }
109:
110:            /** Returns the next pseudorandom, uniformly distributed double value
111:             between 0.0 and 1.0 from this random number generator's sequence.
112:             */
113:            public static double nextDouble() {
114:                return psuedoRng.nextDouble();
115:            }
116:
117:            /** Returns the next pseudorandom, uniformly distributed long value from
118:             this random number generator's sequence. The general contract of
119:             nextLong is that one long value is pseudorandomly generated and
120:             returned. All 264 possible long values are produced with
121:             (approximately) equal probability.
122:             */
123:            public static long nextLong() {
124:                return psuedoRng.nextLong();
125:            }
126:
127:            /** Generates random bytes and places them into a user-supplied byte
128:             array. The number of random bytes produced is equal to the length
129:             of the byte array.
130:             */
131:            public static void nextBytes(byte[] bytes) {
132:                psuedoRng.nextBytes(bytes);
133:            }
134:
135:            /** Returns the given number of seed bytes, computed using the seed
136:             generation algorithm that this class uses to seed itself. This call
137:             may be used to seed other random number generators.
138:             */
139:            public static byte[] generateSeed(int numBytes) {
140:                return psuedoRng.generateSeed(numBytes);
141:            }
142:
143:            /** Cacluate the SRP RFC2945 password hash = H(salt | H(username | ':' | password))
144:             where H = SHA secure hash. The username is converted to a byte[] using the
145:             UTF-8 encoding.
146:             */
147:            public static byte[] calculatePasswordHash(String username,
148:                    char[] password, byte[] salt) {
149:                // Calculate x = H(s | H(U | ':' | password))
150:                MessageDigest xd = newDigest();
151:                // Try to convert the username to a byte[] using UTF-8
152:                byte[] user = null;
153:                byte[] colon = {};
154:                try {
155:                    user = username.getBytes("UTF-8");
156:                    colon = ":".getBytes("UTF-8");
157:                } catch (UnsupportedEncodingException e) {
158:                    log.error(
159:                            "Failed to convert username to byte[] using UTF-8",
160:                            e);
161:                    // Use the default platform encoding
162:                    user = username.getBytes();
163:                    colon = ":".getBytes();
164:                }
165:                byte[] passBytes = new byte[2 * password.length];
166:                int passBytesLength = 0;
167:                for (int p = 0; p < password.length; p++) {
168:                    int c = (password[p] & 0x00FFFF);
169:                    // The low byte of the char
170:                    byte b0 = (byte) (c & 0x0000FF);
171:                    // The high byte of the char
172:                    byte b1 = (byte) ((c & 0x00FF00) >> 8);
173:                    passBytes[passBytesLength++] = b0;
174:                    // Only encode the high byte if c is a multi-byte char
175:                    if (c > 255)
176:                        passBytes[passBytesLength++] = b1;
177:                }
178:
179:                // Build the hash
180:                xd.update(user);
181:                xd.update(colon);
182:                xd.update(passBytes, 0, passBytesLength);
183:                byte[] h = xd.digest();
184:                xd.reset();
185:                xd.update(salt);
186:                xd.update(h);
187:                byte[] xb = xd.digest();
188:                return xb;
189:            }
190:
191:            /** Calculate x = H(s | H(U | ':' | password)) verifier
192:             v = g^x % N
193:             described in RFC2945.
194:             */
195:            public static byte[] calculateVerifier(String username,
196:                    char[] password, byte[] salt, byte[] Nb, byte[] gb) {
197:                BigInteger g = new BigInteger(1, gb);
198:                BigInteger N = new BigInteger(1, Nb);
199:                return calculateVerifier(username, password, salt, N, g);
200:            }
201:
202:            /** Calculate x = H(s | H(U | ':' | password)) verifier
203:             v = g^x % N
204:             described in RFC2945.
205:             */
206:            public static byte[] calculateVerifier(String username,
207:                    char[] password, byte[] salt, BigInteger N, BigInteger g) {
208:                byte[] xb = calculatePasswordHash(username, password, salt);
209:                BigInteger x = new BigInteger(1, xb);
210:                BigInteger v = g.modPow(x, N);
211:                return v.toByteArray();
212:            }
213:
214:            /** Perform an interleaved even-odd hash on the byte string
215:             */
216:            public static byte[] sessionKeyHash(byte[] number) {
217:                int i, offset;
218:
219:                for (offset = 0; offset < number.length && number[offset] == 0; ++offset)
220:                    ;
221:
222:                byte[] key = new byte[2 * HASH_LEN];
223:                byte[] hout;
224:
225:                int klen = (number.length - offset) / 2;
226:                byte[] hbuf = new byte[klen];
227:
228:                for (i = 0; i < klen; ++i) {
229:                    hbuf[i] = number[number.length - 2 * i - 1];
230:                }
231:                hout = newDigest().digest(hbuf);
232:                for (i = 0; i < HASH_LEN; ++i)
233:                    key[2 * i] = hout[i];
234:
235:                for (i = 0; i < klen; ++i) {
236:                    hbuf[i] = number[number.length - 2 * i - 2];
237:                }
238:                hout = newDigest().digest(hbuf);
239:                for (i = 0; i < HASH_LEN; ++i)
240:                    key[2 * i + 1] = hout[i];
241:
242:                return key;
243:            }
244:
245:            /** Treat the input as the MSB representation of a number,
246:             and lop off leading zero elements.  For efficiency, the
247:             input is simply returned if no leading zeroes are found.
248:             */
249:            public static byte[] trim(byte[] in) {
250:                if (in.length == 0 || in[0] != 0)
251:                    return in;
252:
253:                int len = in.length;
254:                int i = 1;
255:                while (in[i] == 0 && i < len)
256:                    ++i;
257:                byte[] ret = new byte[len - i];
258:                System.arraycopy(in, i, ret, 0, len - i);
259:                return ret;
260:            }
261:
262:            public static byte[] xor(byte[] b1, byte[] b2, int length) {
263:                byte[] result = new byte[length];
264:                for (int i = 0; i < length; ++i)
265:                    result[i] = (byte) (b1[i] ^ b2[i]);
266:                return result;
267:            }
268:
269:            /**
270:             3.1.3 Representation of digest values
271:
272:             An optional header allows the server to specify the algorithm used to create
273:             the checksum or digest. By default the MD5 algorithm is used and that is the
274:             only algorithm described in this document.
275:
276:             For the purposes of this document, an MD5 digest of 128 bits is represented
277:             as 32 ASCII printable characters. The bits in the 128 bit digest are
278:             converted from most significant to least significant bit, four bits at a time
279:             to their ASCII presentation as follows. Each four bits is represented by its
280:             familiar hexadecimal notation from the characters 0123456789abcdef. That is,
281:             binary 0000 getInfos represented by the character '0', 0001, by '1', and so
282:             on up to the representation of 1111 as 'f'.
283:             
284:             @param data - the raw MD5 hash data
285:             @return the encoded MD5 representation
286:             */
287:            public static String encodeRFC2617(byte[] data) {
288:                char[] hash = new char[32];
289:                for (int i = 0; i < 16; i++) {
290:                    int j = (data[i] >> 4) & 0xf;
291:                    hash[i * 2] = MD5_HEX[j];
292:                    j = data[i] & 0xf;
293:                    hash[i * 2 + 1] = MD5_HEX[j];
294:                }
295:                return new String(hash);
296:            }
297:
298:            /**
299:             * Hex encoding of hashes, as used by Catalina. Each byte is converted to
300:             * the corresponding two hex characters.
301:             */
302:            public static String encodeBase16(byte[] bytes) {
303:                StringBuffer sb = new StringBuffer(bytes.length * 2);
304:                for (int i = 0; i < bytes.length; i++) {
305:                    byte b = bytes[i];
306:                    // top 4 bits
307:                    char c = (char) ((b >> 4) & 0xf);
308:                    if (c > 9)
309:                        c = (char) ((c - 10) + 'a');
310:                    else
311:                        c = (char) (c + '0');
312:                    sb.append(c);
313:                    // bottom 4 bits
314:                    c = (char) (b & 0xf);
315:                    if (c > 9)
316:                        c = (char) ((c - 10) + 'a');
317:                    else
318:                        c = (char) (c + '0');
319:                    sb.append(c);
320:                }
321:                return sb.toString();
322:            }
323:
324:            /**
325:             * BASE64 encoder implementation.
326:             * Provides encoding methods, using the BASE64 encoding rules, as defined
327:             * in the MIME specification, <a href="http://ietf.org/rfc/rfc1521.txt">rfc1521</a>.
328:             */
329:            public static String encodeBase64(byte[] bytes) {
330:                String base64 = null;
331:                try {
332:                    base64 = Base64Encoder.encode(bytes);
333:                } catch (Exception e) {
334:                }
335:                return base64;
336:            }
337:
338:            /**
339:             * Calculate a password hash using a MessageDigest.
340:             *
341:             * @param hashAlgorithm - the MessageDigest algorithm name
342:             * @param hashEncoding - either base64 or hex to specify the type of
343:                encoding the MessageDigest as a string.
344:             * @param hashCharset - the charset used to create the byte[] passed to the
345:             *  MessageDigestfrom the password String. If null the platform default is
346:             *  used.
347:             * @param username - ignored in default version
348:             * @param password - the password string to be hashed
349:             * @return the hashed string if successful, null if there is a digest exception
350:             */
351:            public static String createPasswordHash(String hashAlgorithm,
352:                    String hashEncoding, String hashCharset, String username,
353:                    String password) {
354:                return createPasswordHash(hashAlgorithm, hashEncoding,
355:                        hashCharset, username, password, null);
356:            }
357:
358:            /**
359:             * Calculate a password hash using a MessageDigest.
360:             *
361:             * @param hashAlgorithm - the MessageDigest algorithm name
362:             * @param hashEncoding - either base64 or hex to specify the type of
363:                encoding the MessageDigest as a string.
364:             * @param hashCharset - the charset used to create the byte[] passed to the
365:             *  MessageDigestfrom the password String. If null the platform default is
366:             *  used.
367:             * @param username - ignored in default version
368:             * @param password - the password string to be hashed
369:             * @param callback - the callback used to allow customization of the hash
370:             *    to occur. The preDigest method is called before the password is added
371:             *    and the postDigest method is called after the password has been added.
372:             * @return the hashed string if successful, null if there is a digest exception
373:             */
374:            public static String createPasswordHash(String hashAlgorithm,
375:                    String hashEncoding, String hashCharset, String username,
376:                    String password, DigestCallback callback) {
377:                byte[] passBytes;
378:                String passwordHash = null;
379:
380:                // convert password to byte data
381:                try {
382:                    if (hashCharset == null)
383:                        passBytes = password.getBytes();
384:                    else
385:                        passBytes = password.getBytes(hashCharset);
386:                } catch (UnsupportedEncodingException uee) {
387:                    log.error("charset " + hashCharset
388:                            + " not found. Using platform default.", uee);
389:                    passBytes = password.getBytes();
390:                }
391:
392:                // calculate the hash and apply the encoding.
393:                try {
394:                    MessageDigest md = MessageDigest.getInstance(hashAlgorithm);
395:                    if (callback != null)
396:                        callback.preDigest(md);
397:                    md.update(passBytes);
398:                    if (callback != null)
399:                        callback.postDigest(md);
400:                    byte[] hash = md.digest();
401:                    if (hashEncoding.equalsIgnoreCase(BASE64_ENCODING)) {
402:                        passwordHash = Util.encodeBase64(hash);
403:                    } else if (hashEncoding.equalsIgnoreCase(BASE16_ENCODING)) {
404:                        passwordHash = Util.encodeBase16(hash);
405:                    } else if (hashEncoding.equalsIgnoreCase(RFC2617_ENCODING)) {
406:                        passwordHash = Util.encodeRFC2617(hash);
407:                    } else {
408:                        log.error("Unsupported hash encoding format "
409:                                + hashEncoding);
410:                    }
411:                } catch (Exception e) {
412:                    log.error("Password hash calculation failed ", e);
413:                }
414:                return passwordHash;
415:            }
416:
417:            // These functions assume that the byte array has MSB at 0, LSB at end.
418:            // Reverse the byte array (not the String) if this is not the case.
419:            // All base64 strings are in natural order, least significant digit last.
420:            public static String tob64(byte[] buffer) {
421:                return Base64Utils.tob64(buffer);
422:            }
423:
424:            public static byte[] fromb64(String str)
425:                    throws NumberFormatException {
426:                return Base64Utils.fromb64(str);
427:            }
428:
429:            /** From Appendix E of the JCE ref guide, the xaximum key size
430:             * allowed by the "Strong" jurisdiction policy files allows a maximum Blowfish
431:             * cipher size of 128 bits.
432:             * @return true if a Blowfish key can be initialized with 256 bit
433:             * size, false otherwise.
434:             */
435:            public static boolean hasUnlimitedCrypto() {
436:                boolean hasUnlimitedCrypto = false;
437:                try {
438:                    ClassLoader loader = Thread.currentThread()
439:                            .getContextClassLoader();
440:                    Class keyGenClass = loader
441:                            .loadClass("javax.crypto.KeyGenerator");
442:                    Class[] sig = { String.class };
443:                    Object[] args = { "Blowfish" };
444:                    Method kgenInstance = keyGenClass.getDeclaredMethod(
445:                            "getInstance", sig);
446:                    Object kgen = kgenInstance.invoke(null, args);
447:
448:                    Class[] sig2 = { int.class };
449:                    Object[] args2 = { new Integer(256) };
450:                    Method init = keyGenClass.getDeclaredMethod("init", sig2);
451:                    init.invoke(kgen, args2);
452:                    hasUnlimitedCrypto = true;
453:                } catch (Throwable e) {
454:                    log.debug("hasUnlimitedCrypto error", e);
455:                }
456:                return hasUnlimitedCrypto;
457:            }
458:
459:            /** Use reflection to create a javax.crypto.spec.SecretKeySpec to avoid
460:             an explicit reference to SecretKeySpec so that the JCE is not needed
461:             unless the SRP parameters indicate that encryption is needed.
462:             @return a javax.cyrpto.SecretKey
463:             */
464:            public static Object createSecretKey(String cipherAlgorithm,
465:                    Object key) throws KeyException {
466:                Class[] signature = { key.getClass(), String.class };
467:                Object[] args = { key, cipherAlgorithm };
468:                Object secretKey = null;
469:                try {
470:                    ClassLoader loader = Thread.currentThread()
471:                            .getContextClassLoader();
472:                    Class secretKeySpecClass = loader
473:                            .loadClass("javax.crypto.spec.SecretKeySpec");
474:                    Constructor ctor = secretKeySpecClass
475:                            .getDeclaredConstructor(signature);
476:                    secretKey = ctor.newInstance(args);
477:                } catch (Exception e) {
478:                    throw new KeyException(
479:                            "Failed to create SecretKeySpec from session key, msg="
480:                                    + e.getMessage());
481:                } catch (Throwable e) {
482:                    throw new KeyException(
483:                            "Unexpected exception during SecretKeySpec creation, msg="
484:                                    + e.getMessage());
485:                }
486:                return secretKey;
487:            }
488:
489:            /**
490:             * @param cipherAlgorithm
491:             * @return A javax.crypto.Cipher
492:             * @throws GeneralSecurityException
493:             */
494:            public static Object createCipher(String cipherAlgorithm)
495:                    throws GeneralSecurityException {
496:                javax.crypto.Cipher cipher = javax.crypto.Cipher
497:                        .getInstance(cipherAlgorithm);
498:                return cipher;
499:            }
500:
501:            public static Object createSealedObject(String cipherAlgorithm,
502:                    Object key, byte[] cipherIV, Serializable data)
503:                    throws GeneralSecurityException {
504:                Object sealedObject = null;
505:                try {
506:                    javax.crypto.Cipher cipher = javax.crypto.Cipher
507:                            .getInstance(cipherAlgorithm);
508:                    javax.crypto.SecretKey skey = (javax.crypto.SecretKey) key;
509:                    if (cipherIV != null) {
510:                        javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(
511:                                cipherIV);
512:                        cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skey, iv);
513:                    } else {
514:                        cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skey);
515:                    }
516:                    sealedObject = new javax.crypto.SealedObject(data, cipher);
517:                } catch (GeneralSecurityException e) {
518:                    throw e;
519:                } catch (Throwable e) {
520:                    throw new GeneralSecurityException(
521:                            "Failed to create SealedObject, msg="
522:                                    + e.getMessage());
523:                }
524:                return sealedObject;
525:            }
526:
527:            public static Object accessSealedObject(String cipherAlgorithm,
528:                    Object key, byte[] cipherIV, Object obj)
529:                    throws GeneralSecurityException {
530:                Object data = null;
531:                try {
532:                    javax.crypto.Cipher cipher = javax.crypto.Cipher
533:                            .getInstance(cipherAlgorithm);
534:                    javax.crypto.SecretKey skey = (javax.crypto.SecretKey) key;
535:                    if (cipherIV != null) {
536:                        javax.crypto.spec.IvParameterSpec iv = new javax.crypto.spec.IvParameterSpec(
537:                                cipherIV);
538:                        cipher.init(javax.crypto.Cipher.DECRYPT_MODE, skey, iv);
539:                    } else {
540:                        cipher.init(javax.crypto.Cipher.DECRYPT_MODE, skey);
541:                    }
542:                    javax.crypto.SealedObject sealedObj = (javax.crypto.SealedObject) obj;
543:                    data = sealedObj.getObject(cipher);
544:                } catch (GeneralSecurityException e) {
545:                    throw e;
546:                } catch (Throwable e) {
547:                    throw new GeneralSecurityException(
548:                            "Failed to access SealedObject, msg="
549:                                    + e.getMessage());
550:                }
551:                return data;
552:            }
553:
554:            /**
555:             * Execute a password load command to obtain the char[] contents of a
556:             * password.
557:             * @param  passwordCmd  - A command to execute to obtain the plaintext
558:             * password. The format is one of:
559:             * '{EXT}...' where the '...' is the exact command
560:             * line that will be passed to the Runtime.exec(String) method to execute a
561:             * platform command. The first line of the command output is used as the
562:             * password.
563:             * '{CLASS}classname[:ctorargs]' where the '[:ctorargs]' is an optional
564:             * string delimited by the ':' from the classname that will be passed to the
565:             * classname ctor. The ctorargs itself is a comma delimited list of strings.
566:             * The password is obtained from classname by invoking a
567:             * 'char[] toCharArray()' method if found, otherwise, the 'String toString()'
568:             * method is used.
569:             * @throws Exception
570:             */
571:            public static char[] loadPassword(String passwordCmd)
572:                    throws Exception {
573:                char[] password = null;
574:                String passwordCmdType = null;
575:
576:                // Look for a {...} prefix indicating a password command
577:                if (passwordCmd.charAt(0) == '{') {
578:                    StringTokenizer tokenizer = new StringTokenizer(
579:                            passwordCmd, "{}");
580:                    passwordCmdType = tokenizer.nextToken();
581:                    passwordCmd = tokenizer.nextToken();
582:                } else {
583:                    // Its just the password string
584:                    password = passwordCmd.toCharArray();
585:                }
586:
587:                if (password == null) {
588:                    // Load the password
589:                    if (passwordCmdType.equals("EXT"))
590:                        password = execPasswordCmd(passwordCmd);
591:                    else if (passwordCmdType.equals("CLASS"))
592:                        password = invokePasswordClass(passwordCmd);
593:                    else
594:                        throw new IllegalArgumentException(
595:                                "Unknown passwordCmdType: " + passwordCmdType);
596:                }
597:                return password;
598:            }
599:
600:            /**
601:             * Execute a Runtime command to load a password.
602:             * @param passwordCmd
603:             * @return
604:             * @throws Exception
605:             */
606:            private static char[] execPasswordCmd(String passwordCmd)
607:                    throws Exception {
608:                log.debug("Executing command: " + passwordCmd);
609:                String password = SecurityActions.execCmd(passwordCmd);
610:                return password.toCharArray();
611:            }
612:
613:            private static char[] invokePasswordClass(String passwordCmd)
614:                    throws Exception {
615:                char[] password = null;
616:
617:                // Check for a ctor argument delimited by ':'
618:                String classname = passwordCmd;
619:                String ctorArgs = null;
620:                int colon = passwordCmd.indexOf(':');
621:                if (colon > 0) {
622:                    classname = passwordCmd.substring(0, colon);
623:                    ctorArgs = passwordCmd.substring(colon + 1);
624:                }
625:                log.debug("Loading class: " + classname + ", ctorArgs="
626:                        + ctorArgs);
627:                ClassLoader loader = SecurityActions.getContextClassLoader();
628:                Class c = loader.loadClass(classname);
629:                Object instance = null;
630:                // Check for a ctor(String,...) if ctorArg is not null
631:                if (ctorArgs != null) {
632:                    Object[] args = ctorArgs.split(",");
633:                    Class[] sig = new Class[args.length];
634:                    ArrayList<Class> sigl = new ArrayList<Class>();
635:                    for (int n = 0; n < args.length; n++)
636:                        sigl.add(String.class);
637:                    sigl.toArray(sig);
638:                    Constructor ctor = c.getConstructor(sig);
639:                    instance = ctor.newInstance(args);
640:                } else {
641:                    // Use the default ctor
642:                    instance = c.newInstance();
643:                }
644:
645:                // Look for a toCharArray() method
646:                try {
647:                    log.debug("Checking for toCharArray");
648:                    Class[] sig = {};
649:                    Method toCharArray = c.getMethod("toCharArray", sig);
650:                    Object[] args = {};
651:                    log.debug("Invoking toCharArray");
652:                    password = (char[]) toCharArray.invoke(instance, args);
653:                } catch (NoSuchMethodException e) {
654:                    log.debug("No toCharArray found, invoking toString");
655:                    String tmp = instance.toString();
656:                    if (tmp != null)
657:                        password = tmp.toCharArray();
658:                }
659:                return password;
660:            }
661:
662:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.