Identity Manager Design
Last updated
Last updated
Note that the examples in this documentation are provided in JavaScript and are derived from the signata-web source code. The examples are one way to achieve the desired results for on-chain interactions, but are not the only way to do so.
The Signata Identity Manager is a dedicated application for the creation and management of web3 identities within an organization. It serves as the equivalent of an enterprise identity manager, but for self-sovereign web3 identities. With the Signata Identity Manager, users can create and manage all of their web3 identities within a single interface and prepare them for use with Signata Identity Providers. Signata uses blockchain technology as decentralized identity registers, ensuring that every Signata identity can be consumed within smart contracts and that users retain control over their identity state.
An "Standard" identity is created with 3 keys, an Identity key, a Delegate key, and a Security key.
Each time a private key is used for any publicly-available information (such as digitally signed records), the risk of key material compromise will increase through known-plaintext attacks. Most Public Key Infrastructure systems enforce key life limits (typically 1 to 2 years) on an active key, rolling over to new keys before the key could theoretically become compromised.
Signata will not enforce key lifespan lengths for identities, however the use of the 3-key identity lifecycle model will help to mitigate any risk of exposure through prolonged use of an identity, and also allow for simple rollover to a new set of keys if a user suspects any compromise.
The recommended approach to handling keys with Signata identities is to use 3 separate BIP-39 seeds for deriving the 3 keys needed to create each identity.
The identity key is the core identity identifier. This key is intentionally "useless" in the context of lifecycle management with Signata. That is, it cannot be used to perform lifecycle event management of itself, just to ensure the key material is not used extraneously. It will bear all rights assigned to it, and be used for proving ownership, but all lifecycle events are instead handled by the Delegate Key.
The delegate key is the lifecycle management key for a Signata identity. It is used to lock, unlock, destroy, and rollover identities after they are created.
It is not recommended that these keys be derived from the same seed as the identity key, otherwise a seed compromise will immediately compromise this key as well.
The security key is a fallback key, specifically designed to provide recovery mechanisms in the event of a compromise. In ideal circumstances this key should never be needed to be used, it will only be used for important lifecycle events.
It is not recommended that these keys be derived from the same seed as the identity key, otherwise a seed compromise will immediately compromise this key as well.
Signata stores no identity data on its servers. All identity records you create are AES256 password-encrypted and stored on IPFS. The actual record stored on IPFS is the entire array object of user identities converted to a JSON string and encrypted.
An IPFS Name key is generated for new user accounts and stored on Signata servers. This Name key is used to provide a consistent link to the same IPFS record, and replace the link with updated records as users make changes.
Signata servers retain the IPFS file name, as well as the account wallet address that created it. This way the Signata Identity Manager doesn't need to retain that information to recover user data on load.
All modifications to identity data stored in IPFS require a signature from the wallet that is pinned to the account. This ensures no unauthorised user can overwrite stored user data. Whilst overwritten data would not be lost, it would be treated as a denial of service attack against users.
The standard identity contract requires unique counters for events such as locking, unlocking, and rolling over. These counters ensure that signed mutations cannot be replayed after use.
The create and destroy functions can only be executed once for each identity, and as such do not require counters to resist replay attacks.
The domain separator is used to constrain signatures generated for Signata to just the Signata dApp and resist phishing attacks. The EIP-712 standard explains this in detail:
Deriving the Domain Separator should be done for each chain to make sure you're capturing the correct values that are specified in the contract, as well as the specific chainId you're connected to.
An identity is registered within the SignataIdentity
contract using the following process:
A SHA3 Hash
is generated of the truncation of the TXTYPE_CREATE_DIGEST
, the Delegate Address
, and the Security Address
.
The SHA3 Hash
is digitally signed by the Identity Private Key
.
The SHA3 Hash
, the Identity Address
, the Delegate Address
, and the Security Address
are sent to create()
. The sender can be any address.
A Create
event is emitted from the contract upon successful creation.
All three keys must be distinct, and they cannot already be in use with another identity (that is, you cannot re-use any of the keys more than once).
The identity address must be provided with the signature to validate that the signature is actually signed by the same address.
0x1901
represents EIP-191 signed data, with 01
being the version number.
Alternatively, you can generate the signature components required in JS and then use Remix or Etherscan to make the chain call:
To prevent an identity being modified or used, such as in the event you believe it has been compromised, you can flag the identity as "locked". You will not be able to use the identity whilst it is locked, but the delegate can still perform a rollover to ensure any compromise can be mitigated.
A SHA3 Hash
is generated of the truncation of the TXTYPE_LOCK_DIGEST
, and the _identityLockCount
.
The SHA3 Hash
is digitally signed by the Delegate Private Key
.
The SHA3 Hash
and the Identity Address
are sent to lock()
. The sender can be any address.
A Lock
event is emitted from the contract upon successful creation.
To unlock an identity, the delegate
and security
keys are needed to digitally sign the authorization of unlocking.
A SHA3 Hash
is generated of the truncation of the TXTYPE_UNLOCK_DIGEST
, and the _identityLockCount
.
The SHA3 Hash
is digitally signed by the Security Private Key
.
The SHA3 Hash
and the Identity Address
are sent to unlock()
. The sender can be any address.
An Unlock
event is emitted from the contract upon successful creation.
Much like the destruction event, rollovers also need signatures from both the delegate
and security
keys. Rollover will transfer control of an identity address to new delegate and security keys, the identity itself will remain the same.
After this mutation has been made the old delegate and security keys can no longer be used.
Once an identity is no longer required, it can be destroyed to prevent further use. Identity destruction cannot be undone, it is permanent. If you wish to disable an identity temporarily, just lock it instead.
Identity destruction requires both the delegate
and the security
keys to digitally sign the authorization of destruction.
Also bear in mind that this is a blockchain and all the history of the identity will still remain on the chain after destruction. Destruction in this case simply means to prevent the key from ever being used again in the Signata identity ecosystem, and identity providers must honour the mutation that has been made.