On Wed, Mar 13, 2013 at 4:33 PM, NabbleReallySucks
<[email protected]> wrote:
> So I am using AesCipherService to encrypt passwords when a user registers. In
> it, I generate a Key/salt and use it to encrypt. I then convert to base 64
> and store it in the database.
>
> Works great. But I can't see how to hook it up when we try to login. So
> right now credentials won't match.
>
> I set my Realms credentials matcher to
>
> <bean id="hashMatcher"
> class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
> <property name="hashAlgorithmName" value="SHA-256"/>
> <property name="hashIterations" value="1024"/>
> <property name="storedCredentialsHexEncoded" value="false"/>
> </bean>
>
> Should it instead be
>
> <bean id="hashMatcher"
> class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
> <property name="hashAlgorithmName" value="AES"/>
> <property name="storedCredentialsHexEncoded" value="false"/>
> </bean>
>
> And would it need hashIterations to be set, and the uses salt boolean be
> set?
The HashedCredentialsMatcher is used only for Hashing algorithms (also
called Message Digest algorithms), like SHA-2 (SHA-256, SHA-384,
SHA-512, etc), MD5, etc. AES is a block cipher algorithm and is not
considered a hashing algorithm, so you can't use the
HashedCredentialsMatcher here.
I'm not entirely sure of your security requirements, but if you use
Shiro's PasswordService and PasswordMatcher, you'll have much easier
results. For example:
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.PasswordMatcher">
<property name="passwordService" ref="passwordService"/>
</bean>
<bean id="passwordService"
class="org.apache.shiro.authc.credential.DefaultPasswordService">
<property name="hashService">
<bean class="org.apache.shiro.crypto.hash.DefaultHashService">
<property name="generatePublicSalt" value="true"/> <!--
ALWAYS true for user passwords -->
<property name="hashAlgorithmName" value="SHA-512"/>
<property name="hashIterations" value="500000"/> <!-- 500,000 -->
</bean>
</property>
</bean>
<bean id="myRealm" class="...">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
...
</bean>
You can then use the PasswordService in your app:
PasswordService svc = getBean("passwordService");
String hashed = svc.encryptPassword(rawPassword);
//store in database:
user.setPassword(hashed);
user.save();
For all subsequent authentication attempts, Shiro will use the
PasswordMatcher to check the hashed value in the database.
That is all that is required.
However, if you want to AES encrypt the hashed value before it goes to
the database, that's fine, but you'll need to write your own
CredentialsMatcher that knows how to decrypt the encrypted value
first.
For example, you might have a CredentialsMatcher that:
1. decrypts the db value
2. uses the decrypted value and delegates to a PasswordMatcher
instance for the rest of the work (i.e. the decrypted value is the
hashed password).
Again, I don't know your security requirements, but most applications
don't need the extra encryption before storage - the hash is already a
one-way conversion that can't be reversed (but could be theoretically
brute-forced if the database values were ever available to an attacker
- implying they had direct access to the database - but that would
take a really long time for pretty much any attacker that isn't a
nation state).
HTH,
Les