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/[email protected]/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
