View Javadoc

1   /*
2    * Created on Oct 4, 2004 
3    * Original filename was Password.java
4    */
5   package org.mortbay.util;
6   
7   /***
8    * $Id$ Copyright 1998-2004 Mort Bay Consulting Pty. Ltd.
9    * ------------------------------------------------------------------------
10   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
11   * use this file except in compliance with the License. You may obtain a copy of
12   * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
13   * applicable law or agreed to in writing, software distributed under the
14   * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
15   * OF ANY KIND, either express or implied. See the License for the specific
16   * language governing permissions and limitations under the License.
17   * ========================================================================
18   */
19  
20  /* ------------------------------------------------------------ */
21  /***
22   * Password utility class. This utility class gets a password or pass phrase
23   * either by:
24   * 
25   * <PRE>+ Password is set as a system property. + The password is prompted for
26   * and read from standard input + A program is run to get the password.
27   * 
28   * </pre>
29   * 
30   * Passwords that begin with OBF: are de obfuscated. Passwords can be obfuscated
31   * by run org.mortbay.util.Password as a main class. Obfuscated password are
32   * required if a system needs to recover the full password (eg. so that it may
33   * be passed to another system). They are not secure, but prevent casual
34   * observation.
35   * <p>
36   * Passwords that begin with CRYPT: are oneway encrypted with UnixCrypt. The
37   * real password cannot be retrieved, but comparisons can be made to other
38   * passwords. A Crypt can be generated by running org.mortbay.util.UnixCrypt as
39   * a main class, passing password and then the username. Checksum passwords are
40   * a secure(ish) way to store passwords that only need to be checked rather than
41   * recovered. Note that it is not strong security - specially if simple
42   * passwords are used.
43   * 
44   * @version $Id$
45   * @author Greg Wilkins (gregw)
46   */
47  public final class Password {
48  
49  	/***
50  	 * Create a new instance of this class.
51  	 */
52  	private Password() {
53  		super();
54  	}
55  
56  	/***
57  	 * Prefix of obfuscated login+password string.
58  	 */
59  	public static final String OBFUSCATE_STR = "OBF|";
60  
61  	/***
62  	 * This method change the specific string into another one more difficult to
63  	 * read
64  	 * 
65  	 * @param s
66  	 *          the original string.
67  	 * @return the obfuscated string.
68  	 */
69  	public static String obfuscate(String s) {
70  		StringBuffer buf = new StringBuffer();
71  		byte[] b = s.getBytes();
72  
73  		synchronized (buf) {
74  			buf.append(OBFUSCATE_STR);
75  			for (int i = 0; i < b.length; i++) {
76  				byte b1 = b[i];
77  				byte b2 = b[s.length() - (i + 1)];
78  				int i1 = b1 + b2 + 127;
79  				int i2 = b1 - b2 + 127;
80  				int i0 = i1 * 256 + i2;
81  				String x = Integer.toString(i0, 36);
82  
83  				switch (x.length()) {
84  				case 1:
85  					buf.append('0');
86  					break;
87  				case 2:
88  					buf.append('0');
89  					break;
90  				case 3:
91  					buf.append('0');
92  					break;
93  				default:
94  					buf.append(x);
95  				}
96  			}
97  			return buf.toString();
98  		}
99  	}
100 
101 	/***
102 	 * This method return the hided string behind the specified string. If the
103 	 * string is not hidded, it returns it.
104 	 * 
105 	 * @param s
106 	 *          the hided string.
107 	 * @return the hided string behind the specified string. If the string is not
108 	 *         hidded, it returns it.
109 	 */
110 	public static String deobfuscate(String s) {
111 		if (!s.startsWith(OBFUSCATE_STR)) {
112 			// no need to deobfuscate
113 			return s;
114 		}
115 
116 		String x = s.substring(OBFUSCATE_STR.length());
117 		final byte[] b = new byte[(s.length() - OBFUSCATE_STR.length()) / 2];
118 		int l = 0;
119 		for (int i = 0; i < b.length; i += 4) {
120 			x = x.substring(i, i + 4);
121 			int i0 = Integer.parseInt(x, 36);
122 			int i1 = i0 / 256;
123 			int i2 = i0 % 256;
124 			b[l++] = (byte) ((i1 + i2 - 254) / 2);
125 		}
126 		return new String(b, 0, l);
127 	}
128 }