It’s not super pretty, but a trick I’ve used is type T struct { data any } func (t *T) UnmarshalBinary(…) error { // decode and assign to data }
Now T is basically an enum and you can switch on T.data ~similar to Rust’s match or whatever. Then you’d have map[uint64]T. - eric Ps: hope you’re doing well! On Friday, February 10, 2023 at 6:42:22 PM UTC-8 David Stainton wrote: > 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/40398bbc-b344-42e5-baa6-e719c6cc8ed5n%40googlegroups.com.