Cryptographic Hashing with Flask-Bcrypt6:50 with Kenneth Love
Letting users create accounts is great but until we responsibly store the passwords, we really shouldn't open the doors. We'll use the super-strong `bcrypt` library to hash their passwords before the store them so we know our data is secure.
pip install flask-bcrypt
from flask_bcrypt import generate_password_hash instead for newer Python versions
flask.ext.bcrypt- The path where Flask Bcrypt is available.
generate_password_hash()- function to generate a hash from a string. Takes an optional number of rounds of hashing to use. More rounds always makes the process take longer.
check_password_hash()- function to check a hash against a string to see if they match.
The last thing anyone wants to have happen to their service is a hack. 0:00 But with enough time and nefarious hands, it's bound to happen. 0:04 If it does, let's not let it be due to easily cracked passwords. 0:07 We're going to use the bcrypt library, world famous and super strong. 0:11 Under the hood, it uses the Blowfish cipher salt to prevent 0:15 rainbow table attacks and is resistant to brute force attacks. 0:18 To do all of this, we're going to use the flask-bcrypt package. 0:22 If you don't have it at home, install it with pip. 0:25 Before we write the code, let's talk for 0:28 a second about what we mean when we say cryptographic hashing. 0:29 Isn't it the same thing as encryption? 0:33 No, it's not. 0:34 Encryption is what you do when you create a secret message to send to your friend. 0:37 You swap a for m, b for n, c for o, et cetera, throughout your whole message, and 0:40 then they do the opposite to read it. 0:45 You're super spies, with your secret decoder rings. 0:47 Since the message was encrypted, it could be decrypted. 0:50 Encryption can always be reversed if you know the process, or have the correct key. 0:53 Hashing, though, is a process that can't be undone. 0:58 Without going too far into it, hashing involves a hash function that 1:01 will always turn the same input into the same output, while in the same process. 1:04 We're actually using cryptographic hashing, which involves a salt, or 1:09 random data, added to make the input even more different and unique. 1:12 [SOUND] The salt also lets us compare hashes, even if we're in a new process. 1:15 Before you start using this in Flask, 1:19 I actually wanna play with it a bit in the shell. 1:21 So we're gonna be down here. 1:23 Go into Python. 1:26 Let's actually make this a little bit taller. 1:26 Let's bring it all the way up. 1:28 There we go. 1:31 Okay. 1:32 So, I need to import the generate password hash function. 1:33 So let's go ahead from flask.ext.bcrypt. 1:37 See, there's that same pattern. 1:42 Import generate_password_hash. 1:44 'Kay. So this function, as you can probably 1:48 guess from the name, generates the hash that we can store for a password. 1:51 This is different from just generating a bcrypt hash for like other uses. 1:56 Mainly, in that, this function can be used without the concept of a Flask app. 2:00 As far as flask bcrypt is concerned. 2:06 So this one kinda stands alone. 2:09 And you're gonna use it for generating passwords and models, 2:10 which is why they call it, generate password hash. 2:13 If we look at the help for it, [SOUND] then we can see that it takes a, 2:15 a password or a string, I mean, it's a string. 2:20 We don't really care if it's a password or not, but it takes a string. 2:24 And it takes a number of rounds. 2:27 If we don't specify the rounds, the rounds will be 12. 2:29 And the rounds, I always think of it as being the number of times it goes 2:32 through the hashing, like, how many times it goes around the hashing function. 2:35 But, really it's just, to detail the complexity of the hashing. 2:41 Let's not worry about the rounds for right now. 2:45 Let's do, generate_password_hash, and let's give it the password of secret. 2:46 So, like I said, since we don't pass in around, it does 12 of them by default. 2:52 So there we go. 2:56 This gobbledygook here is what our password is. 2:58 This is our hash password. 3:01 So I wanna point out a couple of things here. 3:03 The beginning of the string, there's this $2a$, that is at the beginning of every 3:05 password generated by BCrypt, or sometimes you'll see, I think it's $2y. 3:12 But the $2a$ is much, much more common. 3:17 And then, the number after the $ right here, 3:22 right there, that tells us how many rounds it did. 3:27 Remember I said it was gonna do 12 rounds? 3:29 It did 12 rounds. 3:31 Then we have another $ and then this part here, is actually our hash. 3:32 So some of the beginning kind of explains like what this thing is, I've never seen 3:37 this before, how do I figure out how to hash something else to match it? 3:41 There's how. 3:44 You do it with BCrypt and you do 12 rounds. 3:45 So, I said that by default that it does 12 rounds, so 3:49 what if we gave it another number? 3:51 I'm gonna warn you right now, don't do this too high. 3:53 So, [SOUND] here's the 15. 3:57 Notice that took a bit longer. 4:00 It took a little bit longer to, generate. 4:03 This is one of the amazing things about BCrypt. 4:05 If you're worried about being hacked, 4:08 maybe you're having to deal with being hacked. 4:09 You can actually make it so that the more times a user tries to log in, 4:12 a certain user account is used to try and log in, and the password fails, 4:16 you'll have to write this yourself, but this is the approach. 4:20 So, say they're trying to log into my account, and they've got the username 4:23 kennethlove, which is often my username, and they keep failing the password. 4:26 Every time they fail the password, you increase the rounds. 4:30 So it starts off at 12 and then they fail a couple of times, and then it goes to 13. 4:34 And they fail a few more times, and it goes to 15. 4:38 And they fail a few more times, and it goes to 20. 4:41 Every time that number increases, it takes longer to generate the hash, or 4:43 to check the hash. 4:47 So you're making it to where it does them no good to repeatedly pound against that 4:49 log in, trying to brute force their way through the password, because it takes 4:54 longer and longer and longer and longer to check to see if the password is right. 4:58 And eventually, it's just not worth the time and the effort. 5:03 All right. 5:06 So now let's try something else. 5:07 Let's do hashed_pw is generate_password_hash for 5:10 secret, and we're gonna do the 12 rounds like normal. 5:18 And so how do we check to see if this was the right password or not, okay? 5:22 Well, I've got hashed_pw, right? 5:27 So maybe I could just do hash_pw is equal to generate_password_hash 5:31 of secret, I'm hashing the same password. 5:38 These should match, right? 5:43 They don't. 5:44 This come back as false. 5:45 Now, why? 5:47 Well it comes back as false, because we have this salt that's added in. 5:48 We have this extra bit of random data that we don't know about. 5:51 That little bit of extra weird data makes it that these two things don't pass. 5:55 So even if someone has your salt, they can't necessarily use your salt to log in. 6:00 Those are not your salt, your hash password. 6:05 They can't use the hash password in order to log in because it 6:07 doesn't really mean anything. 6:11 So how do we ever check? 6:12 Well, the way we check is with another 6:13 [NOISE] function which is check_password_ash. 6:18 And check_password_hash knows how to compare the passwords. 6:25 So, let's check this password. 6:28 [SOUND] Check_password_hash, and we put in the hash, 6:31 the hashed_pw first, and then the password that we're trying. 6:35 So, we're gonna try the password secret. 6:40 And it's true. 6:42 That's the right one. 6:44 So excellent. 6:45 This things working. 6:46 Let's go back to models.py and add this in. 6:47
You need to sign up for Treehouse in order to download course files.Sign up