KeySSI (RFC-002)
The proposal has been accepted and has an implementation.
Document Maintainers: Andi Gabriel Tan 2024. List of other contributors in Annex. 1.
Copyright: MIT license
Copyright© 2018-2024 Axiologic Research and Contributors.
This document is licensed under MIT license.
- Abstract
- 1. Introduction
- 2. Syntax of KeySSI identifiers
- 3. Trustless KeySSI Resolvers
- 4. KeySSIs families
- 5. KeySSIs common functions
- Function keySSI.autoLoad(identifier)
- Function keySSI.cast(newType)
- Function keySSI.clone()
- Function keySSI.getAnchorID()
- Function keySSI.getControlString()
- Function keySSI.getDLDomain()
- Function keySSI.getDSURepresentationName()
- Function keySSI.getHint()
- Function keySSI.getIdentifier(plain)
- Function keySSI.getName()
- Function keySSI.getRelatedType(ssiType, callback)
- Function keySSI.getSpecificString()
- Function keySSI.getVn()
- Function keySSI.load(subType, dlDomain, subtypeSpecificString, control, vn, hint)
- Annex 1. Contributors
Abstract
This RFC introduces one of the main components of OpenDSU: the concept of KeySSIs (Self-Sovereign Identifiers). We will go through:
- The syntax of the identifiers and how they are constructed;
- The key resolution that is necessary to retrieve all key information embedded in the identifier;
- The different KeySSI families that were designed for different use cases, their specificity and the functions that are specific to each family;
- The functions that are common to all KeySSIs and necessary to get useful information about our keys.
Note: For creating different types of keySSIs, the code can be checked at KeySSI (RFC-068).
1. Introduction
The purpose of the KeySSI concept is to provide blockchain-anchored identities for things and processes but potentially also for companies and individuals. The concept of KeySSI is more general than the concept proposed by the W3C DID web standard. DIDs and KeySSIs are two different methods of creating SSIs (Self-Sovereign Identifiers).
An important innovation offered by KeySSI is that the keys are used as secret (symmetrical) encryption/decryption keys for DSUs (or parts of DSUs).
Ideally, for security reasons, KeySSIs should be self-certifying SSIs. “Self-certifying” means that the resolved DSU contains enough information to validate the ownership of the SSI. The self-certification properties are typically a result of using the hash of a public key as part of the identifier. This way, when a DSU is obtained from the resolver, it is possible to verify the authenticity of the DSU; the owner should sign it.
A KeySSI never comes alone but in a group that we call a family. Each KeySSI family is accompanied by lower-level KeySSIs derived from the highest-level key. Derivation can be understood as a form of access delegation: someone who holds a KeySSI with a higher access level can delegate access to lower levels.
Typically (but not always), KeySSIs are anchored in ledgers for integrity and traceability using a special KeySSI called Zero Access SSI (szaSSI). Having a szaSSI gives the user access only to a list of hashes (the versions of the anchored DSU) but nothing else. Without an upper-level KeySSI, the szaSSI has no practical value except giving access to the number of versions of a DSU.
API note: The KeySSI (RFC-068) is used to create the different KeySSIs.
2. Syntax of KeySSI identifiers
The syntax of KeySSI is inspired by the W3C DID and is similar to it, but has several key differences, such as - it starts with the “ssi” string. It allows users to define additional attributes, such as types, ledger domains etc. Equivalent to the DID method string, SSI also consists of types (or subtypes). The purpose of types is not to introduce incompatible methods to W3C DIDs, but rather to add different types of KeySSIs. The different KeySSI types are designed to be compatible, which allows for a standard KeySSI resolver to implement all the standard types. Another unique aspect of the SSI syntax compared to the W3C DIDs is that the 3rd group in the identifier represents a ledger/blockchain domain. OpenDSU is based on the objective that a KeySSI supports multiple hierarchical ledgers/blockchains. The current definition of the blockchain domain and the proposed implementation on resolving these domains are part of the OpenDSU specification and may be found in the BDNS chapters.
Figure 1: Syntax of KeySSI Identifiers
Examples:
ssi:seed:ePI.pharma:RANDOMSEEDKEY:HASHRANDOMKEY:vn
ssi:za:ePI.pharma:HASHSERIALISATION:HASHPUBLICKEY:vn
Figure 2: Syntax of KeySSI Identifiers
The “Type Specific Substrings” contain strings that typically should contain enough random bits for good security.
The “Control Substring” part of the KeySSI is used by the anchoring services to validate the requests for a new version of the anchored DSU. The algorithm used for verification is type-specific.
The “vn” field is a string reflecting the version number of the type. The vn should not be confused with DSU versions: vn refers to the version number of the KeySSI type. The “vn” field is optional; if missing, it defaults to “v0”. The OpenDSU standardization body should approve each new version. Each version has an associated configuration that specifies the cryptographic primitives and conventions, detailed in a separate OpenDSU RFC. For example, these RFCs will specify what hash functions and what methods should be used by the anchoring service.
The “hint” part is optional and subtype-specific. Typically, it hints at some optional information for the KeySSI resolver, for example, the favorite server proposed by the owner of the KeySSI.
This part could also be called “tag” as it is a way of tagging KeySSIs for specific purposes, for example, to tag a DSU containing sensitive information to help indicate that it will require additional data protection mechanisms. This “Hint” or “Tag” extends the KeySSI for countless purposes that could not be imagined now.
3. Trustless KeySSI Resolvers
The primary purpose of standard KeySSI resolvers is to be able to use an SSI identifier to create or load a specific DSU instance. Information embedded in the keySSI will give the resolver everything it needs to ensure the DSUs are stored securely through encryption. Key derivation is also used to give different access rights, and the resolver will ensure these rights are applied when reconstructing a DSU.
Figure 3: KeySSI Resolvers role
KeySSI Resolvers are libraries loaded in the DSU reconstruction environments. OpenDSU implements client-side encryption, therefore avoiding the need for any delegation of trust to any intermediaries or certificate authorities. The KeySSI resolver can call an adapter to a ledger or blockchain and call the Brick Storage, but its usage of any other intermediary Web API is not recommended. The node doing the resolving (the DSU reconstruction environments) should provide the result as an instance of a DSU. The reconstruction environment of DSUs should handle the decryption and the other operations required for resolving a KeySSI to a DSU.
The KeySSI Resolvers should benefit from the BDNS (Blockchain Domain Name System) and other schemes to create a trustless KeySSI resolver so that, when possible, there should be multiple “gateways” for the “anchoring service” as opposed to just one. The “anchoring service” is located where a specific anchor is stored in the ledger. When required, a multiple gateways approach will introduce better decentralization and security, since the difficulty of attacking the network increases with the number of nodes making up the network (see implementation recommendations).
4. KeySSIs families
Depending on the use case, different types of KeySSIs can be used. This table summarizes the different families of KeySSIs and references the links for more detailed information.
Family | Description |
---|---|
SeedSSIs | SeedSSI identifiers are a good method for identifying DSUs that are not shared with many people. A good example is the DSUs that implement some form of digital wallet for users and companies. |
ConstSSIs | Aim to provide human-readable identifiers that can be remembered easily.This RFC also contains information about ArraySSI, WalletSSI and PasswordSSI, since they are all derived to obtain constSSIs. |
HashLinkSSIs | Brick-pointing KeySSIs that allow finding and decrypting un-anchored bricks/DSUs. |
SymetricalEncryptionSSI | SymetricalEncryptionSSIs are used with HashLinkSeedSSIs for bricks’ construction and reconstruction. |
5. KeySSIs common functions
KeySSIs share a set of common functions. They serve to initialize KeySSIs with desired parameters or to get their parameters when they are needed.
How to use KeySSI functions:
variable = keySSI.function();
dlDomain = keySSI.getDLDomain();
seedKeyIdentifier = seedSSI.getIdentifier();
Function keySSI.autoLoad(identifier)
Description: Load parameters for KeySSI from a keySSI Identifier.
Name | Type | Value | Description |
---|---|---|---|
identifier | String | *required | A string that uses the keySSI identifier syntax. Ex: ssi:za:domain:specificStr:control:vn |
Returns: This function does not return anything; it just changes the type of the existing key.
Function keySSI.cast(newType)
Description: Is used to create a new type of KeySSI from a similar KeySSI. You should first create a well-known keySSI, then use the cast function to change the type.
Name | Type | Value | Description |
---|---|---|---|
newType | String | *required | A string that uses the KeySSI identifier syntax. |
Returns: This function does not return anything.
Function keySSI.clone()
Description: Create a clone of an already existing keySSI.
Returns
Name | Description |
---|---|
KeySSI Object | A clone of your KeySSI |
Function keySSI.getAnchorID()
Description: Retrieve the keySSI anchor identifier.
Name | Description |
---|---|
String | Your KeySSI anchor Identifier. It is used for Anchoring operations |
Function keySSI.getControlString()
Description: Retrieve the keySSI control string.
Name | Description |
---|---|
String | Your KeySSI control string. It is used for Anchoring operations for validation purposes |
Function keySSI.getDLDomain()
Description: Retrieve the keySSI DL Domain.
Name | Description |
---|---|
string | Your keySSI DL Domain. It represents the ledger/blockchain domain name, and the personal key that was created and used. More info in BDNS |
Function keySSI.getDSURepresentationName()
Description: Retrieve the keySSI DSU Representation Name.
Name | Description |
---|---|
String | Your keySSI DSU Representation Name. This function is not fully implemented and will only return “RawDossier” if your key is from the seed subtype |
Function keySSI.getHint()
Description: Retrieve the keySSI hint (tag).
Name | Description |
---|---|
String | Your keySSI hint. The hint is optional for keySSI but can contain helpful information for the resolver. |
Function keySSI.getIdentifier(plain)
Name | Type | Value | Description |
---|---|---|---|
plain | string | *required | Enter true if you want the identifier in the ssi format (ssi:za:domain:specificStr:control:vn). Else the identifier will be encoded in Base58. |
Returns
Name | Type | Response example |
---|---|---|
plain | boolean |
Function keySSI.getName()
Description: Retrieve the keySSI subtype name. This function is obsolete, please use keySSI.getTypeName() instead.
Returns: The subtype name (e.g.: seed, sza etc.) for your KeySSI.
Function keySSI.getRelatedType(ssiType, callback)
Description: Get the KeySSI that is related to your KeySSI and that is derived from the selected “ssiType”. A keySSI is returned if the ssiType can be derived from your KeySSI. It works only for lower subtypes for security reasons.
Name | Type | Value | Description |
---|---|---|---|
ssiType | string | *required | The ssi type you want to derive from your key.Need to be from the same family and at a lower level than your keySSI. |
callback | function | *required |
Callback parameters
Name | Type |
---|---|
err | Error object |
relatedKeySSI | KeySSi object |
Description: Error message and the error. / The KeySSI of the selected type if it can be derived from your key. If it is the same subtype, it will return the same key.
Function keySSI.getSpecificString()
Description: Retrieve the keySSI specific string.
Returns
Name | Description |
---|---|
String | Your keySSI specific string. The specific string is a string that should contain enough random bytes for good security. The more the key is at a higher level, the more it should be secure.Public keySSI, like sza KeySSIs do not need this string |
Function keySSI.getVn()
Description: Retrieve the keySSI version number.
Returns
Name | Description |
---|---|
String | Your keySSI Vn (version number). It represents the version of your keySSI so your resolver knows how to deal with it. |
Function keySSI.load(subType, dlDomain, subtypeSpecificString, control, vn, hint)
Description: Change the parameters of a KeySSI to replace the existing one.
Name | Type | Value | Description |
---|---|---|---|
subType | string | *required | TSubtype name of the keySSI. |
dlDomain | string | *required | Blockchain/ledger domain name of the keySSI. |
subtypeSpecificString | string | *required | The subtype specific string of the keySSI. |
control | string | *required | The control substring. |
vn | string | *required | The version number of the keySSI type. |
hint | string | *required | Additional information for the keySSI. |
Returns: This function does not return anything.
Contributors
-
Axiologic Research: New content and improvements. Original texts under PharmaLedger Association and Novartis funding. MIT licensed content accordingly with the contracts. Publish and maintain the www.opendsu.org site.
</p>
-
PharmaLedger Project: Review, feedback, observations, new content, and corrections MIT licensed accordingly with the consortium agreements.
</p>
- PrivateSky Research Project: MIT licensed content accordingly with the contracts. https://profs.info.uaic.ro/~ads/PrivateSky/
Annex 1. Contributors
Current Editors | |
---|---|
Sînică Alboaie | sinica.alboaie@axiologic.net |
Cosmin Ursache | cosmin@axiologic.net |
Teodor Lupu | teodor@axiologic.net |
Andi-Gabriel Țan | andi@axiologic.net |
Contributors Axiologic Research | |
Adrian Ganga | adrian@axiologic.net |
Andi-Gabriel Țan | andi@axiologic.net |
Cosmin Ursache | cosmin@axiologic.net |
Daniel Sava | daniel@axiologic.net |
Nicoleta Mihalache | nicoleta@axiologic.net |
Valentin Gérard | valentin@axiologic.net |
PrivateSky Contributors | |
Alex Sofronie | alsofronie@gmail.com (DPO) |
Cosmin Ursache | cos.ursache@gmail.com (UAIC) |
Daniel Sava | sava.dumitru.daniel@gmail.com (HVS, AQS) |
Daniel Visoiu | visoiu.daniel.g@gmail.com (SGiant) |
Lenuța Alboaie | lalboaie@gmail.com (UAIC) |
Rafael Mastaleru | rafael@rms.ro (RMS) |
Sînică Alboaie | salboaie@gmail.com (UAIC) |
Vlad Balmos | vlad.balmos@gmail.com (Code932) |
PharmaLedger Contributors | |
Ana Balan | bam@rms.ro (RMS) |
Bogdan Mastahac | mab@rms.ro (RMS) |
Cosmin Ursache | cos@rms.ro (RMS) |
Rafael Mastaleru | raf@rms.ro (RMS) |