Upon further reflection I think the simplest solution is to have MixDescriptor represent the maps of mix keys in raw bytes and use a method to unmarshal them when needed. The unmarshal method could use CBOR tags to figure out which type to unmarshal into.... but it would be easier to implement this where a Sphinx Geometry object is an argument to the method which does the unmarshaling; and using that Sphinx Geometry to determine which concrete cryptographic key type should be used.
On Friday, February 10, 2023 at 6:19:55 PM UTC-5 David Stainton wrote: > > Greetings people of golang, cryptographers, software architects, > > Hi. I'm a Katzenpost developer, it's a software project, not a legal > entity: https://github.com/katzenpost > > We use the golang CBOR library: github.com/fxamacker/cbor > Works great! > > Jumping right into the nitty gritty here... We have a "directory > authority" protocol (similar to Tor's directory authority protocol) which > votes and publishes a "network view" document which contains many > MixDescriptor objects, one for each network node (known as a mix). > Each mix published several mix keys for future Epochs in their > MixDescriptor. So we have a map of these mix keys, like so: > > > https://github.com/katzenpost/katzenpost/blob/main/core/pki/descriptor.go#L65 > > However, currently the map of keys only stores X25519 keys. But ideally > we'd like the MixDescriptor struct to be more accommodating to migrating to > hybrid post quantum keys. > > How might we accomplish this? > Acceptable solutions will not create intermediary types to represent the > entire MixDescriptor... but there should be no objections to intermediary > types for representing a single field of the MixDescriptor; like a wrapper > type for the map of mix keys? > > Also... can I just point out now that two of the MixDescriptor fields are > interface types representing two different kinds of cryptographic public > key, yet we manage to CBOR unmarshal everything just fine without an > intermediary type, with this trick here: > > > https://github.com/katzenpost/katzenpost/blob/main/core/pki/descriptor.go#L123-L127 > > So we initialize those two fields with valid empty types that implement > those interfaces. Fine. But that won't work for a map of interface types, > right? > > Let's come back to this question soon, and now take a brief digression to > discuss katzenpost architecture design: > > These mix keys are used by a nested encrypted packet format known as > Sphinx (here's the paper > https://www.cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf ). Long story > short, our Sphinx can use any NIKE (non-interactive key exchange e.g. > X25519) and any KEM (key encapsulation mechanism): > > code: https://github.com/katzenpost/katzenpost/tree/main/core/sphinx > design spec: > https://github.com/katzenpost/katzenpost/blob/main/docs/specs/sphinx.rst > design amendment for KEM: > https://github.com/katzenpost/katzenpost/blob/main/docs/specs/kemsphinx.rst > > Backing up a bit, our "directory authority" publishes a document of this > type: > https://github.com/katzenpost/katzenpost/blob/main/core/pki/document.go#L77 > > which contains many MixDescriptor objects for the entire network: > > https://github.com/katzenpost/katzenpost/blob/main/core/pki/document.go#L128 > > Currently all network components use Sphinx with a geometry that is > hardcoded. However I've got a work-in-progress branch where I'm changing > things to distribute the Sphinx geometry in the directory authority > document: > > > https://github.com/katzenpost/katzenpost/blob/sphinx_geo_pki/core/sphinx/geo/geo.go#L31-L89 > > > https://github.com/katzenpost/katzenpost/blob/sphinx_geo_pki/core/pki/document.go#L152 > > The Sphinx Geometry describes it's KEM or NIKE: > > https://github.com/katzenpost/katzenpost/blob/sphinx_geo_pki/core/sphinx/geo/geo.go#L82-L88 > > So I guess my question is: How shall I marshal/unmarshal a map of public > keys where the keys themselves can be any type that satisfies our NIKE > interface or KEM inteface? > > It would be silly to put a bunch of concrete key maps into MixDescriptor. > There will always be more KEMs and NIKEs. > > It sounds like I need change the MixKeys field of the MixDescriptor to use > a wrapper type instead of a map directly. The wrapper type would have it's > own UnmarshalBinary/MarshalBinary (so that cbor.Marshal/Unmarshal can be > called) which would represent the map as a list of two tuples: key, value. > Easy to convert it to a map. > > What do you think of this approach? > > type KeyValue struct { > Key uint64 > Value mixkey.PublicKey > } > > ...blah blah... > > fubar := make([]KeyValue, 123) > cbor.Unmarshal(blob, fubar) > > But can this work if mixkey.PublicKey is an interface? Nope. I don't think > that works because the nil value of KeyValue struct will have a nil for > it's Value field. > > Any suggestions? > > Cheers, > > David > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/ce8a5822-d2a5-4230-858b-00f69a5c4e5bn%40googlegroups.com.