001 package org.esupportail.cas.server.util.crypt;
002
003 import jcrypt.jcrypt;
004 import md5.MD5;
005 import md5.MD5Crypt;
006
007 /**
008 * This class offers encryption methods used by handlers encrypting
009 * users' passwords and comparing them to a reference (file or
010 * database).
011 *
012 * @author Jean-Baptiste Daniel <danielj at sourceforge.net>
013 */
014 public abstract class Crypt {
015
016 /**
017 * An array containing the encryptions supported by the module.
018 */
019 private static String[] supportedEncryptions = {
020 "plain",
021 "des",
022 "md5",
023 "pammd5"};
024
025 /**
026 * Tell if an encryption is supported.
027 * @param encryption an encryption
028 *
029 * @return true if the encryption is supported, false otherwise.
030 */
031 public static boolean isEncryptionSupported(final String encryption) {
032 if (encryption.equals("plain")) {
033 return true;
034 }
035 if (encryption.equals("des")) {
036 return true;
037 }
038 if (encryption.equals("md5")) {
039 return true;
040 }
041 if (encryption.equals("pammd5")) {
042 return true;
043 }
044 return false;
045 }
046
047 /**
048 * Compare a password with its encryption using an encryption method.
049 *
050 * @param encryption an encryption method (must be supported)
051 * @param password the password
052 * @param encryptedPassword the encrypted password
053 *
054 * @return true if password matches, false otherwise
055 * @throws Exception when encryption is not supprted.
056 */
057 public static boolean match(
058 final String encryption,
059 final String password,
060 final String encryptedPassword) throws Exception {
061 if (encryption.equals("plain")) {
062 return encryptedPassword.equals(password);
063 }
064 if (encryption.equals("des")) {
065 return matchDES(password, encryptedPassword);
066 }
067 if (encryption.equals("md5")) {
068 return matchMD5(password, encryptedPassword);
069 }
070 if (encryption.equals("pammd5")) {
071 return matchPAMMD5(password, encryptedPassword);
072 }
073 throw new Exception("Unsupported encryption method.");
074 }
075
076 /**
077 * Retrieve the salt of an MD5 encrypted string.
078 *
079 * @param encryptedString an MD5 encrypted string
080 *
081 * @return the salt of the encrypted string, or null on error.
082 */
083 private static String getMD5Salt(final String encryptedString) {
084
085 try {
086 return encryptedString.split("\\$")[2];
087 } catch (Exception e) {
088 return null;
089 }
090 }
091
092 /**
093 * MD5 Encryption of a string using a salt.
094 *
095 * @param password the password to encrypt
096 * @param salt the salt to encrypt with
097 *
098 * @return the encrypted string (null if the salt is null).
099 */
100 private static String cryptMD5(
101 final String password,
102 final String salt) {
103 if (salt == null) {
104 return null;
105 }
106 return MD5Crypt.crypt(password, salt);
107 }
108
109 /**
110 * MD5 comparison.
111 *
112 * This method compares a clear password with a MD5 hash as created
113 * by 'md5sum' or MySQL's 'MD5()'.
114 *
115 * @param password a clear password.
116 * @param encryptedPassword an already encrypted password.
117 *
118 * @return true if password matches, false otherwise.
119 */
120 private static boolean matchMD5(final String password,
121 final String encryptedPassword) {
122 return encryptedPassword.equals(MD5.md5crypt(password));
123 }
124
125 /**
126 * Linux PAM MD5 comparison.
127 *
128 * This method compares a clear password with a Linux PAM / OpenBSD
129 * / FreeBSD compatible md5-encoded password hash.
130 *
131 * @param password a clear password.
132 * @param encryptedPassword an already encrypted password.
133 *
134 * @return true if password matches, false otherwise.
135 */
136 private static boolean matchPAMMD5(final String password,
137 final String encryptedPassword) {
138 return encryptedPassword.equals(cryptMD5(password, getMD5Salt(encryptedPassword)));
139 }
140
141 /**
142 * Retrieve the salt of a DES encrypted string.
143 *
144 * @param encryptedString a DES encrypted string
145 *
146 * @return the salt of the encrypted string, or null on error.
147 */
148 private static String getDESSalt(final String encryptedString) {
149
150 try {
151 return encryptedString.substring(0, 2);
152 } catch (Exception e) {
153 return null;
154 }
155 }
156
157 /**
158 * DES Encryption of a string using a salt.
159 *
160 * @param password the password to encrypt
161 * @param salt the salt to encrypt with
162 *
163 * @return the encrypted string (null if the salt is null).
164 */
165 private static String cryptDES(
166 final String password,
167 final String salt) {
168 if (salt == null) {
169 return null;
170 }
171 return jcrypt.crypt(salt, password);
172 }
173
174 /**
175 * DES comparison.
176 *
177 * @param password a clear password.
178 * @param encryptedPassword an already encrypted password.
179 *
180 * @return true if password matches, false otherwise.
181 */
182 private static boolean matchDES(final String password,
183 final String encryptedPassword) {
184 return encryptedPassword.equals(cryptDES(password,
185 getDESSalt(encryptedPassword)));
186 }
187
188 }
189
190