Skip to content

Ring Token as Server-side User ID: Enhancing Privacy by Not Persistently Storing Session Identity Public Keys in Oxen Storage Server #495

@venezuela01

Description

@venezuela01

Edit: fix some terminology usage.

Currently, the owned_message table in the Oxen storage server uses the Session identity public key as a virtual user ID and stores it persistently.

This design has a disadvantage: in the event of an Oxen storage server breach, an attacker can retrieve a massive amount of Session IDs and potentially spam those Session IDs, among other actions that threaten privacy.

It may not be necessary to use the Session identity public key directly as the server-side user ID. We have a deterministic partitioner that translates Session identity public keys into a ring token (also referred to as swarm space keys in Session's terminology). In theory, we can use this ring token as the server-side user ID, or a virtual user ID, and always translate from the Session identity public key to ring tokens on the fly whenever there is a read/write request from any Session user.

For instance:

Assume a user has the Session ID 05a0962389777624bbe97f883221e5c03c967003e2af53e1c2d02028c1ff901224. Instead of removing the 05 prefix from the Session ID and using the public key 0xa0962389777624bbe97f883221e5c03c967003e2af53e1c2d02028c1ff901224 as the server side user ID, we could consider using the ring token 0xfb9809806501761 directly to store or retrieve user messages in the Oxen storage server.

In other words, we only need to maintain the connection between the Session ID and its ring token in memory and temporarily during the read/write operation. The rest of the time, the service node has no knowledge about how to reverse a ring token back to the original Session ID.

If we avoid saving Session identity public keys on disk, then Session users will not risk exposing their Session IDs even in the event of a data breach, since nobody can decipher a Session ID from its ring token.

For readers who are less familiar with the partitioning design of the Oxen storage server, below is a replicated implementation of the partitioner used by the Oxen Storage Server:

import struct

def pubkey_to_swarm_space_position(pk: str) -> int:
    if len(pk) != 64:
        print('Incorrect pubkey length')
        return
    res = 0
    bytes_pk = bytes.fromhex(pk)
    for i in range(4):
        buf, = struct.unpack('Q', bytes_pk[i*8:(i+1)*8])
        res ^= buf
    return struct.unpack('!Q', struct.pack('Q', res))[0]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions