| | |
| | | */ |
| | | package org.opends.server.extensions; |
| | | |
| | | |
| | | |
| | | import java.security.MessageDigest; |
| | | import java.util.Arrays; |
| | | import java.util.Random; |
| | |
| | | import static org.opends.server.extensions.ExtensionsConstants.*; |
| | | import static org.opends.server.util.StaticUtils.*; |
| | | |
| | | |
| | | |
| | | /** |
| | | * This class defines a Directory Server password storage scheme based on the |
| | | * MD5 algorithm defined in RFC 1321. This is a one-way digest algorithm so |
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** |
| | | * The fully-qualified name of this class. |
| | | */ |
| | | /** The fully-qualified name of this class. */ |
| | | private static final String CLASS_NAME = |
| | | "org.opends.server.extensions.SaltedMD5PasswordStorageScheme"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * The number of bytes of random data to use as the salt when generating the |
| | | * hashes. |
| | | */ |
| | | /** The number of bytes of random data to use as the salt when generating the hashes. */ |
| | | private static final int NUM_SALT_BYTES = 8; |
| | | |
| | | /** The number of bytes MD5 algorithm produces. */ |
| | | private static final int MD5_LENGTH = 16; |
| | | |
| | | |
| | | /** The message digest that will actually be used to generate the MD5 hashes. */ |
| | | private MessageDigest messageDigest; |
| | | |
| | |
| | | /** The secure random number generator to use to generate the salt values. */ |
| | | private Random random; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new instance of this password storage scheme. Note that no |
| | | * initialization should be performed here, as all initialization should be |
| | |
| | | super(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void initializePasswordStorageScheme( |
| | | SaltedMD5PasswordStorageSchemeCfg configuration) |
| | |
| | | throw new InitializationException(message, e); |
| | | } |
| | | |
| | | |
| | | digestLock = new Object(); |
| | | random = new Random(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getStorageSchemeName() |
| | | { |
| | | return STORAGE_SCHEME_NAME_SALTED_MD5; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ByteString encodePassword(ByteSequence plaintext) |
| | | throws DirectoryException |
| | |
| | | return ByteString.valueOfUtf8(Base64.encode(hashPlusSalt)); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ByteString encodePasswordWithScheme(ByteSequence plaintext) |
| | | throws DirectoryException |
| | |
| | | return ByteString.valueOfUtf8(buffer); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean passwordMatches(ByteSequence plaintextPassword, |
| | | ByteSequence storedPassword) |
| | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | // Use the salt to generate a digest based on the provided plain-text value. |
| | | int plainBytesLength = plaintextPassword.length(); |
| | | byte[] plainPlusSalt = new byte[plainBytesLength + saltLength]; |
| | |
| | | return Arrays.equals(digestBytes, userDigestBytes); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean supportsAuthPasswordSyntax() |
| | | { |
| | |
| | | return true; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String getAuthPasswordSchemeName() |
| | | { |
| | | return AUTH_PASSWORD_SCHEME_NAME_SALTED_MD5; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ByteString encodeAuthPassword(ByteSequence plaintext) |
| | | throws DirectoryException |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // Encode and return the value. |
| | | StringBuilder authPWValue = new StringBuilder(); |
| | | authPWValue.append(AUTH_PASSWORD_SCHEME_NAME_SALTED_MD5); |
| | |
| | | return ByteString.valueOfUtf8(authPWValue); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean authPasswordMatches(ByteSequence plaintextPassword, |
| | | String authInfo, String authValue) |
| | |
| | | return false; |
| | | } |
| | | |
| | | |
| | | int plainBytesLength = plaintextPassword.length(); |
| | | byte[] plainPlusSaltBytes = new byte[plainBytesLength + saltBytes.length]; |
| | | plaintextPassword.copyTo(plainPlusSaltBytes); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isReversible() |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ByteString getPlaintextValue(ByteSequence storedPassword) |
| | | throws DirectoryException |
| | |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public ByteString getAuthPasswordPlaintextValue(String authInfo, |
| | | String authValue) |
| | |
| | | throw new DirectoryException(ResultCode.CONSTRAINT_VIOLATION, message); |
| | | } |
| | | |
| | | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean isStorageSchemeSecure() |
| | | { |
| | |
| | | return true; |
| | | } |
| | | } |
| | | |