On Fri, Apr 1, 2011 at 5:11 AM, Tauren Mills <[email protected]> wrote:
> Les,
> Thanks for your ideas, as always! So for password hashing, would you suggest
> using something like this?
> ByteSource appSalt = new SimpleByteSource(APPLICATION_SALT);
> ByteSource userSalt = (new SecureRandomNumberGenerator()).nextBytes();
> ByteSource salt = new SimpleByteSource(ArrayUtils.addAll(appSalt.getBytes(),
> userSalt.getBytes()));
> member.setPassword(new Sha512Hash(dto.getPassword(), salt.getBytes(),
> SALT_ITERATIONS).toBase64());
> member.setSalt(userSalt.toBase64());
> Note that this uses your suggestion to have both an application salt and a
> user salt, but only the user salt gets saved to the database. That way a
> database compromise would still not give the attacker the full salt value.

Yep, this looks great.  Exactly what I do in my own apps :)

Because of this, for a long time I wanted to create a PasswordService
concept in Shiro (maybe something in line with
https://issues.apache.org/jira/browse/SHIRO-213 - I'm not sure) that
encapsulates the logic that you've just laid out and what I'm sure
people replicate from app to app.

I just created a new issue for it here:
https://issues.apache.org/jira/browse/SHIRO-280

Feel free to vote for it if you'd like to see it implemented earlier
rather than later.

> Any suggestions on migrating existing simple Sha256Hash() passwords without
> interrupting user logins? Perhaps have Member.password and
> Member.oldPassword properties. If Member.password is NULL, then test using
> the old method and update Member.password with data if old method is
> successful. If Member.password exists, then test using new method as user
> password has been upgraded already. Or do you have a better idea?

Nope, this sounds pretty good to me as a non-invasive approach.

A more direct approach might be to send 'reset password' emails and
force them to reset their passwords either via a link in the email or
upon the next login (you would null/remove the existing password hash
to ensure it couldn't be used to compromise their account).  This is
definitely invasive in that it requires user interaction, but if you
have any concern at all, it is the safe approach.

> In regards to encrypting sensitive data, I don't yet want to get into the
> complexities of rolling keys, although it sounds like a really great idea.
> I'm only wanting to make sure my application is PCI compliant, it doesn't
> need to provide military grade security. If I choose to not install the JCE
> unlimited strength policy files, I will be limited to using AES-128 at the
> maximum, right?

Yep.  But if you have control of the JVM, it is trivial to install the
files, so I'd do it as a matter of course.  But if you don't control
the JVM installation, then yes, it'd be harder to support anything
above 128 bit encryption.

> When reading the Javadocs, it looks like the IV is prepended to the
> encrypted data and stored with it. It also looks like they are comprised of
> purely random data. I'm curious what your thoughts are in regards to
> including an entity ID into the IV, as suggested in Method 6 in the
> following link. To me it really only sounds useful if you're trying to
> conserve space in the DB.
> http://www.di-mgt.com.au/cryptoCreditcard.html

The only need for this is to save space, which is unnecessary these
days IMO.  Having your IV based on anything that is not random (e.g.
an entity id) weakens the IV to a certain degree.  I'd just stick to
Shiro's defaults of using completely random IVs and accept the extra
few bytes (it's only really 16 bytes for AES - practically a
negligible amount for modern systems).

My opinion for this is that my application users' security is easily
worth the extra disk space it might cost me, especially given the cost
of cheap disks these days, as well as any larger costs (e.g. lawsuits)
that might arise from doing it in a less secure manner.

> Assuming I'm not going for rolling keys, would you suggest having one
> application-wide key that is used to encrypt and decrypt any sensitive
> values? Or would it be better to have different keys for different purposes
> (one for credit cards, another for SSNs, etc.)?

The more keys the better, since a compromise on one doesn't
necessarily mean a compromise of another.  However, if you store all
of your keys in the same place, you can assume that if one is
compromised, they all will be.  In this case, a single key is just as
effective as multiple keys.

> Shiro's certainly made it dead simple to work with crypto. Is there anything
> wrong with the following implementation, or anything you would do to improve
> the way I'm using Shiro's crypto (note I haven't tested the following code
> yet)?

Looks pretty good to me!

Best,

-- 
Les Hazlewood
Founder, Katasoft, Inc.
Application Security Products & Professional Apache Shiro Support and Training:
http://www.katasoft.com

Reply via email to