 So, usable cryptography with Jose. So, Josie, which is what many Americans call this word. I think they're wrong, but they call it this word anyway. Josie is not Jose. Josie is a set of RFCs that specify different encryption formats. So you get a format for web signing, for encryption, for keys, and for a variety of other things as well. So this is what a key looks like, a symmetric key. It's a JSON object. It says it's an octet string. There's the actual symmetric key, and then that's the algorithm it's used for. We're going to go fast, like I said. Here's an elliptic curve key. Key type, that's the curve group we're in. So P256, X and Y values. There's your D, private value. This can be used for encryption, and it has a KID of 1, a key ID of 1. So here's an RSA key. Similar stuff, got a key type RSA. You've got all the public and private values. You've got the algorithm that this key can be used with, and the ID that uniquely identifies this key. So this is all just the RFC stuff. So we have a JWK set, which is just a set of keys. And it's an object with one attribute keys, which is an array containing all of the keys. All right, here's where things start to get really interesting. Got to roll up my sleeves for this. So we have here a signature object. We have a payload, which is base 64 encoded, base 64 URL encoded, I should say. And then we have an array of signatures. So in this case, we have two different signatures. Each signature has a set of headers. So in this case, we have the protected header, which if you attempt to modify it, the signature will fail. Then you have a regular header, which is not protected. And so if you modify this, then the signature still validates. And then we have the actual signature value itself. The protected header is also a JSON object. But because we have to be sure that if we're doing like re-encryption or re-signing of anything, if we don't change the contents of the header, it has to be exactly the same. So it specifies that what we do is we render the JSON string with sorted keys and then base 64 encoded. And that way, as long as the contents of the JSON object don't change, the output never changes. So again, protected header, unprotected header, and signature. And this is signed by two keys. So if you were to validate this key, then this payload would validate or this key, this would validate as well. Now, there's also a flattened format. And this should look very similar to what we were just looking at a moment ago. You have a payload, which is also base 64 encoded, just like before. Then we have the signature data. But since we only have one signature, in this case, we can use flattened format, which just simply takes the same exact object as it would have been in the signature and flattens it upward in the structure. So if we go back on slide, you'll see protected header signature, protected header signature. Same exact contents, just moved upwards in the object. Now, notice that in flattened format, you can only ever have one signature. So you can have multiple signatures this way. And that allows us to actually do something called compact format. The compact format is where we take the protected attribute, the payload attribute, and the signature attribute, and just concatenate them all base 64 encoded. Now, the neat thing about this is that this structure can actually be used in the URL because it's all base 64 URL safe. So you can actually pass this signature in a URL. The server can take it and validate it right out of the URL. We have something similar with encryption. And you probably can't read it because it's pretty small. But on the top, we have similar idea of headers. We have a protected header and an unprotected header. Now, notice, unlike the signature, this is global. So we don't have a protected headers like we did in the signature. So protected header also base 64 encoded, which is just that JSON object. And then we have an unprotected header here. And this specifies a URL to get the keys to decrypt this. We have an IV, a ciphertext, and a tag. This is just your main encryption data for the data itself. So the ciphertext is the encrypted data. The IV is the initialization vector for the cipher you're using. And the tag is the way we do authenticated encryption. So this is relating to the encryption itself. But then like the signature structure, we have multiple recipients. So we can actually encrypt this to multiple people. And the way that it works is we encrypt this bit with a symmetric key. And then we encrypt the symmetric key to each of the recipients. So this recipient can unpack its encrypted key and then use that key to decrypt this data. Does that make sense? Not your head of being. All right, I think everybody's asleep. So we also have a per recipient header, but this is not a protected header. Unlike up here, if you change the contents of this protected header, then decryption will fail. On the other hand, if you change the contents of this per recipient header, it will not fail. So it is not a protected header. Similar to the signing object, we also have a flattened form of this. So if it only has one recipient, we just pull all of the objects from the recipient object upward into the parent. And so we have encrypted key and header here, just like we did encrypted key and header. So we just pulled it up into the parent. And then again, if we have certain constraints, for instance, if we don't have an unprotected header and we don't have this header either, you can actually do this in compact format as well. So protected header, encrypted key, IV, ciphertext and tag. So notice that we went from the most general use case, right? Where we can represent basically anything you want to. And then we said for some very common use cases, we can actually make the dataset smaller. Just like the JWS, this can also be passed in a URL. So a web server can receive this encrypted data in a URL. We also have something called the JSON WebToken, JWT. And so this contains the actual information on the inside. If you wanted to make claims about a certain entity, there's a standard way to do that. So we have the issuer here. I work for Red Hat, so that's me. There, I'm the subject. The audience is you at Fozdem. Expiration time, not before, and issued at. And then finally an ID for the particular token. I know I've gone fast, but I really want to spend our time here on Jose. So Jose is actually implementation of the Josie specs. So if you remember what I've shown you up until this point was actually specified in RFCs. It's well-defined and there's lots of implementations of this out there, and most all of them are terrible. The reason most all of them are terrible is because people basically implement only the thing that they care about, the algorithms they care about or whatever, they don't implement the full specs. The other problem that I ran into when using lots of different versions was that lots of different implementations is that they expected you to essentially parse all of your JSON into a language structure or of some kind and then do all your operations and then push it back out again. Which of course if you have any extensible metadata in there that's all lost in that process or they had to go to great lengths in order to keep it. So we did this as a way to improve the state of the art and we think we have. So then we have support for all the RFC defined algorithms which most implementations do not. We do not have any native C data types. So everything that you do with Jose is gonna be done in JSON. We don't do any JSON parsing. So we use the wonderful library Janssen which is a great upstream and very active. And so basically you use Janssen to parse into a JSON struct and then those JSON structs will do all of the, will do all the crypto with those. One of the nice things about this approach is that Janssen actually provides really handy utilities for actually creating JSON objects and everything. It's got everything you could ever need. So it's really simple to use. Our API is driven by a template approach. So basically what comes in is what it's gonna look like when it comes out. So you don't have options or parameters to specify like the algorithm. You just say I want a JWE that looks like this. And so we introspect that and then we give you the output. The missing parameter is anything you don't provide us is gonna be inferred from the keys that you use or inferred from the headers that you've specified. Or if you haven't specified anything then we're gonna give you sensible security faults. So the idea is that you should never be surprised by the output and everything should be sane and secure by default. Library design, we have a core which implements the Jose logic itself or the Josie logic I should say. And then we have hooks for the actual crypto algorithms themselves. So for instance, we can have a, we currently have an open SSL implementation. We would welcome other implementations as well. You just basically need to plug into this spot and handle the algorithm properly. So we also provide a CLI tool which provides a thin layer around the CAPI. So anything you can do with the CAPI almost is like one thing you can't do but you can do with this command line utility as well. So that's really, really helpful for writing tests and shell script. It's really helpful for just prototyping something, making sure that it works before you actually write the code. It's also fully tested against the very many RFC provided test factors. So if there's something wrong, we probably have already caught it. And if we haven't, give us a test and we'll happily test for your case as well. So the URL for the project is github.com slash latch set slash Jose. And this is available in Fedora 24 and later just DNF install Jose. So pretty much that simple. So let's show a little bit of how this works. We have one function to generate a key. It takes a Jensen type as input and this is the thin wrapper in shell around this API. So we say we want a key that looks like this. It's usable for AES 128 GCM. So we know what an AES 128 GCM key looks like. So because we can infer it from your template, we can just generate a key that works for you. Same thing for RSA, for elliptic curves. We can also, you don't have to specify the algorithm though. There's other ways we can infer it as well. Like you can just tell us you want an octet of symmetric key and you want it to be 16 bytes and we'll just happily generate that for you as well. Same thing with bits for RSA and you can also just tell us the group you want for an elliptic curve group and it will just be generated. So one last thing is that you can actually specify multiple templates and the output will be a JWK set containing all of the output in keys. So with the exception of bits and bytes, these two parameters here, all input JSON attributes will be retained. So and everything else is specified in the RFCs. So basically again, you give us something that looks like a JWK and if we can figure it out we will. For signing a verification, we have exactly the same sort of schema. So to sign, we pass in a JWS object which again is something that looks like the JWS object you want it to be and then you pass us a key and then optionally you can pass us that signature object that you saw in the end and we use that to infer. So most often times the signature, the SIG option there is actually just null because you just don't care about what the details are for a particular signature, you just wanna sign with a bunch of keys. So basically two inputs for signing, it can't really get any smaller. JWS verifies exactly the same thing and then we have examples of using it here. So we create a signature, in this case we create two signatures, one with an elliptic curve key, one with an RSA key and we output it in msg.jws, we cat the file, you see we've got our JSON data here, well formatted and then let's do the same thing here with other formats like the compact format and we can verify the signature and if it doesn't work, it doesn't work. Yeah, if your signature fails to validate, we error. Encryption is similar, the only thing here is that we have two steps in the CAPI because we need to have a CEK here and you may wanna do things like get in a JWE and then re-encrypt it to somebody else and the only way you can do that in a CPI is to have two functions but those two are merged in the CLI. So the wrapping can be performed multiple times but encryption occurs once, the CEK is generated in the first wrap if it's an empty JSON object, that means that inner key will just generate it for you if you don't care unless you wanna specify one for some reason. Both the JWE and recipient templates respectively and the RCP parameter is often simply null. Encryption is just the reverse of this, you have to unwrap that CEK, pass it back to decrypt and then you get your data. Here's an example of using it for the command line. We also can do passwords because there's passwords specified in the draft. One of the only differences here is that for wrapping and unwrapping if you wanna use a password, you don't pass in a JWK, you pass in a JSON string. That's how we infer from that type. So there's a lot more stuff, I've run out of time. We have lots of future Jose features we'd like to do like PKCS11 support, additional crypto library support. We don't have any functions currently for JWTs but we'd like those. We'd like some additional functions for converting X599 certificates and we'd like to implement some of the additional optional RFC features, which fairly few people use. So we also wanna finish Python bindings, we're almost done with this one. Pull requests are welcome, so please contribute. Any questions? Yes, I think this is on. I know that was a fire hose but I didn't have any way to get through the material so. Okay, I first say that I understand the alpha of the things or none but this is the, I have two questions. This is the most practical and beautiful presentation of the FOSDM, in my opinion. But why, no one knows, for me it's very helpful and very useful, not only as a library but as a concept of exchange information with JSON. And why no one knows, it's RFG, RFCC. Why no one knows one and what are the real use cases of these. So we use Jose in the Clevis and Tang servers, it's a client server side and we do, our entire protocol is built on these objects. So lots of people do know about it, it's just not very popular outside of the web authentication community right now. So it's all fairly new, the RFCs, I think the oldest one is like 2014, so it's very, very new. But I think it also provides a crypto system that's very usable because as long as you've basically looked at the IANA registry with the names of the algorithms you can figure out everything else pretty much directly and just by experimentation. So I like the system a lot, I think it has a lot of uses outside of the web world but right now it's currently used for a variety of web related protocols. So that's why you get lots of implementations like in Python and Ruby but they only implement like the algorithms they actually care about. Yes, absolutely, absolutely. That's what we use it for in Clevis and Tang, yes. So how would you go about interfacing with PKCS 11 spec like what are the libraries or how to do that generally? So this is actually something we are still trying to work out, our moderator actually has written a lovely little piece of software called P11Kit which allows you to like introspect all the PKCS 11 modules and you can actually have a URI that refers specifically to a hardware token and a key as to exactly how we're gonna marry it into this. We haven't done the design yet so I don't have a good answer for you. Long term also we are talking about creating a sort of system wide PKCS 11 policy demon where each user can essentially get their own PKCS 11 slots and the user doesn't know whether those are hardware or software or what the administrator just configures and can route them different ways. So we have sort of a lot of plans but we're still flashing out the details. Yeah, actually if you think that's cool talk with Dikey about his PKCS 11 remoting, he did it like three talks before mine. It's kind of like the basis of this work, so. More questions? We chose it because we knew it would match up well and we didn't want to spend a lot of time looking at other things, so we had a good solution and we just developed it. But we would be happy to have other back ends as well or front ends, they're really front ends. So we would be happy to have any others. So if you want to code one for GNU TLS or whatever, we're happy to take it. I have a question, does it compile on Windows? Probably not. It does on Mac, but I don't think it does on Windows. Okay. More questions? No questions from you. Is it, can you actually do like detach signatures? Like if you have something in some file and you actually don't want to recode it first into base 64 and then throw it away again? The RFC does have support for that but I don't know if we implement it. I don't remember if I implemented that or not. If we didn't, I'm happy to implement it for you. You're welcome. I think it's just a convention whether the data is actually like a hash or it's actual data. It depends on your application format. It shouldn't restrict it in any way. It was just concerned about recoding everything. No, no. It doesn't have. It's right in a way. No, no, no. Yeah, I believe there is a detached signature mode. I just don't remember if I implemented it. I think I may have, but if I haven't, I will definitely implement it. If it is that, then it would be a way nicer alternative to shipping GPGs. Yes. Detached signatures on a web server to sign in or whatever. I agree. GPG is very difficult to use, so. Yeah. Okay. Thank you very much. Thank you. And applause for the presenter.