You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Tauren Mills <ta...@groovee.com> on 2011/04/01 03:34:58 UTC

Securing passwords, emails, credit cards, etc.

What are the current best practices on hashing passwords and encrypting
sensitive data like credit card numbers, social security numbers, etc.? I've
looked for documentation and samples, but haven't really found many
resources on using Shiro's cryptography features.

I have a feeling I could be using the Cryptography features much more
effectively. For instance, when a new user signs up, I do the following:
    member.setPassword(new Sha256Hash(dto.getPassword()).toHex());

I require that all passwords are at least 8 characters long and include
characters from at least three of the following four categories: lowercase
letters, uppercase letters, numbers, and symbols. After reading the
following article, I'm worried about just how easy it would be to crack
these password hashes:
    http://codahale.com/how-to-safely-store-a-password/

I seem to recall some talk of performing multiple hashes on things to secure
them better? Any links to this resource?

Also, I have some sensitive data (credit card, SSN, etc.) that I want to
encrypt before storing in the database. I'm considering adding BouncyCastle
to my application, but perhaps I can use existing Shiro features. It looks
like Shiro can do AES encryption based on this article:
    http://www.infoq.com/articles/apache-shiro

I'd really appreciate any pointers on how to use Shiro to tighten up the
*storage* of sensitive data, as well as when it is better to use other tools
such as BouncyCastle.

Thanks,
Tauren

Re: Securing passwords, emails, credit cards, etc.

Posted by Tauren Mills <ta...@tauren.com>.
>
> 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.


Looks useful, I just voted for it.


> > 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.


I might do something like that after maybe 30 days. Those accounts that
haven't already upgraded will receive a 'reset password' email with a link
at that time. I'm not concerned that I've been compromised, I just want
better safeguards in place without imposing on too many users. Of course,
sending emails with reset links has its own set of vulnerabilities to
consider...


> > 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.


Do you have suggestions on where key storage would ideally be? Currently I
include this sort of application-level information in a properties file that
gets loaded by Spring and the values injected into appropriate beans. But
obviously that would mean all keys would be in the same place. And anyone
who has access to the WAR file could easily discover those keys. The
application is hosted on a different server than the database, but if the
app server is hacked, the intruder would have the WAR file and access to a
system that is able to connect to the DB server.

Plus, this means that every developer, system administrator, or personnel
involved in deployments would be able to see these keys. A little social
engineering hacks and someone might share the keys with the bad guys. But
where could they be stored that these same people would not be able to
easily access them? Hard coded into the application? In a database?


> > 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!


I'm debating between just encrypting the entire credit card number and
encrypting either the middle (like my example) or everything except the last
4 digits. Here's my take on the trade-offs:

* Encrypting the entire card seems more secure, as none of the card's digits
is available in clear text. However, my UI will display masked card number
(i.e. ****1111) more frequently than it needs the full card number. Every
time I need to display a masked card number, I'd have to decrypt the full
card number. This will add some additional resource usage, but more
importantly it means the full card number will be resident in the server's
memory more often.

* Keeping the last 4 digits unencrypted means that I can do all normal UI
display actions without needing to decrypt the credit card. The only time
the card would need to be decrypted is when a charge to that account is
going to be made. This might actually be more secure because the full card
number isn't floating around in memory (and possibly swapped to disk or
logged somewhere) nearly as often.

Any insights?

Thanks again,
Tauren

Re: Securing passwords, emails, credit cards, etc.

Posted by Les Hazlewood <lh...@apache.org>.
On Fri, Apr 1, 2011 at 5:11 AM, Tauren Mills <ta...@tauren.com> 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

Re: Securing passwords, emails, credit cards, etc.

Posted by Tauren Mills <ta...@tauren.com>.
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.

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?

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?

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

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.)?

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)?

/**
 * Encrypt a credit card using the provided key. A key can be generated
with
 * a command like this:
 *
 *  AesCipherService cipherService = new AesCipherService();
 *  Key appKey = cipherService.generateNewKey();
 *
 */
