 Hey everybody, this is Brian. Welcome to the 150-second Qt tutorial with C++ and GUI programming. We're going to continue working with the OpenSSL library, and today we're going to focus on the RSA encryption. So just to quickly get everybody up to speed in case you've kind of skimmed through the last two tutorials, because we've had like 40 minutes of me talking in theory, and I just hate that, it's so boring. So we've got our OpenSSL demo, but we've also got this library's folder and inside of it we've got OpenSSL. I have it just built and I'm statically linking all my stuff together. Not a requirement for these, you can link right to the DLL or the SO file. Alright, so also in the OpenSSL demo I have put the keys in here that we've generated from the previous tutorial, and in the actual source code I have actually made two functions called getPublic and getPrivate. It just returns a byte array with the contents. I have to apologize in advance, I did that rather hurriedly off camera because I had to go somewhere, so if we have an error or a boo boo later on in the tutorial, I may have to stop and revisit that real quick. Also we have our header file, which has been fully fleshed out here, and we have got our code file, which is pretty much blank, there's no implementation in there, and that's what we're going to focus on today. Alright, so what we need to do first, maybe if I can find it in my notes here, is we need to initialize and finalize the library, and when I say the library I'm talking the OpenSSL library. So we're going to say, error, load, crypto strings, OpenSSL, add all algorithms is what we want, so we want all the cryptographic algorithms at our disposal, and open SSL. I'm a little razzled because I was playing Eve online, and I joined a corp with a buddy of mine, and of course, if you've ever played Eve, you know how long it can take to travel somewhere. Anyways, right here we're just going to add the config, and then we're going to finalize, so we're just going to clean up envelopes and stuff. Anyways, so I had to travel, it was like 47 jumps, so if you don't know what the game is, you have no idea what I'm talking about, it was traveling 47 different solar systems, it took me like a couple hours to jump. Anyways, I get to the very last one, I'm almost to the home stretch where my corporation is, and I die because I got jumped. Alright, so what we're doing here is we're calling the library initializer, meaning we're loading the error cryptographic strings, so what happens if cryptography fails? We want like a user-friendly way of displaying that. We're loading all the algorithms, and we're loading the OpenSL config. EVP cleanup, I believe that is the envelope cleanup. If you watch the previous tutorials, we talked a little bit about OpenSSL envelopes, where we use what's called an envelope function rather than calling the raw functions themselves. And then we're just freeing those strings from memory. And then we're going to just initialize our library here, and then in the destructor, we'll finalize the library. If you're coming from Java, the initialize and finalize may be a little bit confusing, I apologize for that, it's just whatever I named them. I'm still getting used to this new version of Ubuntu, it kind of messes with me a little bit here. Alright, so first one is getPublicKey from the cubitarray. This is the actual code that we want to work with, right? So what we're going to do here is we're going to, let's say, const care str. There's a lot of... there's a lot of what I want to call it, well, casting. Let's just be honest here, we're just casting back and forth. There's a lot of casting that happens, because we're working with a raw C++ library, and we're working with cute types. So we're going to get the bio. I really honestly don't know what a bio is, I just know that it works. I think it's the bibliography or whatever. New mem buffer. Alright, so we're going to make a void pointer caster, and if this looks like Ancient Egyptian Algebra, we're really just casting. So basically what we're getting here is we're getting a new a bio memory buffer, you can kind of tell from the name here. Not 100,000% sure what bio really stands for in the open SSL libraries, I just know you need to call it. I think it's short for biography or bibliography, however that's pronounced. Bio, set flags. So now we want to set the flags, and we want to give it the bio, handy. Bio, flags. And if somebody out there is going to be kind of like, you know, chastising me, because I don't know what every single little item is, I just want to throw out there that the open SSL libraries are huge. I mean, they're massive and they're very complex. Probably not as massive as like the Ubuntu code base or Windows code base, but it's still more than I'm going to sit there and read in a weekend. So we're going to get our public key now. Notice how we're getting an RSA right here. We're getting a pointer too. So we're going to say our RSA pub key equals, and this is where we're actually going to get the key. Read. And we're going to read the bio. RSA key. Alright, sorry, RSA public key. We're going to give it the bio. We're just going to say no. No. And last but not least, no. And this is where we need to have some sort of rudimentary error handling, if you will. We're just going to say, if not RSA pub key. Oh, that was a screw up if I ever seen it. My throat's like really raw because it's springtime. Well, it's actually early summer. And my allergies are just kicking my butt. Could not load public key. And then we're just going to say error, error string. And we're going to say error, get error handle. And really what that does is you guessed it. That converts the error number into a readable string here. And then we're going to, in production code you probably want to exit the program at this point or throw up some sort of flashy dialogue or do something. But we're just going to return a null pointer basically here. We're going to free that object. And then we're going to return the RSA pub key. Alright. So let's give this a good build, make sure we didn't goof up anything. Alright, good. And now we want to get it from the read file. But in order to read the file, well, we need to, well, you guessed it. Where is it? Where is it right here? Somebody was messaging me. I'm busy. Go away. I said go away. Leave me alone. Alright, there we go. Sorry. Got distracted. Alright, so we're going to say Q byte away. And this is actually pretty simple here. We've probably done this a million times. We're just going to load the file contents. Oops. So simple. I can't type it out. Alright. Hit Chinese food for lunch. Oh my gosh, I'm so stuffed. I cannot keep my eyes open hardly. So you combine the two, you know, the asthma, allergy thing with the Chinese food. And I'm just like ready for a nap. So really all I'm doing here is saying if I can't open it, you know, then we're just going to break out of there or break, just return out of there. Otherwise, we're going to say data equal file.readall. Close the file. And return the data. So really, we're just reading that file into one big byte array here. Larger files, obviously you'd want to do some sort of buffering, but you know, these are pretty small files. So whoops. So let's go up here. I need to get like multiple monitors. I do all this on one monitor and it kind of just messes with me a little bit. I need to get two monitors and have them sync up like magically. That's some horrible spacing. Some guy, I'm not going to name his name, but he was kind of criticizing my videos pretty nastily. He was like, your videos suck. You make too many mistakes. You talk too much. He got to the point where he was sending me private messages instead of just publicly blasting me. I mean, these were getting kind of mean and nasty. What do you mean? What? Read file. What did I do wrong here? Anyways, while I'm trying to fix this and talk at the same time, he's getting kind of mean towards me and I was just like, dude, what is your problem here? Let's see what's wrong with this thing. All right, I've got something other than that going on. No matching function call for Cypher read file. And this is probably exactly what he's talking about, but he was like, you make too many mistakes. Your videos suck. You're too wordy. You talk too much. All right, let's see what's going on with this. Q byte array read file, Q string. Does it think it's not there or something? Hmm. And I was just like, dude, if you think you can do better, why don't you just have it? I'll put this. All right, time to get a little funky here. Conversion, Q file, Q string. It helps if you read the notes. Note, no known conversion for argument one. So this is what happens when I try to type and talk at the same time. There we go. That should fix it. If not, I'll throw the computer crosser. All right, there we go. But he was just getting real mean and nasty. He's like, well, your videos suck and you talk too much and you make too many mistakes and you waste my time with this. And I'm like, if you don't like my videos, bro, don't watch them. And he's like, but they're good videos. And I'm like, what the hell? He's sitting there yelling at me and then you say they're good videos. All right, lost my train of thought complaining about doober. All right, so we've got our public key. Now remember, the public key is something that you would hand out to just anybody. We've got it so that you can grab that straight from the byte array or from a file. And if we're getting it from a file, we're just loading the byte array and handing it to this function. And then getting the, you guessed it, the, oh, lost my train of thought here. Getting the, where is it? There it is, the RSA from this function. So now we're going to load up the private key. Now remember, the private is something, well, you key private. I think we can actually save a bit of time through the magic of copy and paste. These are very similar. We're going to say private key str. And we're going to get the constants data. Or once again, I'm going to make another buffer. We're going to set the flags. We need the name here, private key string. And then we're going to say RSA privkey. And we're going to say RSA read. RSA read bio, what was that again? RSA, I bet you it's private key, isn't it? All right. And then I think it's bio, no, no, no. And then if not private key, could not load. And we're going to say private. So yeah, my brain between trying to keep up with work and trying to keep up with YouTube and Facebook channel and video games is my brain's just fried. We're going to give that build, make sure it screws something up. And then we're going to pretty much the same thing as this. So pretty much all we're doing is we're loading the keys at this point, right? Now I want to kind of flip this around here. And we're going to say, because we want to be able to test this, you know, you can't just take my word for it that this thing actually works. We want to, you know, actually test it. So we're going to say Q byte array and we'll say test private key equal get private key. So all we're doing here is we're getting the private key bytes and throwing it into a byte array. And then we're just going to say Q byte array, test public key. In a production application, you would never do this. This is strictly a test for us to see the functionality of this application and make sure that it's actually working the way we intended. Some would call this unit testing, but this isn't really unit testing. Cypher, we're going to say C wrapper. So we're going to make an instance of our class. Now when we do that, the first thing it's going to do is it's going to call the initializer. And then when it goes out of scope here, it's going to call that finalize. That way we clean up after ourselves. So we're going to say RSA and let's call this public key equal C wrapper public key. And we want to hand it to you guys at the test public key. Now, common mistake at this point is if you hand the public key, the private bytes or the private bytes to the public key, it'll not end well and you'll get all sorts of funky errors that won't make a whole lot of sense. So we want to get the now the private key. Gosh, I'm like hungry for some reason. Just like it's funny because I was just saying I was full and now I'm like suddenly starving. Q byte array. And we're going to say we'll call this plane equal gunslinger followed. If you're wondering what that's from, it's from Stephen King book called the Dark Tower series. The man in black fled into the desert and the gunslinger followed amazing book series, by the way. All right, so we are going to test RSA here. And we're going to add just a Q to bug so we can see what's going on under the hood. Loading keys. All right, so what we're going to do is just we're going to run this real quick. Maybe if I can friggin type, there we go. This is why I don't have a twitch account, guys, because I will cuss the whole time. I realize that it wasn't a cuss, but I almost did. And I know YouTube allows cussing. I just like to be somewhat professional. That's why I say here and talk about video games and my cat. So we just want to make sure that we can actually load these keys before we go any further. Sure enough, loading keys. And then there's our plain text that we're going to encrypt here very soon. We want to do this just to verify that we can actually load those keys because if those keys don't load, if there's some bug in our code so far, nothing else is going to work. I mean, you can do this for 100 years if the key's not there. It just won't work. Now comes the good stuff. We need to encrypt at RSA level and decrypt at RSA level. So we're going to say Q byte array. Oops, int data size. Somebody did email me and say, hey, you know, I've noticed you say oops quite a bit and stuff like that. Did you, you know, have trouble typing? Now what it is is, you know, this stuff's beyond the complexity that I can keep in my head. So I have notes off to the side of the screen. Typically what I'll do is I'll make the application and I'll test it and I know it works. And then I'll actually rewrite all of this in real time for these tutorials. Much easier on me if I could just say, hey, guys, here's the code. Let me explain it to you. But you guys, for whatever reason, like to watch me type. I think people take bets on how many times I say the word oops. So we're just going to get an unsigned care and we're going to say data dot cons data. Now originally what I was doing is I was making many functions, if you will, to get all this data converted into Qt types and then send those Qt types to these encrypt and decrypt functions. And I found that the casting, I was actually losing data. And then, of course, when you're going to encryption, loss of data when you're talking about a key is not a good thing. So yeah, we're just going to do everything right in the function. int RSA ln equal RSA size. Whoops, RSA size. So what we're going to do is we're just going to get the RSA key length here. And that's what RSA size does. The reason for that is, well, you know, the key size is very important in cryptography because it also has to deal with how it's how it's encrypted, how it's padded, how it's blocked, if it's a Cypher block chaining, things like that. We're just going to give it a build, make sure I'm goofed anything up so far. Ignore the heck out of all those warnings. And then we're going to say unsigned care, maybe ED. So yeah, when I do these, I'm like, I'm typing, I'm talking. Whoops. I can't type or talk apparently unsigned. I'm typing, I'm talking, I'm looking at my notes. My phone will be buzzed, the cat will come up and you know, I need like a quiet room, a little safe place where I can, you know, talk and type. So what we're doing here is we're getting an unsigned care called ED or a pointer to and we're doing it based off memory allocation of the RSA length. So basically we're going to say allocate a chunk of memory the same size as the RSA key length. And that is going to be this pointer here right here, unsigned care unsigned care. If I remember correctly does not have an actual length is just a pointer to the beginning and you need to know the length in advance. That's why the size comes into play. All right, so now what we're going to do is we're going to say int result or RSA public encrypt. And then we're going to say the data size unsigned. And this is kind of why I was going to do with, you know, cute types, but it casting sometimes is just not fun for me and you lose data. Bad things happen and then you have all sorts of weird errors and then, you know, you just like forget it. It's just easier to put everything right in that function. All right, so that's where we're actually doing the encryption right here. And let's talk about this really briefly. What we're saying is we're saying RSA public encrypt. So we're using the public key. We're going to give it the size of the data, a pointer to the data. A pointer to the memory allocated, the key, and then we're giving it the padding. The padding is important because that determines whether or not we're padding it, whether or not they're padding it, how they're padding it, how we've padded it, et cetera, et cetera. When in doubt, that is defined up in the header here. Maybe right here. We'll leave it alone. Leave that default. If you feel like just destroying your data, go ahead and play with the padding by all means. And it's int not in. There we go. So now that we've got our result, then what we need to do is check and make sure that we actually had a successful encryption. And if not, then we need to say, hey, buddy, something bad happened. We could probably just grab this guy right here. I love copy and paste. It's like the best invention ever. All right. So then we're going to return the buffer because we're just going to return a blank cubit array if there was an error. So we'll just get a blank buffer. However, if encryption was successful, we will reach here and we will say buffer equal cubit array. In case you're wondering while I'm typing this, reinterpret cast, sorry. Like I said, talking, typing, reading all at the same time, sometimes too much for a little old me. If you're wondering what started down this whole thing, why did I initially start down this? Well, we were using was a button and I was using that personally in projects. And every time I swear, every time there was a patch in Windows or if I switched from Mac to Linux or whatever, it would just have these bizarre errors that were just pissing me off. And it made no sense. So what we're going to do here is we're just going to return the buffer. So all we're doing is we're going to say our buffer or cubit array is just a reinterpret cast of a care pointer. And then we're returning it. So let's go into our little test here. And we are going to say, let's do it here. C wrapper encrypt RSA. And we want our public key. And then we want the plain text. You know, we try to keep our wrapper pretty simple, pretty easy to use. We're going to down here just say Qtabug. Let's make sure we get a build. And let's run it. And you can see, sure enough, there's our plain text. And here is our encrypted hex string. I generally don't like looking at encrypted hex strings. So for display purposes, I usually just say to base 64, just base 64 encode it. That way it's a little easier on the eyes. And if you have to store it somewhere or if you have to shoot it to like a web service or something, it's already base 64 encoded. There we go. So we've had what we believe is a successful encryption. We've had no error messages and things like that. So now what we need to do, you guessed it, we have to decrypt. And decrypting is about as fun as encrypting. So let's go in here. And I think I can actually do most of this. Let me double check with my notes. Let's try it. Let's just be adventurous and save a little bit of typing here. So we've got our buffer. We've got our data length and already it's different. So now I'm going to cry. Okay. Const unsigned data equal. So I had food poisoning. I think I mentioned this. I'm not sure. I swear sometimes I tell you guys way too much about my life. I had food poisoning from a local Arby's here. And it's sad because I love Arby's. It's like so good. But yeah, I'm never going to have Arby's again. And I've been really, I don't know, I've been really cautious about what I eat. And it's just, yeah, it was not fun. It was like a really long, horrible week. All right. So we have got our buffer. We have got our encrypted data, which we're getting out of the const data from the byte array. We're getting our RSA length from the key that we're handing it. Now we need to say unsigned care. And let's call this decrypted bin because that's what's in my notes. Unsigned camera. We could have actually left that as ED. Why don't we do that just for simplicity sake? And then we're going to say RSA private because remember we're going to decrypt with private. It's kind of pointless to do it the other way around unless you're doing, you know, digital signing or something like that. And that's at even how digital signing works. I don't know why I said that. But all right. So we're getting our RSA private decrypt. We're giving it the RSA size key. I'm kind of deviating from my notes. So if this dies a horrible death, we may have to do some typing here. All right. So there's our key. We're going to give it our encrypted data and then the ED and then the key and then the padding. So then we need to check and we could not decrypt. And if we could not decrypt, then we're just going to return a blank buffer. Otherwise, ta-da, we are going to say, let's just comment this out. From raw data. And we're going to say, but yeah, every time I used botan, botan, man, it just really drive me nuts. Ironically, I was working with botan, botan, whatever you want. While I had food poisoning and I was just like, you know what, I'm done. And that's when I just said, I said, I'm done. I'm just going to, you know, start over again. And I did a lot of research and thus I went with open SSL. Let's give us a build. And oh my gosh, there were no error messages. I thought for sure there would be. So let's go in here. And we're going to say, key byte array, decrypted, C wrapper, decrypt RSA. And we want to give it our private key. Remember, you would not hold both these in the same application. And we want to give it the encrypted data. And then we're going to say, Q byte array. Oops, not Q byte array. Sorry Q debug. This is what hunger does to your brain. I was like full when we started this video. Now I'm starving. And I can't think because I'm hungry. So if all goes good, let's give this a save and a build. It should say the man in black fled through the desert. The gunslinger followed a bunch of base 64 coded data. And then the decrypted version. So fingers crossed. And ta-da. So there is our plain text version. Here's our encrypted base 64 encoded version. And there is our RSA decrypted right here. Whoops, this last part. So let's pick this apart a little bit. And I want to do a bit of cleanup just because I'm kind of like that. Let's get rid of my commented stuff. And let's talk about this. So we've got our public and private keys. Remember that the public key is something that you would give out to someone else where the private key is something you would keep to yourself. Encrypt and decrypt are very similar. You have the data basically. And you have a key for the encryption depending on which direction you're sending. You would give somebody your public key. They would encrypt it and they would send you the file or data or whatever it is. And then when you get it, you would decrypt it with your private key. Now, if it was the other way around, meaning you would encrypt it with your private key, send them the file and they would decrypt it with your public key. That's also a possibility. That's kind of how those two work. Now the internals inside of these are pretty similar. You can see how we're basically allocating some memory, allocating some memory, setting up some variables. And then the bulk of the work is done in here called the RSA public encrypt and the RSA private decrypt. Now, if you're going to flip these around, you're going to have to make different functions, meaning if you try giving the encrypt RSA a private key, notice this RSA encrypt right here, it's going to go boom. So let's look at RSA private. Yeah, there's the private encrypt. So I'm just going to comment that so it'll be in there in case somebody tries to do this, so I don't get some hate mail with the private key. And the same down here, RSA private decrypt. So you would want to do the RSA public decrypt if you're decrypting with the public key. Some questions and answers before you really even ask them is couldn't you do like a switch back and forth? Yeah, you could, but it would actually be better and more streamlined if you broke these out into separate functions. So like you would have like encrypt with public key or encrypt with private key and then decrypt with public or decrypt with private, depending on which way you want it to go. I'm just showing you this code as an example and pretty much it's the exact same signature here. I mean, you've just got the, well, let's just go through it. You've got a size, you've got the actual data, which it's kind of different for each one down here, it's the same thing, it's a constant unsigned care, constant unsigned care. And then you've got the ED, which is the memory allocated, the key, whether it's public or private, and then the padding. So it's pretty easy to understand. And then you're just doing some follow-up and saying, hey, did we get a negative one? Because if we did, something went boom, we're going to grab the error string and then return a blank buffer. If it didn't go boom, then we're going to have to cast this into a cute workable type. So you have to do this if you're working with C++ or C. Should note that none of this requires cute. I just wanted to make a wrapper in Cute for OpenSSL because I couldn't find a real easy one to work with. All right, so Throat's getting a little sore because of allergies and I'm really getting hungry. So we're just going to give this another little build and make sure it works. And I think the next video we're going to focus strictly on the AES. I'm not sure if I'm going to do one video or two. AES is a little more complex and a little more time consuming. But as you can see, I mean, we're almost done with our wrapper here. I mean, we really just have to get random bytes, encrypt and decrypt. And then, oh yeah, we should actually do that free RSA. I totally forgot about that. Let me look at this real quick here. Yeah, we weren't done. I thought we were, but we're not. Yeah, let's go. I knew I was forgetting something. That's why I was kind of stalling for time here. RSA free key. So whenever we work with RSA keys, we need to also free them. So let's go into our little main function here. And we're going to say see wrapper free RSA public key and then see wrapper. And there's all sorts of snazzy things that you could do. You could make your own class or whatever. But basically, that's the, what did I do here? You just got to call this RSA free. That way, open SSL library will go in there and free all the resources associated with that key. There's other ways of doing it, but that's the best way, or I should say the open SSL way. And that's the problem with working with a lot of these libraries is that you have to do it kind of their way. Let's give this another rebuild and make sure it runs. Dot, dot, dot, dot, dot. There we go. And still works. All right. Now let's talk troubleshooting. Let's say you've, you've followed all the instructions. You run this and you get the man in black, blah, blah, blah. You get this and then here, instead of the exact same thing as the plain text, you get like just this wad of binary garbage. What do you do? First thing you do, check your keys. Like I said, if you try to give it a public key to decrypt, you're probably going to go boom and you'll need to figure out why. And nine times out of 10, it's just, it's just you're using the wrong function, you know, RSA private decrypt. So you got to use a private key. I almost wish open SSL had like an RSA public RSA private, but instead they just have this RSA. Then they may have public and private. I don't think they do. I didn't see one. So that's a lot of talking. That's the basics of RSA encryption and decryption and how to work with those keys. A couple quick notes. You might want to, if you're going to use this in production code, break these out into probably four functions instead of two. Never, never, never, never, never put the private key inside of the application like this because you can actually use a resource string extractor and literally read the key back and then dump it to a file. So it kind of defeats the point of putting it in there. Some people may get a little fancy and encrypt the key and put the key in there and no, don't do that. Use a proper key exchange. The public key, however, you can more than definitely put the public key in an application very safely because the public key as well. Public, you can give that away to anybody. So by all means, throw the key in the application, do whatever you want to do. That's it for this one. Looking forward to finishing these up because I actually love encryption. We found this helpful and entertaining and educating. Go to Contact, go to the Voidrums Facebook group and join up. There's 600 plus programmers out there, all sorts of walks of life. I shouldn't even say programmers at this point. We've got so many people with so many facets of the IT, just areas. I mean, it's ridiculous. I go in there and I ask high-end server questions and four or five people answer. I'll ask questions about clustering or about high-end encryption or about artificial intelligence or, you know, whatever Twinkie is made out of. It doesn't matter. People answer. All right. Thanks for watching.