BCrypt hashes

470 views
Skip to first unread message

Michael van Leest

unread,
Apr 2, 2015, 11:34:54 PM4/2/15
to lu...@googlegroups.com
Does anyone has experience with using bcrypt in Lucee?
It looks like it's not supported out of the box, any pointers are much appreciated!

Kind regards, Michael

Tony Junkes

unread,
Apr 3, 2015, 1:11:47 AM4/3/15
to lu...@googlegroups.com
I use it regularly though it's def not an out of the box feature (that I know of). You have to add the JAR file to your class path and call on it from there. I have example code and a CFC for using it over on Github - https://github.com/cfchef/BCryptCFC. It'll at least get ya started.

Cheers.

Michael van Leest

unread,
Apr 3, 2015, 2:00:36 AM4/3/15
to lu...@googlegroups.com
Thanks tony!

I've just tried it out and dropped the jar in the server lib folder and restarted lucee.
Trying to run your index.cfm, I get the follow error:

Lucee 4.5.1.008 Error (java.lang.UnsupportedClassVersionError)
Messageorg/mindrot/jbcrypt/BCrypt : Unsupported major.minor version 52.0
Causejava.lang.UnsupportedClassVersionError

Any idea what this might be?

Thanks


--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/0bdbc822-d33e-4791-b463-8bc96f491f66%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Michael van Leest

Michael van Leest

unread,
Apr 3, 2015, 2:40:06 AM4/3/15
to lu...@googlegroups.com
The jar is compiled with Java 8. I've created a Java 7 version of jBCrypt 4 and will create a pull request to add that jar for java 7 users.
--
Michael van Leest

Dominic Watson

unread,
Apr 3, 2015, 5:36:29 AM4/3/15
to lu...@googlegroups.com
fwiw, you don't need to drop the jar in your lib directory. If you have it in your source, you can instantiate it with:

bcrypt = CreateObject( 'java', 'org.mindrot.jbcrypt.BCrypt', '/path/to/bcrypt.jar' );




For more options, visit https://groups.google.com/d/optout.



--
Pixl8 Interactive, 3 Tun Yard, Peardon Street, London
SW8 3HT, United Kingdom

T: +44 [0] 845 260 0726 W: www.pixl8.co.uk E: in...@pixl8.co.uk

Follow us on: Facebook Twitter LinkedIn
CONFIDENTIAL AND PRIVILEGED - This e-mail and any attachment is intended solely for the addressee, is strictly confidential and may also be subject to legal, professional or other privilege or may be protected by work product immunity or other legal rules. If you are not the addressee please do not read, print, re-transmit, store or act in reliance on it or any attachments. Instead, please email it back to the sender and then immediately permanently delete it. Pixl8 Interactive Ltd Registered in England. Registered number: 04336501. Registered office: 8 Spur Road, Cosham, Portsmouth, Hampshire, PO6 3EB

Peter Boughton

unread,
Apr 3, 2015, 2:57:16 PM4/3/15
to lu...@googlegroups.com
Another option is my cfPassphrase project, which defaults to using
BCrypt (but also offers PBKDF2 and SCrypt).

http://sorcerersisle.com/projects:cfpassphrase

It has been tested on Lucee 4.5.1 and Java 8, but is also compatible
with Railo, OpenBD and CF9+ and compiled on Java 6.

Provides custom built-in functions, or can be used via createObject.

Currently the BIFs need manual install (copying files) - I'll be doing
the auto-deploy thing once Lucee 5 is in beta.

https://github.com/boughtonp/cfpassphrase/wiki/Installation#lucee--railo

As always, feedback/etc is welcome.

Jamie Jackson

unread,
Apr 3, 2015, 4:42:15 PM4/3/15
to lu...@googlegroups.com
Whichever way you end up using it, be sure to reuse the seed for a while; otherwise, you can eat up entropy and cause big problems during times of concurrent user-registration/password-generation.