public static String[] encryptCreditCard(String card, Key appKey) {
Validate.isTrue(card != null, "Card number must exist");

// Verify card is between 13 and 19 characters long
int length = card.length();
 Validate.isTrue(length > 12 && length < 20, "Card number has invalid
length");

 String[] result = new String[3];
 // Store the first 2 digits and last 4 digits of the card unencrypted
 result[0] = card.substring(0,1);
result[2] = card.substring(length - 5, length-1);
 String cardBody = card.substring(2,length-6);
 AesCipherService cipherService = new AesCipherService();
// cipherService.setKeySize(256);

// encrypt the middle part of the card number
 ByteSource encrypted = cipherService.encrypt(cardBody.getBytes(),
appKey.getEncoded());
 result[1] = encrypted.toBase64();
 return result;
}
public static String decryptCreditCard(String[] encryptedCard, Key appKey) {
Validate.isTrue(encryptedCard != null && encryptedCard.length == 3, "Invalid
card");

AesCipherService cipherService = new AesCipherService();
// cipherService.setKeySize(256);

// decrypt the middle part of the card number
ByteSource decrypted = cipherService.decrypt(encryptedCard[1].getBytes(),
appKey.getEncoded());
 // combine plain text parts with decrypted part to form full card number
 return encryptedCard[0] + decrypted.toString() + encryptedCard[2];
}

Thanks again for your assistance!
Tauren








On Fri, Apr 1, 2011 at 1:19 AM, Les Hazlewood <lh...@apache.org> wrote:

> Hi Tauren,
>
> Please see inline:
>
> > looked for documentation and samples, but haven't really found many
> > resources on using Shiro's cryptography features.
>
> Yep, this is the biggest remaining hole in our documentation.  We've
> worked hard on filling in the gaps thus far - but that needs to be
> flushed out.
>
> > I have a feeling I could be using the Cryptography features much more
> > effectively. For instance, when a new user signs up, I do the following:
> >     member.setPassword(new Sha256Hash(dto.getPassword()).toHex());
>
> You absolutely want to be using a salt when hashing passwords, which
> will make rainbow attacks virtually impossible.  I highly recommend
> multiple iterations (built in to Shiro's hash concept from inception).
>  See my link [1] below for more.
>
> > I require that all passwords are at least 8 characters long and include
> > characters from at least three of the following four categories:
> lowercase
> > letters, uppercase letters, numbers, and symbols. After reading the
> > following article, I'm worried about just how easy it would be to crack
> > these password hashes:
> >     http://codahale.com/how-to-safely-store-a-password/
> > I seem to recall some talk of performing multiple hashes on things to
> secure
> > them better? Any links to this resource?
>
> The article is mostly correct, but unfortunately the author delivered
> it with a bit of sensationalism and FUD.  His points are true under a
> really big assumption:
>
> That the saved passwords and password salts are easily accessible to
> the attacker.  This means that the attacker has broken through your
> firewalls and other network security layers, through or around your
> app (hopefully secured by Shiro!) and database connection, etc and has
> a ton of computing power ready to churn all of your data.  While this
> is a real possibility for security unconscious organizations, it is
> managed fairly well by most competent organizations.  IMO the biggest
> risk for this type of attack is not computational but social (e.g.
> social engineering - getting access to a developer or system engineer
> password when that person has the keys to the kingdom).
>
> Basically, at the end of the day, if you use a sufficiently powerful
> hash algorithm (SHA-256 or SHA-512), use a salt, _and_ use a large
> number of hash iterations, you'll be doing what that article
> advocates.  The key is not that bcrypt is some super fancy hashing
> algorithm, but that it is slow.  Speed is the key - the slower the
> hash operation, the longer it takes the attacker to thwart a system.
> While it doesn't sound like a big deal, it provides orders of
> magnitude more protection if a compute cluster is trying to thrash
> your data concurrently.
>
> This is why Shiro's Hash concept has had the 'iterations' property
> since it was created - using a Shiro Hash (with a salt and
> iterations), you'd be doing exactly as that blog advocates.
>
> > Also, I have some sensitive data (credit card, SSN, etc.) that I want to
> > encrypt before storing in the database.
>
> Shiro's CipherService will be a huge help in this case.  Using the JDK
> default block cipher (AES, Blowfish, etc) config is just plain
> insecure - they don't use things like InitializationVectors by
> default.  The CipherService implementations will do a lot of this
> stuff for you out of the box.
>
> The safest thing to do in this case to the best of my knowledge is to
> have a rolling key mechanism:  use AES 256 encryption (requires the
> JCE Unlimited Strength policy files to be installed) using Shiro's
> AesCipherService.  Every n period of time (hours, days, etc),
> un-encrypt what you currently have with the existing AES 256 key,
> generate a new AES 256 key, and re-encrypt the data and save it.  This
> ensures that there is a known (and limited) window of time for which
> the key is valid.
>
> Rolling keys reduce the ability of any previous key accessors (even
> employees) to access the data at a future time.  I know of a more than
> a few companies that require rolling key policies for sensitive data,
> and it is especially smart to do with super sensitive information (HR
> records, credit cards, etc).  I would think a typical web app store
> front could have n equal to 1 or 2 days or even up to a week.  However
> if the number of records is low (only a few million or less), then the
> computation is cheap/fast and having n equal 1 day (or even less) is a
> pretty good practice IMO.
>
> > I'm considering adding BouncyCastle
> > to my application, but perhaps I can use existing Shiro features.
>
> Yep, BouncyCastle is a complementing mechanism to Shiro - not a
> competitor.  Because Shiro sits on top of standard Java cryptography
> classes, and BouncyCastle can be a JCE provider, Shiro will
> effectively 'sit on top of' BouncyCastle quite nicely.  This isn't
> really necessary in my opinion though - AES 256-bit encryption with
> Initialization Vectors is approaching military-grade encryption
> (without the physical security part since Shiro is all software based)
> and is already available in the JDK by default.  You just need to
> ensure you've installed the JCE Unlimited Strength policy files.
>
> Here are some links that might be of help:
>
> [1] A previous discussion of password hashing techniques/reasoning:
> http://www.mail-archive.com/dev@shiro.apache.org/msg00256.html
> [2] A presentation I gave to the San Francisco JUG on Shiro:
> http://www.youtube.com/watch?v=5ZepGFzYHpE  Jump to the 45:52 mark for
> the Cryptography part of the presentation.
>
> HTH!
>
> Best,
>
> --
> Les Hazlewood
> Founder, Katasoft, Inc.
> Application Security Products & Professional Apache Shiro Support and
> Training:
> http://www.katasoft.com
>

Re: Securing passwords, emails, credit cards, etc.

Posted by Les Hazlewood <lh...@apache.org>.
Hi Tauren,

Please see inline:

> looked for documentation and samples, but haven't really found many
> resources on using Shiro's cryptography features.

Yep, this is the biggest remaining hole in our documentation.  We've
worked hard on filling in the gaps thus far - but that needs to be
flushed out.

> I have a feeling I could be using the Cryptography features much more
> effectively. For instance, when a new user signs up, I do the following:
>     member.setPassword(new Sha256Hash(dto.getPassword()).toHex());

You absolutely want to be using a salt when hashing passwords, which
will make rainbow attacks virtually impossible.  I highly recommend
multiple iterations (built in to Shiro's hash concept from inception).
 See my link [1] below for more.

> I require that all passwords are at least 8 characters long and include
> characters from at least three of the following four categories: lowercase
> letters, uppercase letters, numbers, and symbols. After reading the
> following article, I'm worried about just how easy it would be to crack
> these password hashes:
>     http://codahale.com/how-to-safely-store-a-password/
> I seem to recall some talk of performing multiple hashes on things to secure
> them better? Any links to this resource?

The article is mostly correct, but unfortunately the author delivered
it with a bit of sensationalism and FUD.  His points are true under a
really big assumption:

That the saved passwords and password salts are easily accessible to
the attacker.  This means that the attacker has broken through your
firewalls and other network security layers, through or around your
app (hopefully secured by Shiro!) and database connection, etc and has
a ton of computing power ready to churn all of your data.  While this
is a real possibility for security unconscious organizations, it is
managed fairly well by most competent organizations.  IMO the biggest
risk for this type of attack is not computational but social (e.g.
social engineering - getting access to a developer or system engineer
password when that person has the keys to the kingdom).

Basically, at the end of the day, if you use a sufficiently powerful
hash algorithm (SHA-256 or SHA-512), use a salt, _and_ use a large
number of hash iterations, you'll be doing what that article
advocates.  The key is not that bcrypt is some super fancy hashing
algorithm, but that it is slow.  Speed is the key - the slower the
hash operation, the longer it takes the attacker to thwart a system.
While it doesn't sound like a big deal, it provides orders of
magnitude more protection if a compute cluster is trying to thrash
your data concurrently.

This is why Shiro's Hash concept has had the 'iterations' property
since it was created - using a Shiro Hash (with a salt and
iterations), you'd be doing exactly as that blog advocates.

> Also, I have some sensitive data (credit card, SSN, etc.) that I want to
> encrypt before storing in the database.

Shiro's CipherService will be a huge help in this case.  Using the JDK
default block cipher (AES, Blowfish, etc) config is just plain
insecure - they don't use things like InitializationVectors by
default.  The CipherService implementations will do a lot of this
stuff for you out of the box.

The safest thing to do in this case to the best of my knowledge is to
have a rolling key mechanism:  use AES 256 encryption (requires the
JCE Unlimited Strength policy files to be installed) using Shiro's
AesCipherService.  Every n period of time (hours, days, etc),
un-encrypt what you currently have with the existing AES 256 key,
generate a new AES 256 key, and re-encrypt the data and save it.  This
ensures that there is a known (and limited) window of time for which
the key is valid.

Rolling keys reduce the ability of any previous key accessors (even
employees) to access the data at a future time.  I know of a more than
a few companies that require rolling key policies for sensitive data,
and it is especially smart to do with super sensitive information (HR
records, credit cards, etc).  I would think a typical web app store
front could have n equal to 1 or 2 days or even up to a week.  However
if the number of records is low (only a few million or less), then the
computation is cheap/fast and having n equal 1 day (or even less) is a
pretty good practice IMO.

> I'm considering adding BouncyCastle
> to my application, but perhaps I can use existing Shiro features.

Yep, BouncyCastle is a complementing mechanism to Shiro - not a
competitor.  Because Shiro sits on top of standard Java cryptography
classes, and BouncyCastle can be a JCE provider, Shiro will
effectively 'sit on top of' BouncyCastle quite nicely.  This isn't
really necessary in my opinion though - AES 256-bit encryption with
Initialization Vectors is approaching military-grade encryption
(without the physical security part since Shiro is all software based)
and is already available in the JDK by default.  You just need to
ensure you've installed the JCE Unlimited Strength policy files.

Here are some links that might be of help:

[1] A previous discussion of password hashing techniques/reasoning:
http://www.mail-archive.com/dev@shiro.apache.org/msg00256.html
[2] A presentation I gave to the San Francisco JUG on Shiro:
http://www.youtube.com/watch?v=5ZepGFzYHpE  Jump to the 45:52 mark for
the Cryptography part of the presentation.

HTH!

Best,

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

Re: Securing passwords, emails, credit cards, etc.

Posted by Tauren Mills <ta...@groovee.com>.
Janne,

Thanks for your response and good advice. My codebase dates back to
pre-Shiro days, and I don't think multiple iterations were supported then. I
agree that I absolutely should be using salts and should have from the
start.

Anyway, my question was really meant to be focused on using Shiro for
encrypting and decrypting sensitive data such as credit cards and SSNs and
less on hashing passwords. There is very little documentation on the crypto
features and sample code is basically non-existent as far as I've seen. If
there are any resources I'm not aware of, please let me know.

By the way, I found the conversation that I was looking for about salts and
iterations. I see that most of the suggestions in this thread are now part
of Shiro core, so I'll update my code to use them.
http://shiro-user.582556.n2.nabble.com/Password-Salting-one-salt-per-password-td5490030.html

Of course, when I switch to using salts and iterations, I'll have to figure
out a way to migrate all the passwords stored in my database to continue
working. I can't just change the code and force every user to use the
"forgot password" feature.

Thanks,
Tauren


On Fri, Apr 1, 2011 at 12:06 AM, Janne Jalkanen <ja...@ecyrd.com>wrote:

> I have a feeling I could be using the Cryptography features much more
> effectively. For instance, when a new user signs up, I do the following:
>     member.setPassword(new Sha256Hash(dto.getPassword()).toHex());
>
>
> Use a salt to protect against rainbow tables.  It's just good practice.
>
>  I require that all passwords are at least 8 characters long and include
> characters from at least three of the following four categories: lowercase
> letters, uppercase letters, numbers, and symbols. After reading the
> following article, I'm worried about just how easy it would be to crack
> these password hashes:
>     http://codahale.com/how-to-safely-store-a-password/
>
>
> Well, yes and no. My quick calculation suggested that with your scheme, an
> exhaustive search of the keyspace would take about 400 days on the computer
> cluster the article is on about (assuming SHA-256 is about 30% slower than
> SHA-1 as suggested here http://www.cryptopp.com/benchmarks.html). At a
> minimum of ten characters you would need 4000 years. (This is BTW one of the
> reasons why pass phrases are better than passwords.)
>
> However, this is only true if the attacker has access to the hashes, i.e.
> your database security is compromised. And in such a case you have far worse
> problems than someone cracking your database - they could be injecting their
> own passwords, or installing keyloggers or whatever.
>
> The article you refer to just suggests that you use a very slow hash
> function.
>
> I seem to recall some talk of performing multiple hashes on things to
> secure them better? Any links to this resource?
>
>
> One trick would be to run the hashing several hundred times.  You can do
> that in Shiro automatically. This slows down the required time to perform an
> attack.
>
>
> http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/credential/HashedCredentialsMatcher.html
>
> and the setHashIterations() method.
>
> /Janne
>
>

Re: Securing passwords, emails, credit cards, etc.

Posted by Janne Jalkanen <ja...@ecyrd.com>.
> I have a feeling I could be using the Cryptography features much more effectively. For instance, when a new user signs up, I do the following:
>     member.setPassword(new Sha256Hash(dto.getPassword()).toHex());

Use a salt to protect against rainbow tables.  It's just good practice.

> I require that all passwords are at least 8 characters long and include characters from at least three of the following four categories: lowercase letters, uppercase letters, numbers, and symbols. After reading the following article, I'm worried about just how easy it would be to crack these password hashes:
>     http://codahale.com/how-to-safely-store-a-password/

Well, yes and no. My quick calculation suggested that with your scheme, an exhaustive search of the keyspace would take about 400 days on the computer cluster the article is on about (assuming SHA-256 is about 30% slower than SHA-1 as suggested here http://www.cryptopp.com/benchmarks.html). At a minimum of ten characters you would need 4000 years. (This is BTW one of the reasons why pass phrases are better than passwords.)

However, this is only true if the attacker has access to the hashes, i.e. your database security is compromised. And in such a case you have far worse problems than someone cracking your database - they could be injecting their own passwords, or installing keyloggers or whatever.

The article you refer to just suggests that you use a very slow hash function.

> I seem to recall some talk of performing multiple hashes on things to secure them better? Any links to this resource?

One trick would be to run the hashing several hundred times.  You can do that in Shiro automatically. This slows down the required time to perform an attack.

http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/credential/HashedCredentialsMatcher.html

and the setHashIterations() method.

/Janne