Source Code Cross Referenced for RandPass.java in  » Template-Engine » ostermillerutils » com » Ostermiller » util » 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 » Template Engine » ostermillerutils » com.Ostermiller.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Generate random passwords.
003:         * Copyright (C) 2001-2007 Stephen Ostermiller
004:         * http://ostermiller.org/contact.pl?regarding=Java+Utilities
005:         *
006:         * This program is free software; you can redistribute it and/or modify
007:         * it under the terms of the GNU General Public License as published by
008:         * the Free Software Foundation; either version 2 of the License, or
009:         * (at your option) any later version.
010:         *
011:         * This program is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:         * GNU General Public License for more details.
015:         *
016:         * See COPYING.TXT for details.
017:         */
018:
019:        package com.Ostermiller.util;
020:
021:        import java.security.SecureRandom;
022:        import java.text.MessageFormat;
023:        import java.util.ResourceBundle;
024:        import java.util.Locale;
025:        import java.util.Vector;
026:
027:        /**
028:         * Generates a random String using a cryptographically
029:         * secure random number generator.
030:         * <p>
031:         * The alphabet (characters used in the passwords generated)
032:         * may be specified, and the random number generator can be
033:         * externally supplied.
034:         * <p>
035:         * Care should be taken when using methods that limit the types
036:         * of passwords may be generated.  Using an alphabet that is too
037:         * small, using passwords that are too short, requiring too many
038:         * of a certain type of character, or not allowing repetition,
039:         * may decrease security.
040:         * <p>
041:         * More information about this class is available from <a target="_top" href=
042:         * "http://ostermiller.org/utils/RandPass.html">ostermiller.org</a>.
043:         *
044:         * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
045:         * @since ostermillerutils 1.00.00
046:         */
047:        public class RandPass {
048:
049:            /**
050:             * Version number of this program
051:             *
052:             * @since ostermillerutils 1.00.00
053:             */
054:            public static final String version = "1.1";
055:
056:            /**
057:             * Locale specific strings displayed to the user.
058:             *
059:             * @since ostermillerutils 1.00.00
060:             */
061:            protected static ResourceBundle labels = ResourceBundle.getBundle(
062:                    "com.Ostermiller.util.RandPass", Locale.getDefault());
063:
064:            /**
065:             * Default length for passwords
066:             *
067:             * @since ostermillerutils 1.00.00
068:             */
069:            private static final int DEFAULT_PASSWORD_LENGTH = 8;
070:
071:            /**
072:             * Alphabet consisting of upper and lower case letters A-Z and
073:             * the digits 0-9.
074:             *
075:             * @since ostermillerutils 1.00.00
076:             */
077:            public static final char[] NUMBERS_AND_LETTERS_ALPHABET = { 'A',
078:                    'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
079:                    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
080:                    'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
081:                    'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
082:                    'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8',
083:                    '9', };
084:
085:            /**
086:             * Alphabet consisting of all the printable ASCII symbols.
087:             *
088:             * @since ostermillerutils 1.00.00
089:             */
090:            public static final char[] SYMBOLS_ALPHABET = { '!', '\"', '#',
091:                    '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
092:                    '/', ':', ';', '<', '?', '@', '[', '\\', ']', '^', '_',
093:                    '`', '{', '|', '}', '~', };
094:
095:            /**
096:             * Alphabet consisting of all the printable ASCII characters.
097:             *
098:             * @since ostermillerutils 1.00.00
099:             */
100:            public static final char[] PRINTABLE_ALPHABET = { '!', '\"', '#',
101:                    '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.',
102:                    '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':',
103:                    ';', '<', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
104:                    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
105:                    'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
106:                    '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
107:                    'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
108:                    'x', 'y', 'z', '{', '|', '}', '~', };
109:
110:            /**
111:             * Alphabet consisting of the lower case letters A-Z.
112:             *
113:             * @since ostermillerutils 1.00.00
114:             */
115:            public static final char[] LOWERCASE_LETTERS_ALPHABET = { 'a', 'b',
116:                    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
117:                    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', };
118:
119:            /**
120:             * Alphabet consisting of the lower case letters A-Z and
121:             * the digits 0-9.
122:             *
123:             * @since ostermillerutils 1.00.00
124:             */
125:            public static final char[] LOWERCASE_LETTERS_AND_NUMBERS_ALPHABET = {
126:                    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
127:                    'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
128:                    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', };
129:
130:            /**
131:             * Alphabet consisting of upper and lower case letters A-Z.
132:             *
133:             * @since ostermillerutils 1.00.00
134:             */
135:            public static final char[] LETTERS_ALPHABET = { 'A', 'B', 'C', 'D',
136:                    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
137:                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
138:                    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
139:                    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', };
140:
141:            /**
142:             * Alphabet consisting of the upper letters A-Z.
143:             *
144:             * @since ostermillerutils 1.00.00
145:             */
146:            public static final char[] UPPERCASE_LETTERS_ALPHABET = { 'A', 'B',
147:                    'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
148:                    'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', };
149:
150:            /**
151:             * Alphabet consisting of upper and lower case letters A-Z and
152:             * the digits 0-9 but with characters that are often mistaken
153:             * for each other when typed removed. (I,L,O,U,V,i,l,o,u,v,0,1)
154:             *
155:             * @since ostermillerutils 1.00.00
156:             */
157:            public static final char[] NONCONFUSING_ALPHABET = { 'A', 'B', 'C',
158:                    'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R',
159:                    'S', 'T', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
160:                    'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'w',
161:                    'x', 'y', 'z', '2', '3', '4', '5', '6', '7', '8', '9', };
162:
163:            /**
164:             * Random number generator used.
165:             *
166:             * @since ostermillerutils 1.00.00
167:             */
168:            protected SecureRandom rand;
169:
170:            /**
171:             * One less than the maximum number of repeated characters
172:             * that are allowed in a password.
173:             * Set to -1 to disable this feature.
174:             *
175:             * @since ostermillerutils 1.00.00
176:             */
177:            protected int repetition = -1;
178:
179:            /**
180:             * Set of characters which may be
181:             * used in the generated passwords.
182:             * <p>
183:             * This value may not be null or have
184:             * no elements.
185:             *
186:             * @since ostermillerutils 1.00.00
187:             */
188:            protected char[] alphabet;
189:
190:            /**
191:             * Set of characters which may be
192:             * used for the first character
193:             * in the generated passwords.
194:             * <p>
195:             * This value may be null but it must
196:             * have at least one element otherwise.
197:             *
198:             * @since ostermillerutils 1.00.00
199:             */
200:            protected char[] firstAlphabet;
201:
202:            /**
203:             * Set of characters which may be
204:             * used for the last character
205:             * in the generated passwords.
206:             * <p>
207:             * This value may be null but it must
208:             * have at least one element otherwise.
209:             *
210:             * @since ostermillerutils 1.00.00
211:             */
212:            protected char[] lastAlphabet;
213:
214:            /**
215:             * Create a new random password generator
216:             * with the default secure random number generator
217:             * and default NONCONFUSING alphabet for all characters.
218:             *
219:             * @since ostermillerutils 1.00.00
220:             */
221:            public RandPass() {
222:                this (new SecureRandom(), NONCONFUSING_ALPHABET);
223:            }
224:
225:            /**
226:             * Create a new random password generator
227:             * with the given secure random number generator
228:             * and default NONCONFUSING alphabet for all characters.
229:             *
230:             * @param rand Secure random number generator to use when generating passwords.
231:             *
232:             * @since ostermillerutils 1.00.00
233:             */
234:            public RandPass(SecureRandom rand) {
235:                this (rand, NONCONFUSING_ALPHABET);
236:            }
237:
238:            /**
239:             * Create a new random password generator
240:             * with the default secure random number generator
241:             * and given alphabet for all characters.
242:             *
243:             * @param alphabet Characters allowed in generated passwords.
244:             *
245:             * @since ostermillerutils 1.00.00
246:             */
247:            public RandPass(char[] alphabet) {
248:                this (new SecureRandom(), alphabet);
249:            }
250:
251:            /**
252:             * Create a new random password generator
253:             * with the given secure random number generator
254:             * and given alphabet for all characters.
255:             *
256:             * @param rand Secure random number generator to use when generating passwords.
257:             * @param alphabet Characters allowed in generated passwords.
258:             *
259:             * @since ostermillerutils 1.00.00
260:             */
261:            public RandPass(SecureRandom rand, char[] alphabet) {
262:                this .rand = rand;
263:                this .alphabet = alphabet;
264:            }
265:
266:            private class Requirement {
267:                private Requirement(char[] alphabet, int num) {
268:                    this .alphabet = alphabet;
269:                    this .num = num;
270:                }
271:
272:                private char[] alphabet;
273:                private int num;
274:            }
275:
276:            private enum RandPassCmdLnOption {
277:                /** --help */
278:                HELP(new CmdLnOption(labels.getString("help.option"))
279:                        .setDescription(labels.getString("help.message"))),
280:                /** --version */
281:                VERSION(new CmdLnOption(labels.getString("version.option"))
282:                        .setDescription(labels.getString("version.message"))),
283:                /** --about */
284:                ABOUT(new CmdLnOption(labels.getString("about.option"))
285:                        .setDescription(labels.getString("about.message"))),
286:                /** --alphabet */
287:                ALPHABET(new CmdLnOption(labels.getString("alphabet.option"),
288:                        'a').setRequiredArgument().setDescription(
289:                        labels.getString("a.message"))),
290:                /** --first */
291:                FIRST(new CmdLnOption(
292:                        labels.getString("first.alphabet.option"), 'F')
293:                        .setRequiredArgument().setDescription(
294:                                labels.getString("F.message"))),
295:                /** --last */
296:                LAST(new CmdLnOption(labels.getString("last.alphabet.option"),
297:                        'L').setRequiredArgument().setDescription(
298:                        labels.getString("L.message"))),
299:                /** --number */
300:                NUMBER(new CmdLnOption(labels.getString("number.option"), 'n')
301:                        .setRequiredArgument().setDescription(
302:                                labels.getString("n.message"))),
303:                /** --reps */
304:                REPS(new CmdLnOption(labels.getString("maxrep.option"), 'r')
305:                        .setRequiredArgument().setDescription(
306:                                labels.getString("r.message"))),
307:                /** --length */
308:                LENGTH(new CmdLnOption(labels.getString("length.option"), 'l')
309:                        .setRequiredArgument().setDescription(
310:                                labels.getString("l.message"))),
311:                /** --require */
312:                REQUIRE(
313:                        new CmdLnOption(labels.getString("require.option"), 'R')
314:                                .setRequiredArgument().setDescription(
315:                                        labels.getString("R.message"))),
316:                /** --verify */
317:                VERIFY(new CmdLnOption(labels.getString("verify.option"), 'v')
318:                        .setRequiredArgument().setDescription(
319:                                labels.getString("v.message")));
320:
321:                private CmdLnOption option;
322:
323:                private RandPassCmdLnOption(CmdLnOption option) {
324:                    option.setUserObject(this );
325:                    this .option = option;
326:                }
327:
328:                private CmdLnOption getCmdLineOption() {
329:                    return option;
330:                }
331:            }
332:
333:            /**
334:             * Generate a random passwords.
335:             * Run with --help argument for more information.
336:             *
337:             * @param args Command line arguments.
338:             * @throws Exception errors
339:             *
340:             * @since ostermillerutils 1.00.00
341:             */
342:            public static void main(String[] args) throws Exception {
343:                CmdLn commandLine = new CmdLn(args).setDescription(labels
344:                        .getString("randpass")
345:                        + labels.getString("purpose.message"));
346:                for (RandPassCmdLnOption option : RandPassCmdLnOption.values()) {
347:                    commandLine.addOption(option.getCmdLineOption());
348:                }
349:                int number = 1;
350:                char[] alphabet = NONCONFUSING_ALPHABET;
351:                char[] firstAlphabet = null;
352:                char[] lastAlphabet = null;
353:                Vector<String> reqs = new Vector<String>();
354:                Vector<String> ver = new Vector<String>();
355:                int maxreps = 0;
356:                int length = 8;
357:                for (CmdLnResult result : commandLine.getResults()) {
358:                    switch ((RandPassCmdLnOption) result.getOption()
359:                            .getUserObject()) {
360:                    case HELP: {
361:                        // print out the help message
362:                        commandLine.printHelp();
363:                        System.exit(0);
364:                    }
365:                        break;
366:                    case VERSION: {
367:                        // print out the version message
368:                        System.out.println(MessageFormat.format(labels
369:                                .getString("version"),
370:                                (Object[]) new String[] { version }));
371:                        System.exit(0);
372:                    }
373:                        break;
374:                    case ABOUT: {
375:                        System.out
376:                                .println(labels.getString("randpass")
377:                                        + " -- "
378:                                        + labels.getString("purpose.message")
379:                                        + "\n"
380:                                        + MessageFormat
381:                                                .format(
382:                                                        labels
383:                                                                .getString("copyright"),
384:                                                        (Object[]) new String[] {
385:                                                                "2001-2007",
386:                                                                "Stephen Ostermiller (http://ostermiller.org/contact.pl?regarding=Java+Utilities)" })
387:                                        + "\n\n" + labels.getString("license"));
388:                        System.exit(0);
389:                    }
390:                        break;
391:                    case ALPHABET: {
392:                        String alph = result.getArgument();
393:                        if (alph.length() == 0) {
394:                            alphabet = NONCONFUSING_ALPHABET;
395:                        } else {
396:                            alphabet = alph.toCharArray();
397:                        }
398:                    }
399:                        break;
400:                    case FIRST: {
401:                        String alph = result.getArgument();
402:                        if (alph.length() == 0) {
403:                            firstAlphabet = null;
404:                        } else {
405:                            firstAlphabet = alph.toCharArray();
406:                        }
407:                    }
408:                        break;
409:                    case LAST: {
410:                        String alph = result.getArgument();
411:                        if (alph.length() == 0) {
412:                            lastAlphabet = null;
413:                        } else {
414:                            lastAlphabet = alph.toCharArray();
415:                        }
416:                    }
417:                        break;
418:                    case REQUIRE: {
419:                        String alph = result.getArgument();
420:                        if (alph.length() != 0) {
421:                            reqs.add(alph);
422:                        }
423:                    }
424:                        break;
425:                    case VERIFY: {
426:                        ver.add(result.getArgument());
427:                    }
428:                        break;
429:                    case NUMBER: {
430:                        try {
431:                            number = Integer.parseInt(result.getArgument());
432:                            if (number <= 0)
433:                                throw new NumberFormatException();
434:                        } catch (NumberFormatException nfe) {
435:                            System.err.println(labels
436:                                    .getString("number.bad_argument"));
437:                            System.exit(0);
438:                        }
439:                    }
440:                        break;
441:                    case REPS: {
442:                        try {
443:                            maxreps = Integer.parseInt(result.getArgument());
444:                            if (maxreps < 0)
445:                                throw new NumberFormatException();
446:                        } catch (NumberFormatException nfe) {
447:                            System.err.println(labels
448:                                    .getString("number.bad_argument"));
449:                            System.exit(0);
450:                        }
451:                    }
452:                        break;
453:                    case LENGTH: {
454:                        try {
455:                            length = Integer.parseInt(result.getArgument());
456:                            if (length < 0)
457:                                throw new NumberFormatException();
458:                        } catch (NumberFormatException nfe) {
459:                            System.err.println(labels
460:                                    .getString("number.bad_argument"));
461:                            System.exit(0);
462:                        }
463:                    }
464:                        break;
465:                    }
466:                }
467:                RandPass randPass = new RandPass();
468:                randPass.setAlphabet(alphabet);
469:                randPass.setFirstAlphabet(firstAlphabet);
470:                randPass.setLastAlphabet(lastAlphabet);
471:                randPass.setMaxRepetition(maxreps);
472:                for (int i = 0; i < reqs.size(); i++) {
473:                    randPass.addRequirement((reqs.elementAt(i)).toCharArray(),
474:                            1);
475:                }
476:                for (int i = 0; i < ver.size(); i++) {
477:                    randPass.addVerifier((PasswordVerifier) ((Class
478:                            .forName((ver.elementAt(i)))).newInstance()));
479:                }
480:                for (int i = 0; i < number; i++) {
481:                    System.out.println(randPass.getPass(length));
482:                }
483:            }
484:
485:            private Vector<Requirement> requirements = null;
486:
487:            /**
488:             * Require that a certain number of characters from an
489:             * alphabet be present in generated passwords.
490:             *
491:             * @param alphabet set of letters that must be present
492:             * @param num number of letters from the alphabet that must be present.
493:             *
494:             * @since ostermillerutils 1.00.00
495:             */
496:            public void addRequirement(char[] alphabet, int num) {
497:                if (requirements == null)
498:                    requirements = new Vector<Requirement>();
499:                requirements.add(new Requirement(alphabet, num));
500:            }
501:
502:            /**
503:             * Set the alphabet used by this random password generator.
504:             *
505:             * @param alphabet Characters allowed in generated passwords.
506:             * @throws NullPointerException if the alphabet is null.
507:             * @throws ArrayIndexOutOfBoundsException if the alphabet has no elements.
508:             *
509:             * @since ostermillerutils 1.00.00
510:             */
511:            public void setAlphabet(char[] alphabet) {
512:                if (alphabet == null)
513:                    throw new NullPointerException("Null alphabet");
514:                if (alphabet.length == 0)
515:                    throw new ArrayIndexOutOfBoundsException(
516:                            "No characters in alphabet");
517:                this .alphabet = alphabet;
518:            }
519:
520:            /**
521:             * Set the random number generator used by this random password generator.
522:             *
523:             * @param rand Secure random number generator to use when generating passwords.
524:             *
525:             * @since ostermillerutils 1.00.00
526:             */
527:            public void setRandomGenerator(SecureRandom rand) {
528:                this .rand = rand;
529:            }
530:
531:            /**
532:             * Set the alphabet used by this random password generator for the first character
533:             * of passwords.
534:             * <p>
535:             * If the alphabet for the first character is set to null or has no elements, the main alphabet will
536:             * be used for the first character.
537:             *
538:             * @param alphabet Characters allowed for the first character of the passwords.
539:             *
540:             * @since ostermillerutils 1.00.00
541:             */
542:            public void setFirstAlphabet(char[] alphabet) {
543:                if (alphabet == null || alphabet.length == 0) {
544:                    this .firstAlphabet = null;
545:                } else {
546:                    this .firstAlphabet = alphabet;
547:                }
548:            }
549:
550:            /**
551:             * Set the alphabet used by this random password generator for the last character
552:             * of passwords.
553:             * <p>
554:             * If the alphabet for the last character is set to null or has no elements, the main alphabet will
555:             * be used for the last character.
556:             *
557:             * @param alphabet Characters allowed for the last character of the passwords.
558:             *
559:             * @since ostermillerutils 1.00.00
560:             */
561:            public void setLastAlphabet(char[] alphabet) {
562:                if (alphabet == null || alphabet.length == 0) {
563:                    this .lastAlphabet = null;
564:                } else {
565:                    this .lastAlphabet = alphabet;
566:                }
567:            }
568:
569:            /**
570:             * Set the maximum number of characters that may appear in sequence more than
571:             * once in a password.  Your alphabet must be large enough to handle this
572:             * option.  If your alphabet is {'a', 'b'} and you want 8 character passwords
573:             * in which no character appears twice (repetition 1) you are out of luck.
574:             * In such instances your request for no repetition will be ignored.
575:             * <p>
576:             * For example setRepetition(3) will allow a password ababab but not allow
577:             * abcabc.
578:             * <p>
579:             * Using this method can greatly reduce the pool of passwords that are generated.
580:             * For example if only one repetition is allowed then the pool of passwords
581:             * is the permutation of the alphabet rather than the combination.
582:             *
583:             * @param rep Maximum character repetition.
584:             *
585:             * @since ostermillerutils 1.00.00
586:             */
587:            public void setMaxRepetition(int rep) {
588:                this .repetition = rep - 1;
589:            }
590:
591:            /**
592:             * Fill the given buffer with random characters.
593:             * <p>
594:             * Using this method, the password character array can easily
595:             * be reused for efficiency, or overwritten with new random
596:             * characters for security.
597:             * <p>
598:             * NOTE: If it is possible for a hacker to examine memory to find passwords,
599:             * the password should be overwritten in memory as soon as possible after i
600:             * is no longer in use.
601:             *
602:             * @param pass buffer that will hold the password.
603:             * @return the buffer, filled with random characters.
604:             *
605:             * @since ostermillerutils 1.00.00
606:             */
607:            public char[] getPassChars(char[] pass) {
608:                boolean verified = false;
609:                while (!verified) {
610:                    int length = pass.length;
611:                    for (int i = 0; i < length; i++) {
612:                        char[] useAlph = alphabet;
613:                        if (i == 0 && firstAlphabet != null) {
614:                            useAlph = firstAlphabet;
615:                        } else if (i == length - 1 && lastAlphabet != null) {
616:                            useAlph = lastAlphabet;
617:                        }
618:                        int size = avoidRepetition(useAlph, pass, i,
619:                                repetition, useAlph.length);
620:                        pass[i] = useAlph[rand.nextInt(size)];
621:                    }
622:                    if (requirements != null)
623:                        applyRequirements(pass);
624:                    verified = true;
625:                    for (int i = 0; verified && verifiers != null
626:                            && i < verifiers.size(); i++) {
627:                        verified = verifiers.elementAt(i).verify(pass);
628:                    }
629:                }
630:                return (pass);
631:            }
632:
633:            private Vector<PasswordVerifier> verifiers = null;
634:
635:            /**
636:             * Add a class that will verify passwords.  No password
637:             * will be returned unless all verifiers approve of it.
638:             *
639:             * @param verifier class that performs verification of password.
640:             *
641:             * @since ostermillerutils 1.00.00
642:             */
643:            public void addVerifier(PasswordVerifier verifier) {
644:                if (verifiers == null)
645:                    verifiers = new Vector<PasswordVerifier>();
646:                verifiers.add(verifier);
647:            }
648:
649:            private boolean[] touched = null;
650:            private int[] available = null;
651:
652:            private void applyRequirements(char[] pass) {
653:                int size = requirements.size();
654:                if (size > 0) {
655:                    int length = pass.length;
656:                    if (touched == null || touched.length < length)
657:                        touched = new boolean[length];
658:                    if (available == null || available.length < length)
659:                        available = new int[length];
660:                    for (int i = 0; i < length; i++) {
661:                        touched[i] = false;
662:                    }
663:                    for (int reqNum = 0; reqNum < size; reqNum++) {
664:                        Requirement req = requirements.elementAt(reqNum);
665:                        // set the portion of this alphabet available for use.
666:                        int reqUsedInd = req.alphabet.length;
667:                        // figure out how much of this requirement is already fulfilled
668:                        // and what is available to fulfill the rest of it.
669:                        int fufilledInd = 0;
670:                        int availableInd = 0;
671:                        for (int i = 0; i < length; i++) {
672:                            if (arrayContains(req.alphabet, pass[i])
673:                                    && fufilledInd < req.num) {
674:                                fufilledInd++;
675:                                touched[i] = true;
676:                                if (repetition >= 0) {
677:                                    // move already used characters so they can'
678:                                    // be used again.  This prevents repetition.
679:                                    reqUsedInd -= moveto(req.alphabet,
680:                                            reqUsedInd, pass[i]);
681:                                    // allow repetition if we have no other choice
682:                                    if (reqUsedInd < 0)
683:                                        reqUsedInd = req.alphabet.length;
684:                                }
685:                            } else if (!touched[i]) {
686:                                available[availableInd] = i;
687:                                availableInd++;
688:                            }
689:                        }
690:                        // fulfill the requirement
691:                        int toDo = req.num - fufilledInd;
692:                        for (int i = 0; i < toDo && availableInd > 0; i++) {
693:                            // pick a random available slot
694:                            // and a random member of the available alphabet
695:                            int slot = rand.nextInt(availableInd);
696:                            char passChar = req.alphabet[rand
697:                                    .nextInt(reqUsedInd)];
698:                            pass[available[slot]] = passChar;
699:                            touched[available[slot]] = true;
700:                            // make the slot no longer available
701:                            availableInd--;
702:                            available[slot] = available[availableInd];
703:                            if (repetition >= 0) {
704:                                // move already used characters so they can'
705:                                // be used again.  This prevents repetition.
706:                                reqUsedInd -= moveto(req.alphabet, reqUsedInd,
707:                                        passChar);
708:                                // allow repetition if we have no other choice
709:                                if (reqUsedInd < 0)
710:                                    reqUsedInd = req.alphabet.length;
711:                            }
712:                        }
713:                    }
714:                }
715:            }
716:
717:            private static boolean arrayContains(char[] alph, char c) {
718:                for (int i = 0; i < alph.length; i++) {
719:                    if (alph[i] == c)
720:                        return true;
721:                }
722:                return false;
723:            }
724:
725:            /**
726:             * Avoid repetition (if possible) by moving all characters that would cause repetition to
727:             * the end of the alphabet and returning the size of the alphabet that may be used.
728:             *
729:             * @since ostermillerutils 1.00.00
730:             */
731:            private static int avoidRepetition(char[] alph, char[] pass,
732:                    int passSize, int repetition, int alphSize) {
733:                if (repetition > -1) {
734:                    // limit the alphabet to those characters that
735:                    // will not cause repeating sequences
736:                    int repPos = 0;
737:                    while ((repPos = findRep(pass, repPos, passSize, repetition)) != -1) {
738:                        // shuffle characters that would cause repetition
739:                        // to the end of the alphabet and adjust the size
740:                        // so that they will not be used.
741:                        alphSize -= moveto(alph, alphSize, pass[repPos
742:                                + repetition]);
743:                        repPos++;
744:                    }
745:                    if (alphSize == 0)
746:                        alphSize = alph.length;
747:                }
748:                return alphSize;
749:            }
750:
751:            /**
752:             * Find a repetition of the desired length.  The characters to search
753:             * for are located at pass[end-length] to pass[end]
754:             *
755:             * @since ostermillerutils 1.00.00
756:             */
757:            private static int findRep(char[] pass, int start, int end,
758:                    int length) {
759:                for (int i = start; i < end - length; i++) {
760:                    boolean onTrack = true;
761:                    for (int j = 0; onTrack && j < length; j++) {
762:                        if (pass[i + j] != pass[end - length + j])
763:                            onTrack = false;
764:                    }
765:                    if (onTrack)
766:                        return i;
767:                }
768:                return -1;
769:            }
770:
771:            /**
772:             * move all of the given character to the end of the array
773:             * and return the number of characters moved.
774:             *
775:             * @since ostermillerutils 1.00.00
776:             */
777:            private static int moveto(char[] alph, int numGood, char c) {
778:                int count = 0;
779:                for (int i = 0; i < numGood; i++) {
780:                    if (alph[i] == c) {
781:                        numGood--;
782:                        char temp = alph[numGood];
783:                        alph[numGood] = alph[i];
784:                        alph[i] = temp;
785:                        count++;
786:                    }
787:                }
788:                return count;
789:            }
790:
791:            /**
792:             * Generate a random password of the given length.
793:             * <p>
794:             * NOTE: If it is possible for a hacker to examine memory to find passwords,
795:             * the password should be overwritten in memory as soon as possible after i
796:             * is no longer in use.
797:             *
798:             * @param length The desired length of the generated password.
799:             * @return a random password
800:             *
801:             * @since ostermillerutils 1.00.00
802:             */
803:            public char[] getPassChars(int length) {
804:                return (getPassChars(new char[length]));
805:            }
806:
807:            /**
808:             * Generate a random password of the default length (8).
809:             * <p>
810:             * NOTE: If it is possible for a hacker to examine memory to find passwords,
811:             * the password should be overwritten in memory as soon as possible after i
812:             * is no longer in use.
813:             *
814:             * @return a random password
815:             *
816:             * @since ostermillerutils 1.00.00
817:             */
818:            public char[] getPassChars() {
819:                return (getPassChars(DEFAULT_PASSWORD_LENGTH));
820:            }
821:
822:            /**
823:             * Generate a random password of the given length.
824:             * <p>
825:             * NOTE: Strings can not be modified.  If it is possible
826:             * for a hacker to examine memory to find passwords, getPassChars()
827:             * should be used so that the password can be zeroed out of memory
828:             * when no longer in use.
829:             *
830:             * @param length The desired length of the generated password.
831:             * @return a random password
832:             *
833:             * @see #getPassChars(int)
834:             * @since ostermillerutils 1.00.00
835:             */
836:            public String getPass(int length) {
837:                return (new String(getPassChars(new char[length])));
838:            }
839:
840:            /**
841:             * Generate a random password of the default length (8).
842:             * <p>
843:             * NOTE: Strings can not be modified.  If it is possible
844:             * for a hacker to examine memory to find passwords, getPassChars()
845:             * should be used so that the password can be zeroed out of memory
846:             * when no longer in use.
847:             *
848:             * @return a random password
849:             *
850:             * @see #getPassChars()
851:             * @since ostermillerutils 1.00.00
852:             */
853:            public String getPass() {
854:                return (getPass(DEFAULT_PASSWORD_LENGTH));
855:            }
856:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.