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