Skip to main content

Box Key Shares

Box key shares are cryptographic values computed from the secret key of a box. One key share alone is completely useless, but by combining the two corresponding shares (shares are created by pairs) results in the box secret key.

This mechanism is used to reduce the sensitivity of invitation links: instead of putting the box secret key in an invitation link, we put a share of it. The other share is sent to Misakey's backend, but since Misakey never sees the invitation link, encryption is still considered end-to-end.

As a result if an adversary manages to intercept an invitation link, she doesn't immediately have the box secret key: she must convince Misakey's backend to give it the Misakey share first. If the box admin suspected that the invitation link may have ended between evil hands and changed the box key share, the adversary cannot do anything with the invitation link she intercepted because Misakey's backend destroyed the share corresponding to this invitation link.

This is an essential security mechanism because many invitation links will probably be sent through email, which is a quite insecure medium. Also, many people never delete the emails they receive, so you may very well send an invitation link to account now that will be stolen by a hacker a long time after.

Construction#

One share is simply a random byte array of same length as the key. The other share is the XOR of the key and the first share. Since every value is its own inverse for XORing (A XOR B XOR B = A), XORing the two shares together gives back the secret key (S1 XOR S2 = S1 XOR (S1 XOR K) = K). However, each share taken separately gives no information about the key.

The share that goes in the invitation link is called the invitation share and the one that is sent to the Misakey backend is called the misakey share. We suggest to use the share generated randomly as the misakey share, and the one computed by XORing as the invitation share, but in practice it doesn't matter which one is used as which.

When uploading a box key share object to the backend, we also upload the (SHA-512) hash of the invitation share. This allows clients to identify the shares they want to download, and at the same time to prove that they do have the invitation: the client hashes the shares it got in the invitation link, and the backend sends the misakey share that matches this invitation share hash.

Finally, a box admin creating a box key share also upload the invitation key share encrypted with the box public key. Because the backend does not have the box decryption key, this does not break end-to-end encryption. This value is used as a way for box members to compute “the latest value of the invitation link for this box”. Recall that box members do have the box decryption key, so they can decrypt this value.

Formally, here is how you construct box key shares:

  • take the box secret key in binary form (as bytes)
  • generate an array of (secure1) random bytes with the same length as the box secret key: this is the misakey share.
  • combine the box secret key and the misakey share using bitwise XOR: the result is the invitation share

To compute the invitation share hash, simply hash the invitation share with SHA-512.

To compute the encrypted invitation key share:

  • encode the invitation key share using unpadded URL-safe base64

  • stringify the following JSON object:

    { "boxKeyShare": "(the base64...)" }
  • convert the result into bytes and encrypt it using the box public key (using the encryption algorithm associated with the public key)

Using Box Key Shares#

Box key shares are created by interacting with boxes:

  • you can set the key share of a box when creating the box (see boxes endpoints)
  • the admin of the box can change the key share of a box via a state.key_share event (see boxes envents)

Box key shares are read via dedicated endpoints (see below).

Getting a Box Key Share#

Request#

GET https://api.misakey.com/key-shares/:invitation-key-share-hash

Cookies:

  • accesstoken (opaque token) (ACR >= 1): no identity check, just a valid token is required.
  • tokentype: must be bearer

Headers:

  • X-CSRF-Token: a token to prevent from CSRF attacks.

Path Parameters:

  • invitation-key-share-hash (string, URL-safe base64): the invitation share hash.

Response#

Code:

HTTP 200 OK

JSON Body:

{
"misakey_share": "U2hhcmUgeW91ciBrbm93bGVkZ2UuIEl0IGlzIGEgd2F5IHRvIGFjaGlldmUgaW1tb3J0YWxpdHkuICBEYWxhaSBMYW1hIFhJVi4K",
"invitation_share_hash": "SXQgaXMgc29tZXRpbWVzIGhhcmRlciB0byByZWNlaXZlIHRoYW4gdG8gZ2l2ZS4K",
"encrypted_invitation_key_share": "zIGEgd2F5IHRvIGFjaGlldmUgaW1tb3J0YWxpdHkuICcmUgeW91ciBrbm9YWxhaSBMYW1hIFhJVi4KhhcmRlciB0byByZWNlaX",
"box_id": "df53b67d-5619-4ed5-8e6e-01ea7590b5b0"
}

Getting an Encrypted Invitation Share#

This endpoint gives you the encrypted invitation key share part of the box key share object.

Request:

GET https://api.misakey.com/key-shares/encrypted-invitation-key-share?box_id=74ee16b5-89be-44f7-bcdd-117f496a90a7

Access control:

  • querier must be authenticated with ACR ≥ 2

Response:

"cGYMzgIO9rc03WoSLAyoiQdLu7he5VbMRImLhRPmwTQ"

Not that the result is not a JSON literal object but it is still valid JSON (a JSON string is a valid JSON object). The encoding is unpadded URL-safe base64.


  1. always use a pseudo-random generator that is suitable for security-related usage