The Storage Kit uses the concept of ZCap-LD to build a capability-based authorization, but with a modified specification.
This framework provides functionality such as sharing and managing confidential data by using capabilities. In this document any ZCap-LD capability data model is using the JSON format. A ZCap-LD capability represents several attributes:
a context definition
an associated id
an invoker, which represents a nonce
a parentCapability, which contains the whole parent ZCap-LD capability and not only a reference to the capability.
a proof field, which signs the capability with a Linked Data Proof to verify the capability. It also contains a proofPurpose to indicate if it is a capability delegation or invocation.
The field proof contains the following attributes:
"created" represents the exact date and time when the capability delegation was created
"creator" shows the key, a nonce, of the creator
"jws" is a claim signed with a signature. The server can verify the claim with a secret signing key. So the JSON Web Signature (jws) claim signature can be seen as a private key and the server’s secret signing key as the public key. With this the server is able to verify the proof.
"purpose" a string to show if it is a delegation or invocation.
"type" is used to indicate which digital signature the proof includes.
"verificationMethod" represents a key to verify the delegation
The root ZCap-LD capability contains another attribute called "rootCapability". It represents the associated EDV. An EDV is an encrypted data vault. This EDV can be seen as a root of trust. The EDV grants permission to the root capability and the root capability is able to grant permission to a child and so on.
Any capability instead of the target capability needs to have a "parentCapability" property. It points on another capability or at the target. Several capabilities together form a capability chain.
In ZCap-LD delegation is handled via the capability chain.
Example:
The example represents attributes which are needed to create a ZCap-LD capability delegation. Any capability needs an unique id. This id is a simple uuid (Universally unique identifier). In this example the edv delegates permission to the root capability. So the edv serves as the invoker. The attribute invoker is represented as a did:key, nonce, starting with "z6Mk...". To verify this delegation there is a proof attribute. It contains important details: the capability was created on the 19th of december 2021 at 10:42 and 14 seconds, the key of the creator starting with "z6Mkp...", the jws starting with "eyJi...", the proof purpose shows that this capability is a delegation, it includes a digital signature produced by an ed25519 cryptographic key and the key to verify the delegation starting with "z6Mkk...".
At first the proof itself needs to be verified. This can be done by checking the jws attribute. After that the delegation can be verified by comparing the verification method and the invoker. In this example the delegation verification is successful because the key of the "invoker" property and the key of the "verificationMethod" property are equal. At the end there is an attribute called "rootCapability". It is a reference to the associated edv. The root capability can be compared to a root of trust component. It ensures that this delegation can be trusted.
In ZCap-LD an invocation is used to authorize a further capability delegation. It contains a property called "action". This property represents the behavior of an invocation. The "action" property consists of 3 parts. What should be performed, the document id to identify the right document and the content encrypted as a SHA256 of the content.
Example:
At first the initial capability needs to be created and verified. This is done by the attribute "parentCapability". It is a capability delegation. This delegation example is described in the delegation part of this document. Then the invocation will be created. The action attribute tells what the invocation is about. In this case the system will create a new document with the name "testDocument" and the content encrypted as a SHA256ofContent. Like the delegation an invocation includes an unique id, an invoker and a proof field. This capability invocation was created on the 19th of December 2021 at 10:44 and 1 seconds, the key of the creator starts with "z6Mkk...", the jws starts with "eyJi...", the proof purpose shows that this capability is an invocation, it includes a digital signature produced by an ed25519 cryptographic key and the key to verify the invocation starts with "z6Mkk...".
To verify that the invocation has the permission to take place its proof needs to be verified. After that the attribute "verficationMethod" of the initial capability needs to be the same as the "creator" attribute of the invocation capability. In this example both keys are equal, so the initial capability grants authority to the invocation and the document will be created.
A caveat can be used to restrict a capability. In many cases it is useful to define restrictions how the capability may be used. For child capabilities caveats don’t need to be redefined, because every capability inherit all the caveats from their parents. Caveats are identified by their types and other properties. The following code example shows how a caveat has to be declared in JSON format.
Example:
A secure authorization system is a vital part of a Confidential Storage solution to protected data from misuse, such as data manipulation or data theft. This is true for data storage and data transfer as data must be processed confidentially and may only reach those who have the respective right to access the data.
ZCap-LD uses the object capability model to grant and express authority. Its main function is to securely share and manage data. We opted for a capability-based system (instead of a traditional access control list based system).
To understand capability-based systems it is useful to start with the concept of capabilities:
Basically, a capability consists of a token or a key. The owner uses it to verify that he/she has permission to access an entity or object. It is implemented as a data structure consisting of the access rights and a unique identifier:
This identifier points to a specific object. The access rights declare which operations may be performed. For example, the access rights define a read-only access on a file, or a write access on a memory segment.
In a capability-based system, each user has access to a capability list. With these capabilities the system is able to check if the user is allowed to interact with the object.
A capability protects the object from unauthorized access, but the whole concept is useless if a capability is not protected from manipulation. If a program could change the access list and the identifier of a capability at any time, the program would be able to force access to any object. Therefore, a capability-based system is usually built in such a way that direct modifications by a program are not allowed. So the capability list can only be modified by the operating system or the hardware. What programs can do is to call operating system or hardware operations. That means programs can get new capabilities, delete capabilities or change the rights in a capability.
The goal of an authorization system is to protect confidential data. Conventional systems only partially perform this important task. Capabilities can be used to prevent processes from gaining access to data for which they do not have permission. This means a process is allowed to access capabilities which are necessary to only access the resources that the process needs. This ensures that no confidential data is revealed without having the right permissions to access this data.
The concept of capabilities can be well combined with sandboxing (i.e. the creation of an isolated test environment in which it is safe to execute suspicious URLs or files). Capabilities can be used to grant access to all data associated with the program. That means capabilities are used to sandbox every process in the program and giving it access to all associated data. This prevents the program from gaining access to sensitive data located on the other side (i.e. on the user’s desktop).
By advancing the existing basic ZCap-LD implementation with the ZCap-Caveats extension system, it is now a full-blown ZCap-LD issuance and verification system.
ZCap-based capabilities may also include ZCap-Caveats.
ZCap-Caveats allow users even tighter control control on who can access what data in which specific circumstances. These ZCap-Caveats can also be set at multiple levels of delegations, thus allowing a user to restrict access to their documents, and a service setting ZCap-Caveats in a delegation to a sub-service, further restricting access to the users data.
An overview is shown here:
The graphic above shows how capabilities work in the chain (and how we utilize them):
The EDV delegates access from the Root-of-Trust DID (of the EDV), to the user. The user receives a capability delegation without any caveats, so the user has full access, not only to the EDV, but also to delegate access to others.
When the user delegates access to a service, it is possible (and recommended) to include so called "Caveats" in the capability chain. These provide various restrictions, starting at the layer at which they have been included.
The services then creates a capability invocation from the (restricted) capability delegation, naturally the caveats are thus also in the capability chain. If the service tried to remove the Caveats from the delegation in the chain, the capability delegations signature would not match anymore.
In the example featured in graphic above, the following caveats were added to the capability delegation:
NoSubdelegationsAllowed - This caveat disallows the service from sub-delegating access to a sub-service/child-service (e.g. contractors).
ValidUntil - This caveat will expire the capability automatically at the specified date. At or after this date, the capability delegation is no longer valid, thus no (positive-verifiable) capability invocation can be constructed from the chain.
AllowedOperations - This caveat restricts the service to only being able to execute a specified set of operations (READ, CREATE, UPDATE, DELETE). In this case, the service may only read documents, and is disallowed from writing, updating or deleting any documents from the EDV.
AllowedDocuments - This caveat restricts the service to only allow operations on a specified set of documents. This is the primary caveat we are using for document sharing.
CredentialStatus2020 - This caveat allows easy revocation of the capability. When the capability is verified, the specified host will be queried using the CredentialStatus2020 protocol if a specific ID has been revoked. If this is the case, the capability will not be verified positively.
These are the capabilities currently integrated into our ZCap-LD module. However, these are not the only ones we support, as built a plugin-like system for creating and integrating new restrictions in the form of ZCap-Caveats. They even be dynamically registered at runtime, as the plugin system is based upon dynamic reflective access.