dedis / onet

Overlay Network for distributed protocols
GNU Lesser General Public License v3.0
50 stars 29 forks source link

PKI in conodes #433

Open ineiti opened 6 years ago

ineiti commented 6 years ago

Following #432

A first proposition was to add a Sign and VerifySignature method to TreeNodeInstance and Context, so that each service can set up its own public/private key. But, this might be messy, and perhaps we need to suggest a more streamlined way of doing so, some kind of PKI that works over #408.

In the upcoming months, we would need to start changing the protocols/services to set up their own keypairs and use those. The difficult part is how to verify a signature created with this service-key, when all you have is the roster containing the public key of the node...

To be discussed.

ineiti commented 5 years ago

The PKI would be something like

context.RegisterPubKey(keyname string, public kyber.Point)

in the Service, and then you could ask onet to give you the public key of another node:

kyber.Point context.GetPubKey(si network.ServerIdentity)

onet would then have to contact the remote node, ask its public key, verify the signature of the public key using the public key of the remote conode (which is known), and then pass that key to the service.

But then it gets more complicated with things like signatures that need to be verifiable externally to the cothority. If there is a CoSi signature (or BLSCoSi) using a Roster, the signature would need to be:

type SchnorrSig struct{
  // The actual signature on the message
  Signature []byte
  // The mask with respect to the Roster of which node signed
  Mask []byte
  // The public keys used in the signature, signed by the conodes and verifiable using the 
  // public key stored in the roster. The key to the map should be the public key of the
  // conode.
  PublicKeys map[string] struct{
    Public kyber.Point
    Signature []byte
  }
}

Any better ideas are welcome.

LefKok commented 5 years ago

How about this. The first thing the conodes do is setup a PKI-service, this service runs with the conodes' private keys as before and its job is to maintain a global mapping of conodes->keys_for_service_X.

Every time a conode wants to be part of a new service it creates a new registration which is signed by its private key and sends it for validation to the PKI-Service. The service check the signature and updates the mapping.

This service can be implemented using the current skipchain code and will resemble the keyblock blockchain of ByzCoin without the need for PoW. Every epoch, a leader collects the new signed mappings, puts them in a block and sends them for consensus. If the new block is accepted then the map is updated accordingly. For external verification, nodes will act as light clients and follow the skipchain to retrieve the correct keys.

There seems to be a slight issue here if we want to use BLS-CoSi for the PKI-Service though. Could it be that by default the nodes have an individual BLS keypair instead of a Schnorr?

kc1212 commented 5 years ago

The roster is like our source of truth, e.g,., we verify the signatures using the roster from skipblocks. If we start from there, then is it possible to change the server identity (inside the roster) to include additional keys? For example, ServerIdentity will have an AdditionalKeys field which is a mapping between the key type and the actual public key. Maybe AdditionalKeys must be signed by the main key.

To start a protocol, the root must specify the key type (maybe using SetConfig, or we introduce CreateProtocolWithKeyType that lets the root set the key type). The key type must be in all server identities of the roster. This key type is propagated to the child nodes as a part of the protocol config.

Actually, it doesn't even have to be automated, if a protocol is only for a particular key type, then it should just always get the right key type from its roster.