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.