I contributed a patch that fixed this for Mura, and my notes are worth a read: https://github.com/blueriver/MuraCMS/pull/1245

Thanks,
Jamie

--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

Peter Boughton

unread,
Apr 3, 2015, 7:03:15 PM4/3/15
to lu...@googlegroups.com
Thanks for the heads up Jamie - I'd seen theoretical discussions of this
happening but not a conclusive/real-world issue.

I'll need to re-read your write-up when I'm less tired, but what sort
of numbers of concurrent requests caused problems?

Michael van Leest

unread,
Apr 3, 2015, 7:09:45 PM4/3/15
to lu...@googlegroups.com
Thanks Jamie.

Looking at your code, you default to 1 hour of seed caching? Does that have any side effects on security? I'm not familiar with bcrypt, yet, so if there might be some implications for caching a seed for x time, than I can live with a longer request for logins.

Kind regards and thanks, Mike

For more options, visit https://groups.google.com/d/optout.


--
Sent from Gmail Mobile

Peter Boughton

unread,
Apr 4, 2015, 7:32:35 AM4/4/15
to lu...@googlegroups.com
Now I'm more awake, I don't think that pull request is right.

Looking at the commit changes, what's being cached/re-used there is the
salt, which should be unique for every hash.
(This then prevents pre-generation of lookup tables, since attackers
must attack each hash individually.)

It is possible to re-generate the salt without re-seeding - the genSalt
in that code is being called only passing the first argument (rounds),
but genSalt can also receive a second argument - a SecureRandom
instance - so providing the same instance should maintain the seed
whilst still providing a new salt.


Mike:
Not sure that's a clear explanation, but if in doubt don't cache at all.
This only affects the generation - i.e. user registration and similar.
Logging in will use the existing hash's salt so isn't affected.

Michael van Leest

unread,
Apr 4, 2015, 12:37:25 PM4/4/15
to lu...@googlegroups.com
All is very clear. Not caching seems the best way and as intended. It's better to choose a algorithm that fit each need and performance than trying to cut corners with one algorithm.

Thanks again
--
You received this message because you are subscribed to the Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jamie Jackson

unread,
Apr 4, 2015, 4:21:45 PM4/4/15
to lu...@googlegroups.com
Here's my take:

Looking at your code, you default to 1 hour of seed caching? Does that have any side effects on security?

Yes, but that's why it's configurable (although I think a case could be made for reducing, but not eliminating, the default span). The idea is that there can be multiple passwords hashed with the same seed, so if someone cracks one hashed password, they can more easily crack the others that were created with the same seed.

Not caching seems the best way and as intended.

From what I understand about BCrypt and SecureRandom, that's not true.

In my app, I get sudden, concurrent, surges of new registrations and password resets. (This happens when tens or hundreds of users virtually arrive at the start of a popular webinar.)

However, as you can see from my test case, it only takes a handful of requests coming at the rate of 1 request per ~2 or so seconds for things to spin out of control.

Also, take a look at this article, which talks about re-seeding periodically (not every time), if I'm reading it correctly.

It's better to choose a algorithm that fit each need and performance than trying to cut corners with one algorithm.

Yes, I think that's the right takeaway. However, I think that cache span (even if it's very short, say 15 or 30 seconds) is often a better option than none at all, or else an unnecessary DoS target could exist. Think of the problem like a weird query whose execution is usually pretty fast, but which increases steeply with every quickly-repeated execution, and how easily that problem could be mitigated by using a cached query (even if the span is short).

It is possible to re-generate the salt without re-seeding - the genSalt
in that code is being called only passing the first argument (rounds),
but genSalt can also receive a second argument - a SecureRandom
instance - so providing the same instance should maintain the seed
whilst still providing a new salt.

IIRC, it's not SecureRandom instantiation, but secureRandom.nextBytes() that consumes entropy (and can cause problems), so I don't think reusing an existing SecureRandom would help.

Thanks,
Jamie

Reply all
Reply to author
Forward
0 new messages