1 20 21 package org.apache.directory.ldapstudio.browser.core.model; 22 23 24 import java.security.MessageDigest ; 25 import java.security.NoSuchAlgorithmException ; 26 import java.security.SecureRandom ; 27 28 import org.apache.directory.ldapstudio.browser.core.BrowserCoreMessages; 29 import org.apache.directory.ldapstudio.browser.core.utils.LdifUtils; 30 import org.apache.directory.ldapstudio.browser.core.utils.UnixCrypt; 31 32 33 public class Password 34 { 35 36 public static final String HASH_METHOD_SHA = "SHA"; 38 public static final String HASH_METHOD_SSHA = "SSHA"; 40 public static final String HASH_METHOD_MD5 = "MD5"; 42 public static final String HASH_METHOD_SMD5 = "SMD5"; 44 public static final String HASH_METHOD_CRYPT = "CRYPT"; 46 public static final String HASH_METHOD_NO = BrowserCoreMessages.model__no_hash; 47 48 public static final String HASH_METHOD_UNSUPPORTED = BrowserCoreMessages.model__unsupported_hash; 49 50 String hashMethod; 51 52 byte[] hashedPassword; 53 54 byte[] salt; 55 56 String trash; 57 58 59 public Password( byte[] password ) 60 { 61 this( LdifUtils.utf8decode( password ) ); 62 } 63 64 65 public Password( String password ) 66 { 67 68 if ( password == null ) 69 { 70 throw new IllegalArgumentException ( BrowserCoreMessages.model__empty_password ); 71 } 72 else if ( password.indexOf( '{' ) == 0 && password.indexOf( '}' ) > 0 ) 73 { 74 hashMethod = password.substring( password.indexOf( '{' ) + 1, password.indexOf( '}' ) ); 75 String rest = password.substring( hashMethod.length() + 2 ); 76 77 if ( HASH_METHOD_SHA.equals( hashMethod ) || HASH_METHOD_MD5.equals( hashMethod ) ) 78 { 79 hashedPassword = LdifUtils.base64decodeToByteArray( rest ); 80 salt = null; 81 } 82 else if ( HASH_METHOD_SSHA.equals( hashMethod ) ) 83 { 84 byte[] hashedPasswordWithSalt = LdifUtils.base64decodeToByteArray( rest ); 85 hashedPassword = new byte[20]; 86 salt = new byte[hashedPasswordWithSalt.length - hashedPassword.length]; 87 split( hashedPasswordWithSalt, hashedPassword, salt ); 88 } 89 else if ( HASH_METHOD_SMD5.equals( hashMethod ) ) 90 { 91 byte[] hashedPasswordWithSalt = LdifUtils.base64decodeToByteArray( rest ); 92 hashedPassword = new byte[16]; 93 salt = new byte[hashedPasswordWithSalt.length - hashedPassword.length]; 94 split( hashedPasswordWithSalt, hashedPassword, salt ); 95 } 96 else if ( HASH_METHOD_CRYPT.equals( hashMethod ) ) 97 { 98 byte[] saltWithPassword = LdifUtils.utf8encode( rest ); 99 salt = new byte[2]; 100 hashedPassword = new byte[saltWithPassword.length - salt.length]; 101 split( saltWithPassword, salt, hashedPassword ); 102 } 103 else 104 { 105 hashMethod = HASH_METHOD_UNSUPPORTED; 109 trash = password; 110 } 112 } 113 else 114 { 115 hashMethod = null; 117 hashedPassword = LdifUtils.utf8encode( password ); 118 salt = null; 119 } 120 } 121 122 123 public Password( String hashMethod, String passwordAsPlaintext ) 124 { 125 126 if ( !( hashMethod == null || HASH_METHOD_NO.equals( hashMethod ) || HASH_METHOD_SHA.equals( hashMethod ) 127 || HASH_METHOD_SSHA.equals( hashMethod ) || HASH_METHOD_MD5.equals( hashMethod ) 128 || HASH_METHOD_SMD5.equals( hashMethod ) || HASH_METHOD_CRYPT.equals( hashMethod ) ) ) 129 { 130 throw new IllegalArgumentException ( BrowserCoreMessages.model__unsupported_hash ); 131 } 132 if ( passwordAsPlaintext == null ) 133 { 134 throw new IllegalArgumentException ( BrowserCoreMessages.model__empty_password ); 135 } 136 137 if ( HASH_METHOD_NO.equals( hashMethod ) ) 139 { 140 hashMethod = null; 141 } 142 this.hashMethod = hashMethod; 143 144 if ( HASH_METHOD_SSHA.equals( hashMethod ) || HASH_METHOD_SMD5.equals( hashMethod ) ) 146 { 147 this.salt = new byte[8]; 148 new SecureRandom ().nextBytes( this.salt ); 149 } 150 else if ( HASH_METHOD_CRYPT.equals( hashMethod ) ) 151 { 152 this.salt = new byte[2]; 153 SecureRandom sr = new SecureRandom (); 154 int i1 = sr.nextInt( 64 ); 155 int i2 = sr.nextInt( 64 ); 156 this.salt[0] = ( byte ) ( i1 < 12 ? ( i1 + '.' ) : i1 < 38 ? ( i1 + 'A' - 12 ) : ( i1 + 'a' - 38 ) ); 157 this.salt[1] = ( byte ) ( i2 < 12 ? ( i2 + '.' ) : i2 < 38 ? ( i2 + 'A' - 12 ) : ( i2 + 'a' - 38 ) ); 158 } 159 else 160 { 161 this.salt = null; 162 } 163 164 if ( HASH_METHOD_SHA.equals( hashMethod ) || HASH_METHOD_SSHA.equals( hashMethod ) ) 166 { 167 this.hashedPassword = digest( HASH_METHOD_SHA, passwordAsPlaintext, this.salt ); 168 } 169 else if ( HASH_METHOD_MD5.equals( hashMethod ) || HASH_METHOD_SMD5.equals( hashMethod ) ) 170 { 171 this.hashedPassword = digest( HASH_METHOD_MD5, passwordAsPlaintext, this.salt ); 172 } 173 else if ( HASH_METHOD_CRYPT.equals( hashMethod ) ) 174 { 175 this.hashedPassword = crypt( passwordAsPlaintext, this.salt ); 176 } 177 else if ( hashMethod == null ) 178 { 179 this.hashedPassword = LdifUtils.utf8encode( passwordAsPlaintext ); 180 } 181 } 182 183 184 public boolean verify( String testPasswordAsPlaintext ) 185 { 186 187 if ( testPasswordAsPlaintext == null ) 188 { 189 return false; 190 } 191 192 boolean verified = false; 193 if ( hashMethod == null ) 194 { 195 verified = testPasswordAsPlaintext.equals( LdifUtils.utf8decode( hashedPassword ) ); 196 } 197 else if ( HASH_METHOD_SHA.equals( hashMethod ) || HASH_METHOD_SSHA.equals( hashMethod ) ) 198 { 199 byte[] hash = digest( HASH_METHOD_SHA, testPasswordAsPlaintext, this.salt ); 200 verified = equals( hash, this.hashedPassword ); 201 } 202 else if ( HASH_METHOD_MD5.equals( hashMethod ) || HASH_METHOD_SMD5.equals( hashMethod ) ) 203 { 204 byte[] hash = digest( HASH_METHOD_MD5, testPasswordAsPlaintext, this.salt ); 205 verified = equals( hash, this.hashedPassword ); 206 } 207 else if ( HASH_METHOD_CRYPT.equals( hashMethod ) ) 208 { 209 byte[] crypted = crypt( testPasswordAsPlaintext, this.salt ); 210 verified = equals( crypted, this.hashedPassword ); 211 } 212 213 return verified; 214 } 215 216 217 public String getHashMethod() 218 { 219 return this.hashMethod; 220 } 221 222 223 public byte[] getHashedPassword() 224 { 225 return hashedPassword; 226 } 227 228 229 public String getHashedPasswordAsHexString() 230 { 231 return LdifUtils.hexEncode( hashedPassword ); 232 } 233 234 235 public byte[] getSalt() 236 { 237 return salt; 238 } 239 240 241 public String getSaltAsHexString() 242 { 243 return LdifUtils.hexEncode( salt ); 244 } 245 246 247 public byte[] toBytes() 248 { 249 return LdifUtils.utf8encode( toString() ); 250 } 251 252 253 public String toString() 254 { 255 StringBuffer sb = new StringBuffer (); 256 257 if ( HASH_METHOD_UNSUPPORTED.equals( hashMethod ) ) 258 { 259 sb.append( trash ); 260 } 261 else if ( HASH_METHOD_CRYPT.equals( hashMethod ) ) 262 { 263 sb.append( '{' ).append( hashMethod ).append( '}' ); 264 sb.append( LdifUtils.utf8decode( salt ) ); 265 sb.append( LdifUtils.utf8decode( hashedPassword ) ); 266 } 267 else if ( hashMethod != null ) 268 { 269 sb.append( '{' ).append( hashMethod ).append( '}' ); 270 if ( salt != null ) 271 { 272 byte[] hashedPasswordWithSaltBytes = new byte[hashedPassword.length + salt.length]; 273 merge( hashedPasswordWithSaltBytes, hashedPassword, salt ); 274 sb.append( LdifUtils.base64encode( hashedPasswordWithSaltBytes ) ); 275 } 276 else 277 { 278 sb.append( LdifUtils.base64encode( hashedPassword ) ); 279 } 280 } 281 else 282 { 283 sb.append( LdifUtils.utf8decode( hashedPassword ) ); 284 } 285 286 return sb.toString(); 287 } 288 289 290 private static void split( byte[] all, byte[] left, byte[] right ) 291 { 292 System.arraycopy( all, 0, left, 0, left.length ); 293 System.arraycopy( all, left.length, right, 0, right.length ); 294 } 295 296 297 private static void merge( byte[] all, byte[] left, byte[] right ) 298 { 299 System.arraycopy( left, 0, all, 0, left.length ); 300 System.arraycopy( right, 0, all, left.length, right.length ); 301 } 302 303 304 private static boolean equals( byte[] data1, byte[] data2 ) 305 { 306 if ( data1 == data2 ) 307 return true; 308 if ( data1 == null || data2 == null ) 309 return false; 310 if ( data1.length != data2.length ) 311 return false; 312 for ( int i = 0; i < data1.length; i++ ) 313 { 314 if ( data1[i] != data2[i] ) 315 return false; 316 } 317 return true; 318 } 319 320 321 private static byte[] digest( String hashMethod, String password, byte[] salt ) 322 { 323 324 byte[] passwordBytes = LdifUtils.utf8encode( password ); 325 MessageDigest digest; 326 try 327 { 328 digest = MessageDigest.getInstance( hashMethod ); 329 } 330 catch ( NoSuchAlgorithmException e1 ) 331 { 332 return null; 333 } 334 335 if ( salt != null ) 336 { 337 digest.update( passwordBytes ); 338 digest.update( salt ); 339 byte[] hashedPasswordBytes = digest.digest(); 340 return hashedPasswordBytes; 341 } 342 else 343 { 344 byte[] hashedPasswordBytes = digest.digest( passwordBytes ); 345 return hashedPasswordBytes; 346 } 347 } 348 349 350 private static byte[] crypt( String password, byte[] salt ) 351 { 352 String saltWithCrypted = UnixCrypt.crypt( password, LdifUtils.utf8decode( salt ) ); 353 String crypted = saltWithCrypted.substring( 2 ); 354 return LdifUtils.utf8encode( crypted ); 355 } 356 357 } 358 | Popular Tags |