From 3a4a32e654dda7dec5f6908d8f77df028e9cbdd3 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Sun, 22 Oct 2017 15:37:02 -0500 Subject: [PATCH] Remove LdapShaPasswordEncoder from core Issue: gh-4674 --- ...apProviderBeanDefinitionParserTests.groovy | 23 +-- .../LdapAuthenticationProviderConfigurer.java | 31 +-- .../authentication/PasswordEncoderParser.java | 5 - .../security/config/spring-security-5.0.rnc | 2 +- .../security/config/spring-security-5.0.xsd | 6 - ...tionProviderBeanDefinitionParserTests.java | 13 +- .../encoding/LdapShaPasswordEncoder.java | 183 ------------------ .../password/LdapShaPasswordEncoder.java | 10 +- .../PasswordComparisonAuthenticatorTests.java | 8 +- .../PasswordComparisonAuthenticator.java | 65 +++---- .../LdapShaPasswordEncoderTests.java | 134 ------------- 11 files changed, 54 insertions(+), 426 deletions(-) delete mode 100644 core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java delete mode 100644 ldap/src/test/java/org/springframework/security/ldap/authentication/LdapShaPasswordEncoderTests.java diff --git a/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy b/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy index e4586fbe2b..4bfc77ca2a 100644 --- a/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy +++ b/config/src/integration-test/groovy/org/springframework/security/config/ldap/LdapProviderBeanDefinitionParserTests.groovy @@ -1,5 +1,6 @@ package org.springframework.security.config.ldap +import org.springframework.security.crypto.password.NoOpPasswordEncoder import static org.mockito.Mockito.* @@ -88,34 +89,16 @@ class LdapProviderBeanDefinitionParserTests extends AbstractXmlConfigTests { notThrown(AuthenticationException) } - def supportsPasswordComparisonAuthenticationWithHashAttribute() { - xml.'ldap-server'(ldif:'test-server.ldif') - xml.'authentication-manager'{ - 'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') { - 'password-compare'('password-attribute': 'uid', hash: 'plaintext') - } - } - createAppContext('') - def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) - - when: - def auth = am.authenticate(new UsernamePasswordAuthenticationToken("ben", "ben")) - - then: - auth != null - notThrown(AuthenticationException) - - } - def supportsPasswordComparisonAuthenticationWithPasswordEncoder() { xml.'ldap-server'(ldif:'test-server.ldif') xml.'authentication-manager'{ 'ldap-authentication-provider'('user-dn-pattern': 'uid={0},ou=people') { 'password-compare'('password-attribute': 'uid') { - 'password-encoder'(hash: 'plaintext') + 'password-encoder'(ref: 'passwordEncoder') } } } + xml.'b:bean'(id: 'passwordEncoder', 'class' : NoOpPasswordEncoder.name, 'factory-method': 'getInstance') createAppContext('') def am = appContext.getBean(BeanIds.AUTHENTICATION_MANAGER) diff --git a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java index f001216158..03df223539 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java @@ -21,7 +21,7 @@ import java.net.ServerSocket; import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; -import org.springframework.security.authentication.encoding.PasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.authentication.ProviderManagerBuilder; @@ -68,7 +68,7 @@ public class LdapAuthenticationProviderConfigurer passwordEncoder( - PasswordEncoder passwordEncoder) { - this.passwordEncoder = passwordEncoder; - return this; - } - /** * Specifies the {@link org.springframework.security.crypto.password.PasswordEncoder} * to be used when authenticating with password comparison. @@ -410,17 +394,6 @@ public class LdapAuthenticationProviderConfigurer> ENCODER_CLASSES; static { ENCODER_CLASSES = new HashMap>(); ENCODER_CLASSES.put(OPT_HASH_BCRYPT, BCryptPasswordEncoder.class); - ENCODER_CLASSES.put(OPT_HASH_LDAP_SHA, LdapShaPasswordEncoder.class); - ENCODER_CLASSES.put(OPT_HASH_LDAP_SSHA, LdapShaPasswordEncoder.class); } private static final Log logger = LogFactory.getLog(PasswordEncoderParser.class); diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.0.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-5.0.rnc index beda9c117c..012b648f51 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.0.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.0.rnc @@ -7,7 +7,7 @@ start = http | ldap-server | authentication-provider | ldap-authentication-provi hash = ## Defines the hashing algorithm used on user passwords. Bcrypt is recommended. - attribute hash {"bcrypt" | "{sha}" | "{ssha}"} + attribute hash {"bcrypt"} base64 = ## Whether a string should be base64 encoded attribute base64 {xsd:boolean} diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-5.0.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-5.0.xsd index bf71adc097..f8bf5dd19e 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-5.0.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-5.0.xsd @@ -12,8 +12,6 @@ - - @@ -142,8 +140,6 @@ - - @@ -514,8 +510,6 @@ - - diff --git a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java index 4af8ea3eaa..5fcbc7a872 100644 --- a/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/authentication/AuthenticationProviderBeanDefinitionParserTests.java @@ -21,6 +21,7 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio import org.springframework.security.authentication.dao.ReflectionSaltSource; import org.springframework.security.config.BeanIds; import org.springframework.security.config.util.InMemoryXmlApplicationContext; +import org.springframework.security.crypto.password.LdapShaPasswordEncoder; import org.springframework.security.crypto.password.MessageDigestPasswordEncoder; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.AbstractXmlApplicationContext; @@ -119,11 +120,17 @@ public class AuthenticationProviderBeanDefinitionParserTests { @Test public void providerWithShaPasswordEncoderWorks() throws Exception { - setContext(" " - + " " + appContext = new InMemoryXmlApplicationContext( + " " + + " " + + " " + " " + " " - + " " + " "); + + " " + + " " + + " " + + " "); getProvider().authenticate(bob); } diff --git a/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java b/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java deleted file mode 100644 index 9fda7edc24..0000000000 --- a/core/src/main/java/org/springframework/security/authentication/encoding/LdapShaPasswordEncoder.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.authentication.encoding; - -import java.security.MessageDigest; -import java.util.Base64; - -import org.springframework.security.crypto.codec.Utf8; -import org.springframework.util.Assert; - -/** - * A version of {@link ShaPasswordEncoder} which supports Ldap SHA and SSHA (salted-SHA) - * encodings. The values are base-64 encoded and have the label "{SHA}" (or "{SSHA}") - * prepended to the encoded hash. These can be made lower-case in the encoded password, if - * required, by setting the forceLowerCasePrefix property to true. - * - * Also supports plain text passwords, so can safely be used in cases when both encoded - * and non-encoded passwords are in use or when a null implementation is required. - * - * @author Luke Taylor - */ -public class LdapShaPasswordEncoder implements PasswordEncoder { - // ~ Static fields/initializers - // ===================================================================================== - - /** The number of bytes in a SHA hash */ - private static final int SHA_LENGTH = 20; - private static final String SSHA_PREFIX = "{SSHA}"; - private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase(); - private static final String SHA_PREFIX = "{SHA}"; - private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase(); - - // ~ Instance fields - // ================================================================================================ - private boolean forceLowerCasePrefix; - - // ~ Constructors - // =================================================================================================== - - public LdapShaPasswordEncoder() { - } - - // ~ Methods - // ======================================================================================================== - - private byte[] combineHashAndSalt(byte[] hash, byte[] salt) { - if (salt == null) { - return hash; - } - - byte[] hashAndSalt = new byte[hash.length + salt.length]; - System.arraycopy(hash, 0, hashAndSalt, 0, hash.length); - System.arraycopy(salt, 0, hashAndSalt, hash.length, salt.length); - - return hashAndSalt; - } - - /** - * Calculates the hash of password (and salt bytes, if supplied) and returns a base64 - * encoded concatenation of the hash and salt, prefixed with {SHA} (or {SSHA} if salt - * was used). - * - * @param rawPass the password to be encoded. - * @param salt the salt. Must be a byte array or null. - * - * @return the encoded password in the specified format - * - */ - public String encodePassword(String rawPass, Object salt) { - MessageDigest sha; - - try { - sha = MessageDigest.getInstance("SHA"); - sha.update(Utf8.encode(rawPass)); - } - catch (java.security.NoSuchAlgorithmException e) { - throw new IllegalStateException("No SHA implementation available!"); - } - - if (salt != null) { - Assert.isInstanceOf(byte[].class, salt, "Salt value must be a byte array"); - sha.update((byte[]) salt); - } - - byte[] hash = combineHashAndSalt(sha.digest(), (byte[]) salt); - - String prefix; - - if (salt == null) { - prefix = forceLowerCasePrefix ? SHA_PREFIX_LC : SHA_PREFIX; - } - else { - prefix = forceLowerCasePrefix ? SSHA_PREFIX_LC : SSHA_PREFIX; - } - - return prefix + Utf8.decode(Base64.getEncoder().encode(hash)); - } - - private byte[] extractSalt(String encPass) { - String encPassNoLabel = encPass.substring(6); - - byte[] hashAndSalt = Base64.getDecoder().decode(encPassNoLabel.getBytes()); - int saltLength = hashAndSalt.length - SHA_LENGTH; - byte[] salt = new byte[saltLength]; - System.arraycopy(hashAndSalt, SHA_LENGTH, salt, 0, saltLength); - - return salt; - } - - /** - * Checks the validity of an unencoded password against an encoded one in the form - * "{SSHA}sQuQF8vj8Eg2Y1hPdh3bkQhCKQBgjhQI". - * - * @param encPass the actual SSHA or SHA encoded password - * @param rawPass unencoded password to be verified. - * @param salt ignored. If the format is SSHA the salt bytes will be extracted from - * the encoded password. - * - * @return true if they match (independent of the case of the prefix). - */ - public boolean isPasswordValid(final String encPass, final String rawPass, Object salt) { - String prefix = extractPrefix(encPass); - - if (prefix == null) { - return encPass.equals(rawPass); - } - - if (prefix.equals(SSHA_PREFIX) || prefix.equals(SSHA_PREFIX_LC)) { - salt = extractSalt(encPass); - } - else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) { - throw new IllegalArgumentException("Unsupported password prefix '" + prefix - + "'"); - } - else { - // Standard SHA - salt = null; - } - - int startOfHash = prefix.length(); - - String encodedRawPass = encodePassword(rawPass, salt).substring(startOfHash); - - return PasswordEncoderUtils - .equals(encodedRawPass, encPass.substring(startOfHash)); - } - - /** - * Returns the hash prefix or null if there isn't one. - */ - private String extractPrefix(String encPass) { - if (!encPass.startsWith("{")) { - return null; - } - - int secondBrace = encPass.lastIndexOf('}'); - - if (secondBrace < 0) { - throw new IllegalArgumentException( - "Couldn't find closing brace for SHA prefix"); - } - - return encPass.substring(0, secondBrace + 1); - } - - public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) { - this.forceLowerCasePrefix = forceLowerCasePrefix; - } -} diff --git a/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java b/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java index 3e6ce61f4c..8288d801c0 100644 --- a/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java +++ b/crypto/src/main/java/org/springframework/security/crypto/password/LdapShaPasswordEncoder.java @@ -55,7 +55,7 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { // ~ Instance fields // ================================================================================================ - private BytesKeyGenerator saltGenerator = KeyGenerators.secureRandom(); + private BytesKeyGenerator saltGenerator; private boolean forceLowerCasePrefix; @@ -63,6 +63,14 @@ public class LdapShaPasswordEncoder implements PasswordEncoder { // =================================================================================================== public LdapShaPasswordEncoder() { + this(KeyGenerators.secureRandom()); + } + + public LdapShaPasswordEncoder(BytesKeyGenerator saltGenerator) { + if(saltGenerator == null) { + throw new IllegalArgumentException("saltGenerator cannot be null"); + } + this.saltGenerator = saltGenerator; } // ~ Methods diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java index 41f2e277fa..09f37f2228 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticatorTests.java @@ -19,11 +19,12 @@ package org.springframework.security.ldap.authentication; import org.junit.*; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder; -import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.keygen.KeyGenerators; +import org.springframework.security.crypto.password.LdapShaPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.ldap.AbstractLdapIntegrationTests; import org.springframework.ldap.core.DirContextAdapter; @@ -114,7 +115,8 @@ public class PasswordComparisonAuthenticatorTests extends AbstractLdapIntegratio public void testLdapCompareSucceedsWithShaEncodedPassword() { // Don't retrieve the password authenticator.setUserAttributes(new String[] { "uid" }); - authenticator.setPasswordEncoder(new LdapShaPasswordEncoder()); + authenticator.setPasswordEncoder(new LdapShaPasswordEncoder(KeyGenerators.shared(0))); + authenticator.setUsePasswordAttrCompare(false); authenticator.authenticate(ben); } diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java index 9824cf61cc..e791b4ce31 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/PasswordComparisonAuthenticator.java @@ -23,11 +23,12 @@ import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.support.BaseLdapPathContextSource; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder; -import org.springframework.security.authentication.encoding.PasswordEncoder; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.codec.Utf8; +import org.springframework.security.crypto.keygen.KeyGenerators; +import org.springframework.security.crypto.password.LdapShaPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.ldap.SpringSecurityLdapTemplate; import org.springframework.util.Assert; @@ -55,7 +56,7 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic // ~ Instance fields // ================================================================================================ - private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder(); + private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder(KeyGenerators.shared(0)); private String passwordAttributeName = "userPassword"; private boolean usePasswordAttrCompare = false; @@ -116,14 +117,24 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic } private boolean isPasswordAttrCompare(DirContextOperations user, String password) { - Object passwordAttrValue = user.getObjectAttribute(passwordAttributeName); - return passwordEncoder.isPasswordValid(new String((byte[]) passwordAttrValue), - password, null); + String passwordAttrValue = getPassword(user); + return passwordEncoder.matches(password, passwordAttrValue); + } + + private String getPassword(DirContextOperations user) { + Object passwordAttrValue = user.getObjectAttribute(this.passwordAttributeName); + if(passwordAttrValue == null) { + return null; + } + if(passwordAttrValue instanceof byte[]) { + return new String((byte[])passwordAttrValue); + } + return String.valueOf(passwordAttrValue); } private boolean isLdapPasswordCompare(DirContextOperations user, SpringSecurityLdapTemplate ldapTemplate, String password) { - String encodedPassword = passwordEncoder.encodePassword(password, null); + String encodedPassword = passwordEncoder.encode(password); byte[] passwordBytes = Utf8.encode(encodedPassword); return ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, passwordBytes); @@ -135,41 +146,13 @@ public final class PasswordComparisonAuthenticator extends AbstractLdapAuthentic this.passwordAttributeName = passwordAttribute; } - private void setPasswordEncoder(PasswordEncoder passwordEncoder) { + public void setUsePasswordAttrCompare(boolean usePasswordAttrCompare) { + this.usePasswordAttrCompare = usePasswordAttrCompare; + } + + public void setPasswordEncoder(PasswordEncoder passwordEncoder) { Assert.notNull(passwordEncoder, "passwordEncoder must not be null."); this.passwordEncoder = passwordEncoder; - } - - public void setPasswordEncoder(Object passwordEncoder) { - if (passwordEncoder instanceof PasswordEncoder) { - this.usePasswordAttrCompare = false; - setPasswordEncoder((PasswordEncoder) passwordEncoder); - return; - } - - if (passwordEncoder instanceof org.springframework.security.crypto.password.PasswordEncoder) { - final org.springframework.security.crypto.password.PasswordEncoder delegate = (org.springframework.security.crypto.password.PasswordEncoder) passwordEncoder; - setPasswordEncoder(new PasswordEncoder() { - public String encodePassword(String rawPass, Object salt) { - checkSalt(salt); - return delegate.encode(rawPass); - } - - public boolean isPasswordValid(String encPass, String rawPass, Object salt) { - checkSalt(salt); - return delegate.matches(rawPass, encPass); - } - - private void checkSalt(Object salt) { - Assert.isNull(salt, - "Salt value must be null when used with crypto module PasswordEncoder"); - } - }); - this.usePasswordAttrCompare = true; - return; - } - - throw new IllegalArgumentException( - "passwordEncoder must be a PasswordEncoder instance"); + setUsePasswordAttrCompare(true); } } diff --git a/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapShaPasswordEncoderTests.java b/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapShaPasswordEncoderTests.java deleted file mode 100644 index 87cc37f0cf..0000000000 --- a/ldap/src/test/java/org/springframework/security/ldap/authentication/LdapShaPasswordEncoderTests.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ldap.authentication; - -import static org.assertj.core.api.Assertions.*; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder; - -/** - * Tests {@link LdapShaPasswordEncoder}. - * - * @author Luke Taylor - */ -public class LdapShaPasswordEncoderTests { - // ~ Instance fields - // ================================================================================================ - - LdapShaPasswordEncoder sha; - - // ~ Methods - // ======================================================================================================== - - @Before - public void setUp() throws Exception { - sha = new LdapShaPasswordEncoder(); - } - - @Test - public void invalidPasswordFails() { - assertThat(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", - "wrongpassword", null)).isFalse(); - } - - @Test - public void invalidSaltedPasswordFails() { - assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", - "wrongpassword", null)).isFalse(); - assertThat(sha.isPasswordValid("{SSHA}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", - "wrongpassword", null)).isFalse(); - } - - @Test(expected = IllegalArgumentException.class) - public void nonByteArraySaltThrowsException() { - sha.encodePassword("password", "AStringNotAByteArray"); - } - - /** - * Test values generated by 'slappasswd -h {SHA} -s boabspasswurd' - */ - @Test - public void validPasswordSucceeds() { - sha.setForceLowerCasePrefix(false); - assertThat(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", - "boabspasswurd", null)).isTrue(); - assertThat(sha.isPasswordValid("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", - "boabspasswurd", null)).isTrue(); - sha.setForceLowerCasePrefix(true); - assertThat(sha.isPasswordValid("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", - "boabspasswurd", null)).isTrue(); - assertThat(sha.isPasswordValid("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=", - "boabspasswurd", null)).isTrue(); - } - - /** - * Test values generated by 'slappasswd -s boabspasswurd' - */ - @Test - public void validSaltedPasswordSucceeds() { - sha.setForceLowerCasePrefix(false); - assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", - "boabspasswurd", null)).isTrue(); - assertThat(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", - "boabspasswurd", null)).isTrue(); - sha.setForceLowerCasePrefix(true); - assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", - "boabspasswurd", null)).isTrue(); - assertThat(sha.isPasswordValid("{ssha}PQy2j+6n5ytA+YlAKkM8Fh4p6u2JxfVd", - "boabspasswurd", null)).isTrue(); - } - - @Test - // SEC-1031 - public void fullLengthOfHashIsUsedInComparison() throws Exception { - // Change the first hash character from '2' to '3' - assertThat(sha.isPasswordValid("{SSHA}35ro4PKC8jhQZ26jVsozhX/xaP0suHgX", - "boabspasswurd", null)).isFalse(); - // Change the last hash character from 'X' to 'Y' - assertThat(sha.isPasswordValid("{SSHA}25ro4PKC8jhQZ26jVsozhX/xaP0suHgY", - "boabspasswurd", null)).isFalse(); - } - - @Test - public void correctPrefixCaseIsUsed() { - sha.setForceLowerCasePrefix(false); - assertThat("{SHA}ddSFGmjXYPbZC+NXR2kCzBRjqiE=").isEqualTo( - sha.encodePassword("boabspasswurd", null)); - assertThat(sha.encodePassword("somepassword", "salt".getBytes()).startsWith( - "{SSHA}")); - - sha.setForceLowerCasePrefix(true); - assertThat("{sha}ddSFGmjXYPbZC+NXR2kCzBRjqiE=").isEqualTo( - sha.encodePassword("boabspasswurd", null)); - assertThat(sha.encodePassword("somepassword", "salt".getBytes()).startsWith( - "{ssha}")); - - } - - @Test(expected = IllegalArgumentException.class) - public void invalidPrefixIsRejected() { - sha.isPasswordValid("{MD9}xxxxxxxxxx", "somepassword", null); - } - - @Test(expected = IllegalArgumentException.class) - public void malformedPrefixIsRejected() { - // No right brace - sha.isPasswordValid("{SSHA25ro4PKC8jhQZ26jVsozhX/xaP0suHgX", "somepassword", null); - } -}