Announcement Announcement Module
Collapse
No announcement yet.
Oracle PL/SQL HMAC_SHA1 question (vs SHA-1 (ShaPasswordEncoder)) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Oracle PL/SQL HMAC_SHA1 question (vs SHA-1 (ShaPasswordEncoder))

    We currently have a pre-existing user repository in our database (Oracle 10g) where we store our users' hashed passwords.

    When we hash the passwords in PL/SQL initially, we use:

    Code:
            ...
    
            vHashingAlgorithm PLS_INTEGER := 2; --PLS_INTEGER 2 == HMAC_SHA1
    
            ...
    
            RETURN DBMS_CRYPTO.Mac(UTL_I18N.string_to_raw(p_password_txt,'AL32UTF8'),  vHashingAlgorithm, p_salt);
    I'm currently trying to implement a Spring Security prototype project (hacking the Spring Social Showcase XML project) to authenticate against our database of existing users/passwords).

    I think I'm very close...

    This is what I'm seeing in the logs when I try to authenticate/login:

    DEBUG: org.springframework.security.web.authentication.Us ernamePasswordAuthenticationFilter - Request is to process authentication
    DEBUG: org.springframework.security.authentication.Provid erManager - Authentication attempt using org.springframework.security.authentication.dao.Da oAuthenticationProvider
    INFO : org.springframework.social.showcase.signin.CustomJ dbcDaoImpl - Getting Info For User: [email protected]
    INFO : org.springframework.social.showcase.signin.CustomJ dbcDaoImpl - org.springframework.social.showcase.signin.LocalSa ltedUser@651127ba: Username: [email protected]; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER
    INFO : org.springframework.social.showcase.signin.CustomJ dbcDaoImpl - createUserDetails is searching for: [email protected], returnUserName: [email protected]
    INFO : org.springframework.social.showcase.signin.LocalSa ltedUser - My salt was requested!!!, returning: 6868699ECACB7365672DE749608CA63F47943456
    INFO : org.springframework.social.showcase.signin.LocalSa ltedUser - My salt was requested!!!, returning: 6868699ECACB7365672DE749608CA63F47943456
    DEBUG: org.springframework.security.authentication.dao.Da oAuthenticationProvider - Authentication failed: password does not match stored value
    DEBUG: org.springframework.security.web.authentication.Us ernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCre dentialsException: Bad credentials


    Here's my configuration in security xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:beans="http://www.springframework.org/schema/beans"
    	xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
    
    	<http pattern="/resources/**" security="none" />
    
    	<http use-expressions="true">
    		<!-- Authentication policy -->
    		<form-login login-page="/signin" login-processing-url="/signin/authenticate" authentication-failure-url="/signin?param.error=bad_credentials" />
    		<logout logout-url="/signout" delete-cookies="JSESSIONID" />
    		<intercept-url pattern="/favicon.ico" access="permitAll" />
    		<intercept-url pattern="/resources/**" access="permitAll" />
    		<intercept-url pattern="/signin/**" access="permitAll" />
    		<intercept-url pattern="/signup/**" access="permitAll" />
    		<intercept-url pattern="/disconnect/facebook" access="permitAll" />
    		<intercept-url pattern="/**" access="isAuthenticated()"  />
    	</http>
    
        <beans:bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
            <beans:property name="userPropertyToUse" value="salt"/>
        </beans:bean>
    	
    	<beans:bean id="jdbcUserService" class="org.springframework.social.showcase.signin.CustomJdbcDaoImpl">
    	    <beans:property name="dataSource" ref="dataSource"></beans:property>
    	    <beans:property name="usersByUsernameQuery">
    	        <beans:value>
    	            select t1.email_addr_desc as "username",
    	                   t2.hashed_passwd as "password",
    	                   1 as "enabled",
    	                   t2.salt as "salt"
    	            from
    	                   table1 t1,
    	                   table2 t2
    	            where  t1.id = t2.id
    	            and    t1.email_addr_desc = ?
    	        </beans:value>
    	    </beans:property>
    	</beans:bean>
    	
    	<authentication-manager alias="authenticationManager">
    		<authentication-provider user-service-ref="jdbcUserService">
    		    <password-encoder ref="passwordEncoder">
    		        <salt-source ref="saltSource"/>
    		    </password-encoder>
    		</authentication-provider>
    	</authentication-manager>
    	
    </beans:beans>

    Here's where I think I'm defining my password encoder in MainConfig.java (using SHA1 by default, right?):

    Code:
    	@Bean(name="passwordEncoder") //overly explicit
    	public ShaPasswordEncoder passwordEncoder() {
    		return new ShaPasswordEncoder();
    	}
    I *believe* my issue is that Spring Security is using SHA-1 and my Oracle hashing algorithm is using HMAC_SHA1?

    I'm not sure where to proceed from here and I'm not seeing any smoking gun statements in the logs either.

    Is there a way I can tell Spring Security to call my hashing function via the injected datasource and use that to compare to what's stored as the hashed_password in the database, vs Spring Security hashing the password itself and then comparing that to what's stored in the database?

    Turning to the experts for some advice/input...

    Thanks in advance.

  • #2
    Code:
    java.lang.Object
      org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider
          org.springframework.security.authentication.dao.DaoAuthenticationProvider
    Can I subclass DaoAuthenticationProvider, wire it in to my application context, and @Override the method:

    Code:
    authenticate(Authentication authentication)
    Would this be a possible solution?

    Comment


    • #3
      Why don't you implement your own PasswordEncoder which could hash the password using whatever logic you desire

      Comment


      • #4
        Brilliant. I didn't even think of that.

        Thanks for your input.. that's a much more elegant approach than what I was currently cobbling together.

        Comment


        • #5
          I've done some experimenting/testing. I have a question:

          When I implement my own PasswordEncoder using:

          Code:
          import org.springframework.security.crypto.password.PasswordEncoder;
          I get the following exception in my logs:

          Code:
          SEVERE: Servlet.service() for servlet appServlet threw exception
          java.lang.IllegalArgumentException: Salt value must be null when used with crypto module PasswordEncoder
          	at org.springframework.util.Assert.isNull(Assert.java:89)
          	at org.springframework.security.authentication.dao.DaoAuthenticationProvider$1.checkSalt(DaoAuthenticationProvider.java:152)

          I can see where this is being thrown:

          Code:
                          private void checkSalt(Object salt) {
                              Assert.isNull(salt, "Salt value must be null when used with crypto module PasswordEncoder");
                          }
          However, if i try to implement the org.springframework.security.providers.encoding.Pa sswordEncoder interface, I get method invocation errors in my logs. I'm assuming this is because it's trying to access protected class methods?

          Code:
          Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0': Cannot resolve reference to bean 'org.springframework.security.authentication.ProviderManager#0' while setting bean property 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authentication.ProviderManager#0': Cannot resolve reference to bean 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Cannot resolve reference to bean 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0' while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
          PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'passwordEncoder' threw exception; nested exception is java.lang.NullPointerException
          	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
          These seem to be the method signatures I could really use:

          http://static.springsource.org/sprin...rdEncoder.html
          Last edited by yamasaki760; Feb 14th, 2013, 03:17 PM.

          Comment


          • #6
            Originally posted by yamasaki760 View Post
            Code:
            import org.springframework.security.crypto.password.PasswordEncoder;
            I get the following exception in my logs:

            Code:
            SEVERE: Servlet.service() for servlet appServlet threw exception
            java.lang.IllegalArgumentException: Salt value must be null when used with crypto module PasswordEncoder
            	at org.springframework.util.Assert.isNull(Assert.java:89)
            	at org.springframework.security.authentication.dao.DaoAuthenticationProvider$1.checkSalt(DaoAuthenticationProvider.java:152)
            This interface does not allow a salt source since the method does not include salt as an argument. It uses the best practice of a secure random salt and includes it in the hashed password.

            Originally posted by yamasaki760 View Post
            However, if i try to implement the org.springframework.security.providers.encoding.Pa sswordEncoder interface, I get method invocation errors in my logs. I'm assuming this is because it's trying to access protected class methods?
            What do the method invocation errors look like?

            Comment


            • #7
              Originally posted by Rob Winch View Post
              This interface does not allow a salt source since the method does not include salt as an argument. It uses the best practice of a secure random salt and includes it in the hashed password.
              When used to generate a new password, I agree.

              However, when I want to authenticate a login attempt, I want to get the salt I have stored in the database for that user, and then try to encrypt the password (using the stored salt in the db) and compare passwords.

              This is the way I'm doing it now. Is there a better approach that doesn't require me passing in the salt? I don't see how I'd be able to do this without first retrieving my stored salt per-user when authenticating logins.




              What do the method invocation errors look like?

              Code:
              Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0': Cannot resolve reference to bean 'org.springframework.security.authentication.ProviderManager#0' while setting bean property 'authenticationManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authentication.ProviderManager#0': Cannot resolve reference to bean 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.authentication.AuthenticationManagerFactoryBean#0': FactoryBean threw exception on object creation; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authenticationManager': Cannot resolve reference to bean 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0' while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
              PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'passwordEncoder' threw exception; nested exception is java.lang.NullPointerException
              	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
              	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)

              Comment


              • #8
                What is the entire stack trace, relevant configuration, and any custom source code

                Comment


                • #9
                  I've attached my relevant configs and source.

                  Thanks again for your time and assistance, I really appreciate it.

                  Comment


                  • #10
                    Here is my stack trace
                    Last edited by yamasaki760; Feb 18th, 2013, 10:34 PM.

                    Comment


                    • #11
                      This error is different than the truncated error posted earlier. Previously there was a NullPointerException causing a problem where as now it appears that the configuration is missing a bean named passwordEncoder. You need to add your custom PasswordEncoder to your bean configuration.

                      Comment


                      • #12
                        Ah, you're right, sorry, I was trying to cleanse my code last night to make it safe for uploading and I grabbed the wrong stack trace.

                        Relevant code and configs are attached, once again (with db config cleansed for security purposes).

                        Comment


                        • #13
                          CustomPasswordEncoder does not handle a null salt which is causing a NPE.

                          Comment


                          • #14
                            Code:
                            salt.toString();
                            d'oh.

                            Thank you for your help. I can't believe I didn't see that.

                            Comment


                            • #15
                              Rob,

                              I was able to finish the prototype last night and it's working properly now.

                              Thanks again for your input, sometimes a second set of eyes can spot the easiest missed mistakes.

                              Comment

                              Working...
                              X