00:00:28.240
An open source love story in three acts. Just like every good three-act play, we will start with a dramatis personae—a listing of the characters.
00:00:34.000
This is Peppercorn. Peppercorn is one of your user's dogs. Like every good dog owner, as soon as they got Peppercorn, they went and changed every single one of their passwords on all of their sites to 'Peppercorn.' You'll see more of Peppercorn later.
00:00:50.000
This is Mallory. Mallory is an attacker who is going to try to compromise us. We'll come back to Mallory as well.
00:01:03.760
And this is me. My name is TJ Schuck. I am on the Internet everywhere—GitHub, Twitter, etc.—as TJ Shuck. That's my name without the dots and spaces. I work at Harvest, and I'm a developer there. We are online at Harvest.com, and we make the world's best time tracking software.
00:01:17.440
If you do anything where you turn your time into money, like work for an agency, a consultancy, do freelance work, or any kind of thing like that, you should check out Harvest.
00:01:32.640
I have a couple of local points of order. First one is this guy. This is my co-worker, Doug Fales. He currently lives in Montana, but he used to live in Boulder, and the tech community here is apparently tight-knit enough that he knows all of you.
00:01:49.040
So, he rattled off a list of 30 names and told me to meet all of you and say hello, which I promptly forgot. If you do know Doug, come say hi to me, and I will relay the message. To clarify, I'm talking about the human; I don't know who the fish is.
00:02:05.680
Also, if you know the fish, come talk to me because I’d like to give him credit. Additionally, like everyone, we are hiring in both tech roles and non-tech roles. So, if you know anyone that’s looking for a job, tell them to check Harvest.com/careers.
00:02:21.760
We also have remote workers; two-thirds of our company is remote, which is great. Now, for this talk, however, it is notable that I am not a security expert. I'm not a cryptanalyst.
00:02:36.240
I coincidentally have a degree in math, but that doesn't help me here at all. There are people who are actually security experts, cryptanalysts, and they have a lot of fancy letters after their names.
00:02:49.280
They get paid a lot of money to know a lot about this stuff that I don’t know. If you have true fundamental security issues, you should hire one of them. You shouldn’t just listen to this talk and think you’re good.
00:03:06.080
But I have users. We heard earlier about how everyone has a users table. By virtue of the fact that I have users, I need to be a security expert because ignorance isn’t an excuse.
00:03:21.840
If you are compromised and something goes wrong, you can’t say, 'We just didn’t know any better.' That is not an excuse, and if you are the weakest link in the chain of a greater vulnerability, everyone will come back to you and blame you.
00:03:36.240
You cannot just push it away as if you didn’t know any better. So, I have to be a security expert by virtue of having users, and you do too.
00:03:50.240
Back to Mallory. Let’s talk about her attack. Good security is about layers. You should have security at different layers—application level security to protect against things like SQL injection, XSS, and CSRF.
00:04:07.200
You should have infrastructure-level security, which means having a secure data center with physical firewalls between your devices. You should update your version of Bash and do all these things. However, to analyze any individual layer of the security structure, we have to assume that all of them have failed.
00:04:22.960
Mallory can just run this and get a database dump of your database because security has failed. So, we need to do something to mitigate that threat.
00:04:37.760
How are we going to authenticate our users? How are we going to store passwords? The easiest option is plain text: just throw them in the database. You have all your users, they log in with their email, and we have their passwords. Great! This is easy, but it's obviously bad.
00:04:56.640
And no one here is doing that, right? Anyone want to admit to it? Someone here is doing it, and they don’t want to admit it, but they’re doing it because they have reasons.
00:05:08.720
They are running an internal application, so they don’t think it matters, or they run a website that’s for ranking animated GIFs. So, if their passwords get compromised, it doesn’t really matter because people just come rank GIFs on their users’ behalf.
00:05:22.560
But it's bad because users reuse passwords. If there is a breach of your database, they’re going to take 'Peppercorn' from your database and then go over to Gmail and try it.
00:05:37.440
They will try it on banking sites, Facebook, and other places and will get into a lot of those accounts because users use their dog's name as their password everywhere. Therefore, we need some way to obfuscate the data of our passwords because we know that this is bad.
00:05:52.960
The easiest way to obfuscate it is just to encrypt it. So, here are our passwords encrypted. This is a very secure encryption scheme known as ROT13. ROT13 is a Caesar cipher with a key of 13.
00:06:05.760
You take all the letters and shift them by 13. So, an 'A' becomes an 'N', a 'B' becomes an 'O', a 'C' becomes a 'P', etc. That is kind of just for illustrative purposes; it could be DES3, AES256, or anything really.
00:06:16.080
The key to all of those things is that they are reversible. You do something to encrypt them, but then you can do something to get them back out again. They have a secret key in this case; it is 13, but oftentimes it's a more complicated key.
00:06:28.320
However, by virtue of there being that secret key and by the fact that they are reversible, and because we've already had our security compromised, the attacker potentially has access to that key as well.
00:06:38.080
It's often stored in application code or on the server as an environment variable. If they are already into your infrastructure, they can get it. It's also important to note that a malicious actor could just be a malicious employee.
00:06:51.040
If there is a public database dump but it is still encrypted, if you have a large enough organization, there is likely someone nefarious enough who could leak that key. So, even having any way to reverse them is bad.
00:07:03.680
The key here is that encryption is reversible; hashing is irreversible. So using the correct vocabulary here helps make this a little easier to talk about: encryption is reversible; hashing is irreversible.
00:07:13.440
If you take 'Peppercorn' and you hash it, you get some value. If you take 'secret1234' and hash it, you get some value. But if you have some value, even as a good actor, not as an attacker, there’s no way to go backward.
00:07:29.200
So that’s the first key of hashing. The important other thing is that it’s deterministic, which means that if you hash 'Peppercorn', you get a value, and if you hash 'Peppercorn' a second time, you get the same value.
00:07:43.680
If you hash 'Peppercorn' a third time, you get the same value. That’s important because we’re using this for authentication. When users come in with their password in plain text, we need some way to verify it with our stored one.
00:07:59.200
By rehashing it, we can get the output and make sure they're the same, thus authenticating them. It's also important that it's deterministic but not obvious.
00:08:12.960
So when you hash 'Peppercorn', you get the same value both times. However, if you trivially change 'Peppercorn' by capitalizing the first letter, you get a completely different output.
00:08:24.960
Also, if you have an output that is trivially different, just like the least significant bit is off by one, it’s probably completely different from 'CapitalPeppercorn'. So, it is deterministic but not obvious.
00:08:41.760
This is now our table with our hashed passwords. They are all hashed throughout all of this with MD5, just because it's the shortest and fits on slides, but it is the same for SHA-1 and other common hashing algorithms.
00:09:02.560
Now we cannot go backwards, so if there is a dump, our passwords are safe. The problem is what we said earlier: that hashing is deterministic. That’s a double-edged sword because the hash of 'Peppercorn' is always the same.
00:09:17.680
This brings us to the concept of rainbow tables. There are three important points of order here: the first one is that this is the best slide that’s ever been made.
00:09:30.080
The second important point of order is I’ve already turned it into a GIF, and I’ll tweet it to you later. The third important point of order is I am not actually going to talk about rainbow tables right now; I'm going to be talking about lookup tables.
00:09:44.000
A rainbow table is kind of just a specialized case of a rainbow lookup table. It’s just, you know, a longer chain than a lookup table, which is a chain of one.
00:09:58.080
If I was going to talk about lookup tables, my slide would look like this—and that’s boring—so instead you get this one. But you have to know I’m talking about lookup tables.
00:10:10.640
If we have this dump of our database and we have all of these things, we can take the hash and put it into a lookup table. Because that hash is always the same, there are precomputed values where we can see that that hash backwards corresponds to this one.
00:10:23.680
As a proof of concept, we can use the world’s best lookup table, which is Google. You can take a hash and just drop it into Google, and you don’t even have to leave the results page.
00:10:36.400
You can just see what that hash is for. So, we need some way to render all of these precomputed tables obsolete. We need some way to defeat the rainbow. So, when you go to Google and dump it in, you can’t find the output.
00:10:48.080
The easiest way is just to change all the inputs. So, we hash 'Peppercorn'; we know we get this output, and we know that existing tables already include that output.
00:11:01.440
So if we just add a string of nonsense and add some entropy, we’re now giving everyone secure passwords by default. Effectively, their passwords are kind of random, and we can see this works.
00:11:14.640
If we look it up in the lookup table, that value has never been hashed before and is now not in Google, so it’s probably not in lookup tables. We did it; we solved password security. We’re awesome!
00:11:28.960
So yes, attackers won’t be able to look up passwords in a table—that is true. However, it is trivially easy to generate new tables because they can get that altering scheme from your application code or from a malicious employee.
00:11:40.880
You’re storing that little bit of entropy somewhere, usually within your auth check. On this MacBook Air, which is not usually known as a powerhouse of a machine, I can compute 13 million SHA-1 hashes every second.
00:11:54.080
So, if you wanted to make your own table, you could do that very quickly. If you had a 25 million word list, it would take two seconds. If you had a 13 million word list, it would take one second.
00:12:08.320
As a proof of concept, this is where Harvest was. We had a table of users with a table of SHA-1 passwords that had a global salt applied to them. It was just some nonsense.
00:12:23.760
So before anyone else could do it, I decided to attack us. I took a dump, and I then used a very accessible way to extract all these passwords from there.
00:12:36.080
I used freely available software that you can download from the internet trivially. There’s a program called Hashcat; that’s what I used, or John the Ripper, which you can install via Homebrew.
00:12:49.680
It’s not hard to do this, and I needed a dictionary—a word list. I got a 25 million word-long list in about five minutes of Googling. It’s really easy to do these attacks.
00:13:02.320
So, I took the dump of our data, and just for the sake of any Harvest customers here, I did my best to anonymize this data. I only looked at the hashes, so though I kind of know a bunch of passwords, I don’t know your password, and a lot of them have probably been changed anyway.
00:13:16.480
And right there in the middle was 'Peppercorn,' along with 80,000 other passwords from the Harvest database that I got in 87 seconds. So, in less than a minute and a half, I extracted 80,000 passwords.
00:13:29.440
This is not even a majority of our users, but it's definitely enough to do significant damage. I could, if I were a true blackhat attacker, go try to log into all those other services and probably get into many of them.
00:13:43.520
It's important to note that in this crack, I also found these passwords that seem like they're secure. But the programs and word lists are really good. People spend a lot of time developing them because they are useful.
00:13:56.000
So, things like leet speak or alternate character substitutions like making 'universe' with numbers will not work anymore. These programs are smart enough to take the word list and swap out 'I's for '1's and that kind of thing.
00:14:08.320
The middle one looks secure too, until you look down at your keyboard. It’s actually a hardware hack; it’s just marching keys. So, there are a lot of those in there too because they are pretty common.
00:14:20.560
The last one, I don't even know. I don’t know where that’s from. It's not some Game of Thrones character that I haven’t heard of, but by virtue of these things being well architected, they can compute shorter passwords.
00:14:32.480
It's probably just by virtue of the length of it that it got cracked. So, we can do one last attempt. Instead of using a global salt, we can do a per-password salt.
00:14:47.440
Instead of hashing every 'Peppercorn' in our table with the same global one, we can give every individual one a new random bit of entropy, which we then store alongside the password hash in our database.
00:15:04.080
Just to note, I got rid of the email column just for space; you would still have that, or else you wouldn’t be able to look up your people. Knowing the salt is not particularly useful to the attacker, because that is where the complexity is coming from.
00:15:18.880
We also need some way to look it up, and what this does is it just makes it a computational problem. Now, instead of having to generate one table for each user, we would have to generate a table for each user.
00:15:29.840
If you had a thousand users, you'd have to generate a thousand tables. If you had a hundred thousand users, you’d have to generate a hundred thousand tables. Doing that per-password salt gives us a little bit more computational complexity.
00:15:43.440
It takes longer for us to crack these passwords. Unfortunately, it is still a pretty good solution for 1976. This is roughly what Unix’s crypt3 does.
00:15:56.560
That was written in 1976, and at the time, a computer could calculate approximately four of these hashes per second. But today we have this—an AMD AX 7990— which costs less than a thousand bucks.
00:16:08.960
So, if you really wanted one, you could probably get one. It can compute 1.5 billion hashes a second.
00:16:20.960
So now, we’re back to being able to generate these tables so trivially that generating one table per user is actually not a problem anymore.
00:16:33.760
The reason that’s the case is that these hashing algorithms are not designed for password security; they’re actually designed typically for file integrity. They provide a way to get checksums of things so you can verify that something is the same over a network transfer.
00:16:50.160
We are just using it improperly to check that that thing, which is the same on both ends, is a password. So, we need a hashing algorithm that’s not designed to be fast like these are, so your network transfers are quicker.
00:17:04.960
We need one that’s designed to be purposefully slow. So, in 1999, Niels Provos and David Mazières published a paper about future adaptable password schemes, where they came up with bcrypt.
00:17:17.520
Now bcrypt hits all of the sweet spots that we’ve already talked about: it’s a one-way hash that’s pre-image resistant, deterministic, and has built-in per-password salts. We’ll see them in a second.
00:17:35.680
The salts are 128 bits long; that's a nice bit of extra entropy. There are also two additional goodies: one is the underlying cipher, which is xBlowfish, based on Blowfish, which is notably an expensive cipher.
00:17:49.760
The EKS stands for expensive key schedule, so it’s even more expensive to get the algorithm up and running. It takes longer to get booted and requires more memory.
00:18:01.680
More RAM kind of mitigates the problem of GPUs, which typically just provide processing power; they don't have RAM along with them. More importantly and interestingly is the notion of adaptive cost.
00:18:16.000
Let's go back to our database dump and look at it again. These are now the passwords hashed with bcrypt. Let’s investigate a bcrypt digest.
00:18:32.960
Ignore the dollar signs; they’re just delimiters and don’t mean anything. This last column, I guess you would call it, of the digest is the actual hash—that’s the checksum that comes out at the end.
00:18:47.520
It’s a 192-bit number encoded in a slightly modified base64. To the left of it is the salt, and instead of being stored in a separate database column, it’s stored right in the digest.
00:19:02.560
So, it’s more convenient, and we don’t have to worry about digest; they’re built into the algorithm. The salts on the far end are just identifiers of the algorithm we used, so this actually came out of Unix’s password schemes.
00:19:18.560
In those schemes, you could have multiple different ones used for different users and also change them over time. 2a just means this is bcrypt. There’s also 2x and 2y, which also mean this is bcrypt for historical reasons.
00:19:34.080
We can talk about them later; they’re not that interesting. But more interesting is the second column, the '10'. What does that cost mean? It means that when we hash 'Peppercorn' with bcrypt with a cost of 10, we get some output.
00:19:48.800
When we hash it again with a cost of 10, we get a different output. We already expected that because of salting. When we hash it a third time with a cost of 14, we get a third output.
00:20:05.840
This is not that interesting until you look at how long it took for each of these to happen. The first one took about 0.06 seconds; the second one also about 0.06 seconds, but the third one took more than a second.
00:20:19.920
What we can do is march forward this cost over time as computers get faster. If we start today with a cost of 12, a year from now we can use a cost of 13, and ten years from now we can use a cost of 25 to keep up with computing speed.
00:20:36.160
Here are the approximate average times it would take to do them on my computer using each of these costs. The thing that you kind of have to balance is the security of being able to have a long cost and the login speed for your users.
00:20:52.960
If you are just doing a login flow and want to increase it by four seconds, that’s kind of bad. But if you increase it by a half second, it might not be noticeable.
00:21:06.160
But if you use basic authentication for your APIs, where every single request comes with a password, then it's a half-second added to every request. You might not want that.
00:21:19.440
So, you do have to balance it for your use case. But what is good is that as computers get faster, you can increase the cost. That’s the future adaptability.
00:21:34.960
So using bcrypt with our set cost, the attack that took 87 seconds before, would now take about 84,000 years to complete. So, that’s a pretty good improvement.
00:21:51.920
Bcrypt is kind of the sweet spot for us because it has been researched for many years, was written by true cryptanalysts, is secure, and has a Ruby library, which we'll cover shortly.
00:22:02.000
Some of you are now thinking in your head, 'Why don’t you just use PBKDF2, or why don’t you use scrypt, or why don’t you use some other password hashing algorithm?' That’s fine, too! You’re probably okay.
00:22:16.480
PBKDF2 is actually the government-approved kind of password hashing scheme, so if you do any government work, I think you have to use that. They are both fine; I think they’re worse, but not significantly worse.
00:22:29.680
If you are already using one of them, you don’t have to convert over. But if you are, you’re already ahead of the class, so don’t worry about it.
00:22:43.120
How can we fix our problem now that we have all of these SHA-1 passwords? We need some way to convert them to bcrypt. If we already have plain text, it’s easy; you can just run a one-shot to do it for you in the background.
00:22:57.920
If we have only the hash, however, it’s irreversible, so we can’t encrypt it with bcrypt. The only time we can get the plain text password is by hooking into our authentication.
00:23:10.480
This is effectively a dumbed-down method of authentication: the password comes in, you use your hashing method, and you check to see if the digest matches the password coming in.
00:23:24.720
We want to get here using bcrypt to do it. The astute readers of the audience will notice the double equals up here that is seemingly comparing the plain text password to the decrypted digest.
00:23:39.680
Some of you are saying, 'I thought bcrypt was irreversible because it’s a hash.' Well, it is! Bcrypt in Ruby overrides the equals operator to make this a comparison.
00:23:52.240
I think this is one of the worst design decisions of bcrypt Ruby, but you will see it happen. If you check this in a pull review, someone will definitely point it out.
00:24:06.640
There is an alias for it that I think is called 'is_password' that you can use, but that’s a little awkward too. I keep meaning to change that, but that’s what it is.
00:24:20.280
So, the easiest way to deal with this is to throw in a pre-filter to our auth flow to convert where we have already converted. We can go through the conversion and then do the bcrypt one.
00:24:34.720
That conversion just checks if we’ve already converted, then bcrypt has a nice valid_hash method that you can use to check if it’s already done; otherwise, we have the plain text and just update it to the bcrypt one.
00:24:50.880
You can do it in the background, and that’s exactly what we did. All of this code is actually taken right out of Harvest when we did the conversion.
00:25:06.240
And these were our users with decrypted passwords over time. You can see there was a big spike initially as all the daily users and Mac app authenticated, and then it kind of trailed off over time.
00:25:20.960
But it got us most of the way there. We still had some remaining ones. That taper though, was unfortunate. But luckily, I had already extracted a bunch of plain text passwords when I attacked the database.
00:25:32.720
So, I just did it a second time, but this time, I had it convert all the passwords, and that got us the rest of the way there.
00:25:48.480
There were a couple of outliers that had actually good passwords that we couldn’t crack or that did not log in during the couple of weeks that we did this for them.
00:26:03.680
We just reset their passwords and sent them an email telling them they had to change their passwords and we received no complaints; it’s not even that scary to do.
00:26:18.960
People won’t freak out. There is one downside to bcrypt: because it’s an expensive algorithm, that means it will increase the CPU load.
00:26:32.640
Particularly as we support basic auth from our API, any API call that’s coming in with a password has to go through the bcrypt overhead.
00:26:48.960
We saw roughly a doubling of our CPU load, but it’s definitely within the realm of acceptability, and the trade-off for the security we got from it was totally worth it.
00:27:01.680
So, just be aware of it, but it’s not that bad. Act one was just the exposition; that’s the boring part. You can learn all of that on your own.
00:27:14.960
Act two is where we add conflict in a three-act play, so we’re going to talk about fat binary gems.
00:27:27.920
As I mentioned earlier, bcrypt has a Ruby library called 'bcrypt-ruby.' You can find it on GitHub at Coda Hale’s bcrypt-ruby.
00:27:43.440
While doing this, I wanted to add a feature to bcrypt-ruby. But when I tried to do that, the tests didn’t run, the dependencies were out of date, and there were missing docs.
00:27:56.760
So, my one pull request turned into a dozen pull requests. If you do that long enough, eventually someone will just say, 'Can you please give this person commit bit?' And then suddenly, I was the maintainer of bcrypt-ruby.
00:28:09.600
There have been three de facto maintainers: Coda Hale is the third one; he wrote it initially, then TenderLove took over, then TMM-1 amongst Gupta took over from GitHub, and now it’s me.
00:28:26.240
That number of 5.8 million is now like 12 million downloads, which is terrifying, but so it goes! Anyway, this is what bcrypt-ruby looks like.
00:28:39.440
But more accurately, this is what bcrypt-ruby looks like. bcrypt-ruby is just a wrapper around C and Java extensions, which is why it’s not natively implemented in Ruby.
00:28:56.480
Ruby is not slow it has been debunked, but it is definitely slower, and your attacker is going to use the fastest thing they have. Your attacker will use a C implementation.
00:29:12.720
Therefore, you don’t want to have unnecessary overhead and lower your costs to make it more speed efficient when your attacker is going to have the advantage.
00:29:25.760
So, it uses the C and Java extensions, which means that when you distribute a gem, you have to distribute it with compiled binaries for the sake of your users.
00:29:38.560
You can see the 315 actually has four versions. The third one’s a native one; the fourth one is the Java version, and the top two are Windows fat binaries.
00:29:54.960
What they are is gems built with support for multiple versions of Ruby—because that’s how Windows plays. However, I’m not a Windows developer so I don’t know much about that.
00:30:07.440
Luckily, when Aman added this to bcrypt-ruby, he wrote this awesome commit message with all these instructions, but he wrote it three years ago.
00:30:23.520
Like anything on the Internet written about computers, it’s three years old; it doesn’t work. Aaron on his blog actually introduced the notion of fat binary gems five years ago.
00:30:36.160
He made the same meme as me five years before me, but anything written about computers on the internet that's five years old definitely doesn’t work.
00:30:49.120
Ultimately, all of this is just wrapping up rake-compiler, which is this library that uses the power of rake to help you cross-compile your gems, so that you can provide these binaries to all these different platforms.
00:31:00.160
However, nice long documentation with all of these instructions—none of that works.
00:31:13.280
The Rails team has this thing that I think is great called the Rails Dev Box, and what it is is a virtual machine that has all of these external dependencies.
00:31:26.640
This means that you are not required to have them on your local machine, such as all of the databases, and the system dependencies for running them.
00:31:39.440
That's very useful so you can run the tests on your local machine without having every possible environment set up. I had a dream to create a rake-compiler dev box that had all the Ruby versions I need.
00:31:52.480
It should have the GCC, JDK, mingw, which is for compiling Windows binaries on UNIX-like machines. Vagrant exists and provides configurable lightweight reproducible portable developer environments.
00:32:05.920
So, I set up a Vagrant box that had everything I needed to compile these binaries. None of that worked.
00:32:18.080
Difficulties can be overcome sometimes, but for now it still is a challenge. This is where I opened up rake-compiler issue number 79.
00:32:31.360
I effectively said I followed all of the documentation as long as possible. I tried to do it in the cleanest environment I could, and nothing worked.
00:32:44.800
In our three-act play, this would be the climax! This is Luis Lavena.
00:32:58.240
Luis is the developer of the One-Click Ruby Installer for Windows. By working on all of this stuff for Ruby on Windows, he is also a member of the Ruby Core Team.
00:33:11.680
By virtue of both of these things, he was voted a Ruby hero in 2010. More importantly, he is the developer of rake-compiler.
00:33:22.560
After I opened up that issue on rake-compiler, he opened up rake-compiler dev box issue/pull request number two.
00:33:33.680
He dropped on me triple hearts—not once, not twice, not three times, but four times! But here’s the problem.
00:33:47.680
This was a great pull request and everything, but I’m twelve hearts in the hole. I need you guys to help me!
00:34:02.480
Please pull out your devices and tweet at Luis right now three hearts. Additionally, if you are on a Mac—on Mavericks or later—hit control + command + space to get all the fancy emoji!
00:34:15.520
So go to town on Luis! I’ll wait. Thank him for being a great OSS contributor and maintainer. He truly is the best.
00:34:29.680
While you’re doing that to half of you, I want to encourage you to find your Luis. Thank the person that has helped you to do things that are often too hard for you to figure out on your own.
00:34:43.520
But more importantly, cooperate with them. Thinking is easy, but actually collaborating can be a lot of fun and very rewarding.
00:34:55.680
Luis lives in Argentina and Paris, splitting his time between them. It’s nice to see global collaboration.
00:35:07.680
To the other half of you who are already maintaining giant libraries or are already a mentor of some way, I encourage you to be the Luis you wish to see in the world.
00:35:22.480
While it’s easy to get frustrated when someone comes in with the same issue you’ve seen a hundred times, consider that the problem might be the documentation.
00:35:35.760
Rewrite your docs to be more friendly to people, or just be supportive of them when they open up usage issues.
00:35:49.040
I know a lot of people don’t like GitHub for usage support, but you can be friendly to people. So, what have we learned today?
00:36:02.560
Number one: just use bcrypt. If you're not already doing it, you should!
00:36:14.560
Come find me afterward; we’ll cry, we’ll hug, and we’ll convert our passwords. Number two: distribute a dev box.
00:36:29.760
If you have any kind of complicated library you’re shipping, make it easier for others to run it by distributing a dev box.
00:36:42.080
Alternatively, if you make or maintain a gem that has extensions, try rake-compiler devbox; it’ll make your life a lot easier.
00:36:57.680
Most importantly, I want to encourage you to release, collaborate, and iterate. With that, I’m TJ Schuck. Thank you!
00:37:18.320
I have 52 seconds for questions. How far will that adaptive cost value scale? Was the question? Potentially endlessly.
00:37:31.040
It's just an integer that you pass in. So, as time marches on you could raise that cost to a hundred or a thousand. Something tells me that will no longer be our problem.
00:37:45.760
In our lifetimes, we might hit 20, but even still, it operates adding up the cost factor in exponents.
00:38:00.560
Also, like Moore's Law, computers are keeping up. Does anyone have anything else?
00:38:11.040
Yes.
00:38:24.800
Did we have any min or max values on the password field in our database? Yes, now we do.
00:38:37.440
But Harvest is actually a decently old Rails app; it was written before Rails 1.0. I think it launched in 2006, when we were all terrible at the Internet.
00:38:50.560
So, I think our password restrictions were much looser then, and as time has gone on they’ve gotten stricter.
00:39:00.960
But legacy users have had worse passwords. Today, if you have a Harvest account, you have a more secure password, which is required to be longer and have a little more complexity.
00:39:14.560
But as we saw, that doesn’t necessarily help. So, I encourage users to utilize a password manager like OnePassword or LastPass.
00:39:27.040
But yeah, now we have stricter requirements; it has just been a gradual evolution.
00:39:40.320
What were the passwords I couldn't crack? By definition, no.
00:39:57.840
Looking at that list, there was nothing that was like a 30-character long random string. There were some passwords that were like passphrases like the XKCD comic you’ve seen.
00:40:10.080
That XKCD comic is partly true in a strictly computational sense, but again, these word lists have gotten better. Many tools will combine words in different orders.
00:40:24.160
So, I recommend actually using random passwords. Length is also good, but there was nothing that wasn't expected.
00:40:34.160
Yes.
00:40:46.080
So, the question was about Devise. Many people use Devise. It uses bcrypt; I believe it uses a default cost of 10.
00:40:58.880
But that might be a little low. I think we're at 12 but again it depends on your use case. You can easily set the cost externally.
00:41:12.160
So that Devise can just use that cost under the hood. Also related to Devise is secure password, which is in Rails’ Active Support.
00:41:23.920
It is kind of like a minimal implementation that uses bcrypt. So, if you use either has_secure_password or Devise, you're set.
00:41:35.440
Yes.
00:41:49.520
The question was do I know anyone implementing a gem for two-factor authentication? I don’t offhand.
00:42:01.920
But I wouldn’t be surprised if there’s one; I just don’t know. If you do have a question but you’re too shy to ask, you can find me afterward. I’ll be around. Thank you!