001: /* Copyright 2005 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005: package org.jasig.portal.channels.cusermanager.provider;
006:
007: import java.io.*;
008: import java.util.Date;
009: import java.security.*;
010:
011: import org.jasig.portal.security.provider.AccountStoreFactory;
012:
013: /**
014: * <p>A utility class that demonstrates changing and locking md5 passwords in
015: * the UP_PERSON_DIR table. The program accepts two optional flags <code>-c</code>
016: * causes the user to be created if he/she doesn't exist. The <code>-l</code>
017: * flag causes the specified user's account to be locked.</p>
018: *
019: * copied from uportal package path to correct it for use
020: * @author smb1@cornell.edu
021: * @author Andrew Newman, newman@yale.edu (heavily modified by smb1@cornell.edu)
022: * @version $Revision: 35600 $
023: */
024: class Md5passwd {
025:
026: public static final String ACCOUNTLOCK = "*LCK*";
027:
028: /**
029: * Returns the MD5 encoded password.
030: * @param ProposedPassword
031: * @return
032: * @throws IOException
033: * @throws NoSuchAlgorithmException
034: * @throws SQLException
035: */
036: protected static String encode(String ProposedPassword)
037: throws IOException, NoSuchAlgorithmException {
038:
039: byte[] hash, rnd = new byte[8], fin = new byte[24];
040: Long date = new Long((new Date()).getTime());
041: SecureRandom r = new SecureRandom((date.toString()).getBytes());
042: MessageDigest md = MessageDigest.getInstance("MD5");
043:
044: // Create a password for this user
045: if (!ProposedPassword.equals(ACCOUNTLOCK)) {
046:
047: r.nextBytes(rnd);
048: md.update(rnd);
049:
050: hash = md.digest(ProposedPassword.getBytes());
051: System.arraycopy(rnd, 0, fin, 0, 8);
052: System.arraycopy(hash, 0, fin, 8, 16);
053: } else
054: fin = ACCOUNTLOCK.getBytes();
055:
056: return "(MD5)" + encodeRaw(fin);
057: }// Encode
058:
059: /**
060: * Check entered password against stored password
061: * @param uid
062: * @param EnteredPassword
063: * @return
064: * @throws Exception
065: */
066: protected static boolean verifyPassword(String uid,
067: String EnteredPassword) throws Exception {
068:
069: boolean isauth = false;
070:
071: try {
072:
073: String acct[] = AccountStoreFactory.getAccountStoreImpl()
074: .getUserAccountInformation(uid);
075: if (acct[0] != null && !acct[0].equals("")) {
076:
077: byte[] whole, salt = new byte[8], compare = new byte[16], dgx;
078: whole = decode(acct[0].substring(5));
079:
080: if (whole.length == 24) {
081:
082: System.arraycopy(whole, 0, salt, 0, 8);
083: System.arraycopy(whole, 8, compare, 0, 16);
084: MessageDigest md = MessageDigest.getInstance("MD5");
085: md.update(salt);
086:
087: dgx = md.digest(EnteredPassword.getBytes());
088:
089: int i;
090: for (i = 0; i < dgx.length; i++) {
091: if (dgx[i] != compare[i]) {
092: isauth = false;
093: break;
094: }//if
095:
096: isauth = true;
097: }// for
098:
099: }// if, 24.length
100: }// if !null
101: } catch (Exception e) {
102: throw (e);
103: }
104:
105: return isauth;
106: }// verifyPassword
107:
108: //
109: // This was originally Jonathan B. Knudsen's Example from his book
110: // Java Cryptography published by O'Reilly Associates (1st Edition 1998)
111: //
112:
113: private static String encodeRaw(byte[] raw) {
114: StringBuffer encoded = new StringBuffer();
115: for (int i = 0; i < raw.length; i += 3) {
116: encoded.append(encodeBlock(raw, i));
117: }
118: return encoded.toString();
119: }
120:
121: private static char[] encodeBlock(byte[] raw, int offset) {
122: int block = 0;
123: int slack = raw.length - offset - 1;
124: int end = (slack >= 2) ? 2 : slack;
125: for (int i = 0; i <= end; i++) {
126: byte b = raw[offset + i];
127: int neuter = (b < 0) ? b + 256 : b;
128: block += neuter << (8 * (2 - i));
129: }
130: char[] base64 = new char[4];
131: for (int i = 0; i < 4; i++) {
132: int sixbit = (block >>> (6 * (3 - i))) & 0x3f;
133: base64[i] = getChar(sixbit);
134: }
135: if (slack < 1)
136: base64[2] = '=';
137: if (slack < 2)
138: base64[3] = '=';
139: return base64;
140: }
141:
142: private static char getChar(int sixBit) {
143: if (sixBit >= 0 && sixBit <= 25)
144: return (char) ('A' + sixBit);
145: if (sixBit >= 26 && sixBit <= 51)
146: return (char) ('a' + (sixBit - 26));
147: if (sixBit >= 52 && sixBit <= 61)
148: return (char) ('0' + (sixBit - 52));
149: if (sixBit == 62)
150: return '+';
151: if (sixBit == 63)
152: return '/';
153: return '?';
154: }
155:
156: //
157: // This was originally Jonathan B. Knudsen's Example from his book
158: // Java Cryptography published by O'Reilly Associates (1st Edition 1998)
159: //
160: protected static byte[] decode(String base64) {
161: int pad = 0;
162: for (int i = base64.length() - 1; base64.charAt(i) == '='; i--)
163: pad++;
164: int length = base64.length() * 6 / 8 - pad;
165: byte[] raw = new byte[length];
166: int rawIndex = 0;
167: for (int i = 0; i < base64.length(); i += 4) {
168: int block = (getValue(base64.charAt(i)) << 18)
169: + (getValue(base64.charAt(i + 1)) << 12)
170: + (getValue(base64.charAt(i + 2)) << 6)
171: + (getValue(base64.charAt(i + 3)));
172: for (int j = 0; j < 3 && rawIndex + j < raw.length; j++)
173: raw[rawIndex + j] = (byte) ((block >> (8 * (2 - j))) & 0xff);
174: rawIndex += 3;
175: }
176: return raw;
177: }
178:
179: protected static int getValue(char c) {
180: if (c >= 'A' && c <= 'Z')
181: return c - 'A';
182: if (c >= 'a' && c <= 'z')
183: return c - 'a' + 26;
184: if (c >= '0' && c <= '9')
185: return c - '0' + 52;
186: if (c == '+')
187: return 62;
188: if (c == '/')
189: return 63;
190: if (c == '=')
191: return 0;
192: return -1;
193: }
194:
195: }// eoc
|