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.

Reply via email to