 Silence, please, everyone. Clint Adams is going to be speaking about HOpenPGP, a Haskell OpenPGP implementation. So I'm a little bit sick, so I apologize in advance if I collapse in a coughing fit or something worse. I assume all of you have seen my talk from last year, so this is gonna be a little redundant, but HOpenPGP is an implementation of OpenPGP in Haskell. It's primary consumers, as far as I know, is HOpenPGP tools, which is referred to by RiseUp's OpenPGP best practices, and also now the key signing party instructions at DebConf this year. So the intent of this talk is to explain what's changed since last year's DebConf, which is some bug fixes, some incompatible API changes, dependencies, and I'll go into a little more detail on some of these. So the API changes have mostly been for type safety, so for example, in the olden days of 2013, we used a type synonym timestamp for word 32 because most of time expressions in the OpenPGP standard are 32-bit unsigned integers, but some of them are expressed as seconds since the epoch, or not actually not the API. Some of them are absolute values of time and some of them are durations, so even though the standard calls the key expiration time, the key expiration time, it is number of seconds since the creation time, so I wanted to help the users understand which type is which to reduce confusion. So now we have two new type wrappers, one for duration and one for time, so now you'll get a compile time error if you try to do the wrong thing. And I think I talked about this last year a little instead of allowing you to have a list of MPIs for a key, it doesn't make any sense to have no MPIs at all, so we're gonna enforce at the type level that this list has to be non-empty. And since I was breaking things, I decided to change the type of the user IDs from strings to text, which theoretically will give us a performance boost, but probably doesn't matter at all. So a lot of the dependencies have changed out from underneath, including switching from serial and serial conduit to binary and binary conduit, and CWLP print to WLP print extras, and I accept typed, which is primarily because the former doesn't work with GC7.10, which will be in the WN archive pretty soon. Well, it's already in experimental, but it'll be in CID pretty soon, so I wanna be prepared for that. I was also abusing the show instances for fingerprints, so in order to not violate the principle of read and show around tripping, the show instance now contains no spaces. If you want spaces in your fingerprint output, you need to use the pretty instance. And there's more test coverage, which is still not complete, so if you feel like contributing test cases, that would be great. Now more interestingly, there are now JSON instances for transferable keys and all the types used by transferable keys, so this means you can, if you can parse a transferable OpenPGP key with HOpenPGP, you can output it as JSON or YAML, so this is somebody's key, and hopefully you can read that. So at the top, you'll see the RSA MPIs and the timestamps. The schema of this is clearly suboptimal, so if somebody has strong opinions on how this should actually look, and I see Paul Tagg as a volunteering, feel free to help get this into a sane format, because it is definitely not ideal. Because we're using JSON for the JSON, we get YAML output for free, so depending on which you prefer, you can just swap that out and every bit of data is going to be the same, just in the different format. And so there's some more YAML. This is either Paul Tagg's key or Francesca's, I can't tell them apart anymore. And as you can see, the JPEG is an array of byte values, which I really don't know what the correct way to handle this is, so if anyone else does, that'd be good to know. And the serialization is a bit better. It used to choke on unknown SDK types, and GNU PG has some sort of proprietary SDK type called 101. And so I ran into this in the world and now it can cope with that. So the OpenPGP tools can do filtering either on transferable keys or individual packets, and that code is in the library itself. It used to be split between more evenly, and now it's mostly in the library. And it used to be more poorly designed, so there were separate filtering languages for public keys and signatures and other, and you could not construct a complex query in a sane way if you wanted to do that. So if you were operating on a packet stream, the filters would only apply to the packets of their type, and so you could get surprising results. And that was using Ato Parsec for the parsing and someone convinced me to rewrite it using Alex and Happy, which are the Haskell equivalents of Flex and Bison or Lex and Yak, and the parser is completely redone. And so now you can do queries like, so the first two here are things you could do before, but you can do them with this syntax now. And the last ones are more interesting because now there's, this is using higher order functions, so you can do matching on sub structures of the transferable key, so you can search on all the UIDs or any of the UIDs, not every one of UIDs contains that sign if you wanna look for people that have UIDs that are not obviously email addresses, like Weasel just has his name or a couple other people do this. Or if find any key where the public key algorithm is ECDSA, or where the primary key is less than 2048 bits in size, but you have a sub key larger than that, which is pretty common. So that's probably the thing I'm most excited about. And then at Propo of Nothing, an eBall asked me to do an analysis on the DC-15 key signing party key ring. So I'm just going to segue into that and so this says sort of because there is one defective key in the key ring and HOPN-PGP choked on it. So I got to discover a fun bug. Canoe PG also does buggy things with this key, so that's exciting. And hopefully someone talks to Werner about that pretty soon. So there are actually 283 keys in the key ring, so this does not reflect any of that. And the five unknown, you'll see five other pubkey algorithms and five unknown sizes. Those are type 22, which I believe is ED-2519, no? No? Okay. Yes? Okay, so that is not yet supported, so if somebody wants to do some development, eventually we probably want to support that. And people are still using RIPE MD-160 for self-sigs. And a fair amount are using SHA-1. The longest paths in the self-contained set are six hops long and here they are and if you want to know who these people are, you're going to have to do the analysis yourself. And the strong connectivity analysis shows there's 193 keys in the strong set and a couple of islands and then all, but 215 keys are singletons. So hopefully after the rolling key signing of this conference, those get a lot better. So, right. Okay, so I guess now would be a good time for questions. If anyone has questions? Hello, right. You've mentioned a lot of analysis functionality. Yes. You know, HF and PGP. Is there also mechanisms for creating and manipulating signatures and key material? Sort of. The principle I've been going with thus far is to not implement anything destructive, so there's, if today you want to use a function that'll output a signature, you're going to have to do a little bit of work. The cryptographic support is there for the algorithms that are supported. There's a tiny bit of, there's basically no elliptic curve. There's a tiny stub for it, but that's about it. We can do RSA and DSA. We can't do El Gamal, and that's pretty much the situation. So, that needs a little bit of work, but you could do something. Any more questions, anyone? We have five minutes remaining. There's still chance of questions. What was this problematic key? So the, what about the bug report you sent to the packaging list? Did you send a bug report? Not yet, not yet. Okay, so there was another thing, okay. Yeah, so the key has a subkey packet, a public subkey packet followed by a user ID packet followed by a subkey binding SIG. Yeah, okay. So that sometimes happens and GPG should reorder it. So that's very, very old code. It does reorder it, but not in the right way. So... Yeah, it's not always possible to do this. So it's very limited. It was our bug fix for a key server about 15 years ago or so. Yeah, yeah. So it does not work perfectly. So, and I will delete the speed up now. So I don't know whether it's worth the time for these rare cases to do something about it. Yeah, I don't know what the right thing to do is, but. Yeah. Yeah, of course, because you could just, well, if you find someone who would want to fix this, okay, so expect it. I'll talk to DKG. No, it's a lot of work to test this. Yeah. That's the thing. It's not, it's just possible, but we have to see from where to take the time to fix all the bugs and try to do the same thing. All right. Are we done? Oh, one more. It's being massively self-serving now. Can you show us an example of using HOpenPGP to do something trivial? Something trivial? I know. Input a public key ring and just list the keys. Live demo. So, the font's too small, isn't it? That was not right. And I can't take it. So, let's list of the key ring with new PG-like output. We can also dump the packets. To do graphing or pathfinding, that'll take a few minutes. So... I was actually thinking of a .hs file that you could show us. Oh, oh, I'm not prepared to do that on the spot, but you can look at the OpenPGPTools sources or the test suite. I would like people to help out. So, if there's things I can do to make that easier, please let me know. I think I certainly would like to have a better library for Haskell use and eventually for use by other languages through the FFI. So, if you're interested, but overwhelmed or confused by some of the crazy things, please feel free to approach me. And there are no other questions. Thank you for your time. Thank you very much, Kent.