To make it a little more real, please look at this gist: https://gist.github.com/franks42/b8b28049adcdf4504271238391c3525b
which implements a key identifier generation based on HKDF. Any security concerns with such an approach? Better alternatives? Thanks, Frank. On Sat, Jul 2, 2016 at 4:52 PM, Frank Siebenlist <frank.siebenl...@gmail.com> wrote: > Hi Laurens, > > I'm afraid that I have not been very good in explaining my use case, because > the questions you ask point at more complicated solutions than I thought were > necessary. > > The aim is to find the most convenient symmetric key identifier to embed in a > cipher message that would require the minimum amount of key management. > > What is best depends on the context. Sometimes it's easy because there is > only one key, or the security context is so unambiguous that associating the > right key is trivial. Other times it's a bit more challenging. We have an > existing application with tens of long-lived keys, and the current > key-management complicates key-rotation and upgrades to modern algos and such. > > If both Alice and Bob can generate key identifiers (kid's) from the key that > they share directly, like derive if from the symmetric key, then there is no > need to exchange or agree upon a name for that key as it would be kind of a > "true name" (read Vinge if you haven't ;-) ). The parties only have to agree > on the key identifier derivation method. > > For example, if Alice and Bob agree to name their symmetric keys by taking > the sha256 of that key's bytes, base64url encode the hash, and represent it > as a urn, like "urn:s256:V2jyhd8tX-19vpEhyrDzIHgUYyDA5MS1Qi71iw1SUP0". This > would allow both parties to maintain their own key-db with (kid, key) > associations. Embedding the kid in the exchanged cipher messages would allow > both parties to easily find the key to decrypt the received message. > (very much like we often use the hash of the public key (or pk-cert) to > identify the private key to decrypt) > > The kid embedded in the cipher message is no more than a “hint”. It could be > signed as part of the whole cipher message, but its integrity can only be > confirmed after the message is decrypted&authenticated. Changing the kid in a > cipher message results in DoS, but so would flipping any other bit in that > message. > > In its most simple form, I believe that the kid-derivation could be a sha2 of > the key as long as the key is "truly" random. The only concern may be that > some use a simple hash of the key for key derivation...(?). To avoid any of > those usage collisions, you could define the convention of pre-pending the > key with some publicly know constant, like b'pre-kid-constant' or fancier. > > If one believes that a simple sha2 hash is only borderline enough secure (?), > then maybe use a CMAC or HMAC, where you use the key on the key-value itself, > and the resulting tag would constitute the identifier. (I did something like > that in franks42/naclj with blake2) > > Or use HKDF, with maybe a kid-derivation specific constant for the salt, a > kid-specific info value, and a sufficient length of the resulting key, i.e. > identifier, that makes everybody happy. > > Maybe something based on HKDF would be best (?). > > Hope this additional explanation helps. > > Thanks, Frank. > > PS. Don’t believe I will resurrect that franks42/naclj - I’ll add a note > about depreciation and send them to your effort - it was a good experience > learning about Curve/Ed25519 and the nacl/libsodium code though - also trying > to keep all data structures as immutable as possible was a good exercise. > > > On Fri, Jul 1, 2016 at 3:53 PM, lvh <_...@lvh.io> wrote: >> >>> On Jul 1, 2016, at 12:54 PM, Frank Siebenlist <frank.siebenl...@gmail.com> >>> wrote: >>> >>> Hi lvh, >>> >>> Guess you're the "lvh" who is responsible for "lvh/caesium" ;-). >> >> Yup. I’m also a founding member of PyCA and the resident cryptographer, >> which is why I’m on this list :-) >> >>> Good to see that you've reanimated that project! Believe you were kind of >>> distracted for awhile, which "forced" me to play around with >>> "franks42/naclj"... which has been on live-support for about a year >>> now, because my new job consumes even my playtime. >> >> It did what I needed it to do at the time, so I didn’t fix what wasn’t >> broken ;-) I don’t recall anyone reaching out or filing issues. Once someone >> did ask questions and contributed code, I was happy to merge/review/cut new >> releases/do new development. More dev is happening now to scratch my own >> itch :) >> >> Currently I’m doing a lot of work around NMR as mentioned before, and API >> design around e.g. different byte buffer types, so that for example you can >> efficiently dump a nonce and a ciphertext in the same buffer, or derive >> multiple keys in one iteration of BLAKE2, etc. Also a bunch of work around >> e.g. pinning and verification of the produced binding and related >> benchmarking :) >> >> I invite you to look at caesium again, because some of the criticisms you >> make in naclj’s README no longer apply (e.g. caesium no longer uses kalium >> and instead binds libsodium directly, albeit for a different reason than >> what naclj mentions). Because the binding is done in Clojure, it can do all >> sorts of metaprogramming including binding every permutation of a particular >> method for various byte types in addition to the inspection mentioned above, >> e.g.: >> https://github.com/lvh/caesium/blob/master/src/caesium/binding.clj#L56-L62 >> >> Do you intend to continue to develop naclj, or is it effectively retired? >> >>> As part of that "franks42/naclj" effort, I suggested to standardize >>> the derivation of a kid from the two curve25519 public keys. However, >>> I recognize that you do not always have any DH-keys available when you >>> have a bare symmetric key, >> >> Is that scheme documented anywhere? I wonder what the use case is for two >> curve25519 pubkeys — the “obvious" case would seem to easily degenerate to >> the shared symmetric secret (after doing a DH exchange). >> >>> so I suggested a scheme based on blake2. I >>> wrote up some rationale for those choices here: >>> "https://github.com/franks42/naclj/blob/master/Keys%2C%20IDs%2C%20and%20URNs.md", >>> but never got much traction on the libsodium list,... and then I got >>> distracted. >>> >>> Now I'm faced again with similar key-management issues, which could >>> benefit from such key-derived kid's - so I try again. >>> >>> In summary, your suggestions all resonate very well, but... there are >>> too many of them. Let's just pick one identifier derivation mechanism >>> for symmetric keys, document it, implement it, use it! >> >> I think there are a few problems preventing this from happening right now, >> including: >> >> - Historically, cryptographers have not researched key wrap anywhere near as >> much as other schemes. I think the only reason it’s en vogue now is the >> interest in NMR, which at least a handful of cryptographers (Rogaway, >> Krovetz, and humbly, myself) care about now, and is incidentally a related >> problem. >> - People want subtly different things for their protocols, further reducing >> interest. Do you just want to identify a key? That’s fine, but a problem >> many protocols dodge. Do you want to ship a key to someone who already has a >> secret or asymmetric key? AEAD (including NMR AEAD in particular, so key >> wrap) and just asymmetric encryption (a la non-PFS TLS or GPG) is probably >> where you’re going to land. >> - How does this fit in a grander protocol and what is that protocol trying >> to accomplish? >> - How is the key identifier authenticated? What prevents Mallory from just >> modifying the key id bytes to effectively deny service? E.g. if I’m doing >> this to make sure I can rotate keys effectively, how do I auth that? Ideally >> without replacing an unrotatable secret key with another unrotatable secret >> key :D (Effective key rotation for KEKs is definitely something I care >> about.) >> - When keys are being sent alongside messages, how do we make this not a >> footgun for e.g. key selection attacks? (Granted, harder for EdDSA, but I >> want protocols to be correct for arbitrary schemes :)). PyCA cares about >> recipes being not footguns. That’s a mixed bag: on the one hand, it means we >> can give safe advice, on the other hand, it does mean that all we have is >> Fernet... >> >> Overall, I think this is a reasonable idea for some protocols, but I think >> we need to be extremely clear about what that is, who it’s for, and how to >> use it. >> >> >> lvh >> >>> Groetjes, Frank. >>> >>> On Fri, Jul 1, 2016 at 9:51 AM, lvh <_...@lvh.io> wrote: >>>> Hi Frank, >>>> >>>>> On Jul 1, 2016, at 11:11 AM, Frank Siebenlist >>>>> <frank.siebenl...@gmail.com> wrote: >>>>> >>>>> snip snip key identifiers >>>> >>>> This is why some key derivation functions and PRFs have “purpose” or >>>> “info" fields, yes; including BLAKE2 and HKDF. Deriving a lesser key >>>> (which might just be a keyid) is a perfectly valid strategy from objcap >>>> practice. I’m doing something similar in the scheme of a larger >>>> semiprivate key scheme using libsodium. You probably do want something >>>> that explicitly supports that instead of just implicitly picking a >>>> particular nonce or whatever — I’m not sure which nonce you’re referring >>>> to, I don’t think the systems you mentioned take one. TL;DR: make the >>>> derivation completely distinct based on what you’re deriving and why >>>> you’re deriving it :) >>>> >>>> You might also want to look at the related concept of NMR and key-wrap, >>>> which might let you solve the problem at a slightly different part of your >>>> protocol; essentially giving you a protected key with associated data >>>> about that key. It’s not entirely clear what the people standardizing >>>> GCM-SIV want to do exactly (other than “not TLS”, I don’t think they’ve >>>> said), but this is the obvious choice, especially given GCM-SIVs separate >>>> code path for tiny messages and the historical linking of the two from a >>>> crypto design perspective. >>>> >>>> I am also writing NMR stuff on the side in libsodium/caesium, but that >>>> focuses mostly on being a Fernet replacement, rather than a keywrap, using >>>> secretbox (which makes it easy because big nonce space). Pretty sure I can >>>> translate it to the AEAD schemes, but the security proof gets iffier. >>>> Which reminds me: we should talk about Clojure bindings to libsodium some >>>> time :) >>>> >>>> >>>> lvh >>>> _______________________________________________ >>>> Cryptography-dev mailing list >>>> Cryptography-dev@python.org >>>> https://mail.python.org/mailman/listinfo/cryptography-dev >>> _______________________________________________ >>> Cryptography-dev mailing list >>> Cryptography-dev@python.org >>> https://mail.python.org/mailman/listinfo/cryptography-dev >> >> >> _______________________________________________ >> Cryptography-dev mailing list >> Cryptography-dev@python.org >> https://mail.python.org/mailman/listinfo/cryptography-dev >> _______________________________________________ Cryptography-dev mailing list Cryptography-dev@python.org https://mail.python.org/mailman/listinfo/cryptography-dev