TEMP_Data Structures for Metrics - zwettemaan/TightenerDocs GitHub Wiki

entityHandle

A single string that can contain some identifying data for a person or entity (company,...).

This can be as simple as a short string, or as complex as a JSON file with an elaborate data structure containing data and meta-data.

entityGUID

entityGUID = hash(entityHandle + hash(entityPassword))

entityPassword

A single string

entityPrivateKey

Private entity key

entityPublicKey

Public entity key

capability

{
   receiver: {
       entityGUID: entityGUID,
       allowances: {...}
   }
   issuer: {
       entityGUID: entityGUID
       signature: signature of this capability data (minus signature)
   }   
}

capabilityGUID

hash(capability)

Tables

entities:
   entityGUID
   entityPublicKey
   entityEmailOrHash
capabilities:
   issuerEntityGUID
   capabilityGUID
   machineGUID
   timestamp
machines
   machineGUID
   localGUID
   timestamp

Register new entity

Generate private/public keypair Fill out details into entityHandle, calculate entityGUID=hash(entityHandle) Store entityGUID in repository together with public key

Register a capability

After negotiation, issuer generates a file

capability =
{
   receiver: {
       entityGUID: entityGUID,
       allowances: {...}
   }
   issuer: {
       entityGUID: entityGUID
       signature: issuer signature of this capability data (minus signature)
   }   
}

On the user's end we can verify the correctness of this file by verifying the signature with the issuer public key in the repo.

The issuer registers the hash(capability) = capabilityGUID in the repo. machineGUID is empty.

If the machine does not know its userGUID, it will ask the user for its handle and password, and calculate the userGUID, and store it locally.

The machine also calculates its machineGUID.

When the machine needs the capability, it verifies that the userGUID in the capability matches.

calculate hash(capability)

Then it looks in the repo for a machineGUID + capabilityGUID. If present, capability is granted.

If not present, but capabilityGUID is not assigned yet, the capability is granted

If not present, and capabilityGUID is already assigned, user is informed and capability is reassigned if desired.

Story: registering at the repo

A user needs to register at the repo.

They fill out a local file with some data. At the minimum, they will provide a user name.

entityDescriptor = { name: "some name" }

entityPassword: provided by the user

enetityEmail: provided by user

entityGUID = hash(entityHandle + hash(entityPassword))

User generates a public/private key pair.

Upload (entityGUID, public Key, entityEmail) to repository.

Calculate hash(entityEmail) and make sure neither entityEmail nor hash(entityEmail) is already registered.

Send confirmation email to entityEmail. If no confirmation in x amount of time, delete record.

If confirmation received, replace entityEmail field with hash(entityEmail)

User is now registered.

Database only retains entityGUID, publicKey and hash(entityEmail)

Story: Issuing a capability

A registered user issuerEntityGUID wants to issue a capability to another user, consumerEntityGUID.

The issuer generates a file

capability =
{
   receiver: {
       entityGUID: consumerEntityGUID,
       allowances: {...} // whatever data, describes the capability
       salt: randomGUID
   }
   issuer: {
       entityGUID: issuerEntityGUID
   }   
}

This file is then signed with the issuer's private key and a field is added

capability =
{
   receiver: {
       entityGUID: consumerEntityGUID,
       allowances: {...} // whatever data, describes the capability
       salt: randomGUID
   }
   issuer: {
       entityGUID: issuerEntityGUID
       signature: issuerSignature
   }   
}

capabilityGUID = hash(capability)

The issuer now registers the capability in the repository and creates a new record

   issuerEntityGUID
   capabilityGUID
   machineGUID -> empty

The issuer then sends the capability file to the consumer.

Story: the user's computer needs to verify its localGUID

The system reads some locally stored prefs:

hardwareGUID
localGUID
repoTimestamp

All of these could be empty/undefined.

The system recalculates the hardwareGUID.

If the prefs were empty, or if the hardwareGUID is different than the value from the prefs, a random new localGUID is generated.

In all cases, the computer then interacts with the repo and sends (localGUID, repoTimestamp).

If the repo could not find a matching record, a new record is created and the repo will generate another random localGUID and store it in a new record. It will also generate a new random machineGUID.

Then the repo samples the repo clock and stores the current date and time in the repoTimestamp field of the record.

The repo then replies to the user with the (possibly changed) localGUID and the new repoTimestamp.

The computer now stores the localGUID, the new repoTimestamp and the latest hardwareGUID in the local preferences for future reference.

The computer now has a valid localGUID.

The computer is not aware of its machineGUID - only the repo knows what that is.

Story: some capability is needed

The computer has a local capability file which could provide the needed capability.

The computer verifies the signature of the embedded issuerGUID agains the public key in the repo.

The computer compares the userGUID with the consumerEntityGUID of the local capability file.

The computer now sends the capabilityGUID and its localGUID to the repo.

The repo determines the machineGUID from the localGUID, and then checks whether the capabilities table has a record (capabilityGUID, machineGUID). If not it checks for a record (capabilityGUID, empty), and if found, stores the machineGUID in the record.

If the entry is available, the capability is granted.

If the entry is not available, the capability is denied.

If the capabilityGUID is available but associated with a different machineGUID, the user is warned, and if the timestamp on record is sufficiently old, the machineGUID is replaced and the capability is granted.