9.8 KiB
BSIP: 0040
Title: Custom active permissions
Authors:
Alex Megalokonomos <https://github.com/clockworkgr>
Fabian Schuh <https://github.com/xeroc>
Stefan Schießl <https://github.com/sschiessl-bcp>
Status: Draft
Type: Protocol
Created: 2018-07-25
Discussion: https://github.com/bitshares/bitshares-core/issues/1061
Worker: <Id of worker proposal>
Abstract
Strengthening user security is one of the main factors to elevate BitShares. In light of recent hacking and phishing attempts this becomes even more important. The need for a more sophisticated account security preceeded the idea for a finer-grained control of account permissions. We propose to add an additional authority to the account, called Custom Active (Permission). The permission contains a list of operationid-to-authority mappings that each grant access to the respective operation as if it were the active permission of the account. Additionally, the arguments of said operation can be restricted.
Motivation
Any successfull hacking or phishing attempt on any of the web wallets that are powered by the BitShares Blockchain is bad publicity. The user needs to be educated in account security, and this BSIP aims to ensure all technical possibilities are met while being flexible to allow many use-cases.
With this BSIP any user can create keys with specific purpose (everything else is prohibited). We list some possibilities below:
- Witness Key: Only allows update signing key and publish price feed
- Trading Key: Only allows limit orders (arguments restricted to desired markets), update margin position and transfers (arguments restricted to certain accounts)
- Proposal Update Key: Approve proposals (2FA comes to mind)
- Faucet Key: Allow only to create accounts
- Withdrawal Key: Allow another account to transfer funds to himself
- Cold Storage Key: Only allow to move funds to the Hot Wallet
The above list of named keys is nothing that is known to the backend as the backend should have an abstract implementation. The UI could provide a button "Create Trading Key" that properly configures the respective custom active permission entry.
Rational
Custom active permission is a list of custom active authorities
. A custom active authority
contains an operation_id
, an authority
(just like with active permission) and asserts
than can be used to restrict arguments and is only valid a certain time period (valid_from
and valid_to
). When handling incoming signed transactions, the backend checks for each operation if there is a custom active authority
for any of the required accounts. If all operations within the transaction have a matching custom active authority
(match means same operationid
, now is within valid_to
and valid_from
and all asserts
pass), then active authority of the corresponding account is granted.
Specification
All descriptions in this section are on a pseudo/prosa level and no recommendation how it can best be implemented or serialized. They are meant to facilitate the understanding.
Custom active permission and custom active authority
A custom_active_permission
looks like follows (in JSON/pseudo for clarification):
custom_active_permission = list of custom_active_authority items
custom_active_authority = {
valid_from, // timestamp when this is active, defaults to now
valid_to, // timestamp when this is invalid, defaults to 1 month
operationid, // operationid of the target operation,
authority, // same as for the existing authortities (multisig with weighted accounts or keys),
asserts // see below
}
Note: This assumes custom_active_permission
is stored within account_object
. Actual implementation details left to the implementer, as long as every custom_active_permission
can be assigned to exactly one account.
Asserts
The asserts
is a list of assert_objects
that are all together evaluated with and
logic to evaluate a match
asserts = list of assert_objects
assert_object = {
argument, // target argument of the operationid
function, // functionid to do the assert
data, // stores data specific to the chosen function
state // if this assert is statefull
}
List of possible asserts are:
function | data | state |
---|---|---|
any |
[list , of , allowed , values ] |
stateless |
range |
[min , max ] |
stateless |
length |
[min , max ] |
stateless |
limit |
[max_cumsum , interval_in_sec ] |
[current_cumsum , interval_began ] |
limit_monthly |
[max_cumsum , interval_in_months ] |
[current_cumsum , interval_began ] |
All asserts apply to int
, string
and object_ids
. There is no type converstion, incompatible type means assert failure. Any more sophisticated data types are not included yet.
any
Stateless assert, all argument types. Value of argument must be equal to one of values in the list
range
Stateless assert, only int
type arguments. Value must be inbetween min
and max
, inclusive. One of the bounds can be empty to indicate unlimited.
length
Stateless assert, only string
type arguments. Length of string (or encrypted string in case of memo) must be within min
and max
, inclusive. One of the bounds can be empty to indicate unlimited.
limit
Statefull assert, only int
type arguments. When the authority is created, interval_began
is set to valid_from
from its custom active authority and max_cumsum
to 0
. Incoming operations are first tried to match all stateless asserts,
and if all passes continue with statefull asserts. If now > interval_began + interval_in_sec
, then set max_cumsum = 0
and set interval_began = now
.
The assert that needs to pass is now current_cumsum + incoming value <= max_cumsum
. If all asserts are passed, update current_cumsum = current_cumsum + incoming value
of all involved statefull asserts.
limit_monthly
Statefull assert, only int
type arguments. Analogue to limit
, but interval_began
is initially set to month(valid_from)
and set to month(now)
on update, additionally the time assert is month(now) >= interval_began + interval_in_months
(include logic for month overflow when year changes).
Simple Example
Assume account A and B and some unrelated key K. Furthermore A has a custom active authority in the following way:
custom active authority = {
valid_from: 7.7.2018 00:00
valid_to: 8.7.2018 00:00
operationid: transfer,
authority: {
threshold: 1
key_auth: [K, 1]
account_auth: []
},
asserts: [
{
argument: to
function: any,
data: [B]
}
]
}
That has the consquence now that a transfer transaction sending funds away from A can be signed with key K as long as the receiver is B.
Note: This is just an illustration of a possible serialization, not a specification of the serialized format.
Outline of handling incoming transactions
When a signed transaction arrives and before the backend evaluates if all necessary authorities are present through the signatures, do the following:
- iterate over required accounts and for each account, iterate over all operations within the transactions that require the active authority of this account
- iterate the
custom_active_authorities
of said account - if a
custom_active_authority
is found that matches (sameoperationid
and passes allasserts
), remember that and stop iterating the authorities and continue until all operations are checked - if the account has a
custom active authority
match for every operation in the transaction that requires it, then grant theactive authority
of said account. If no match is found, treat as if no authority was given
Note:
- A
custom_active_authority
can only grant theactive authority
of the corresponding account, nothing more
Modification to the backend
- Extend the account object to store custom active permission that includes a list of custom active authorities. Multiple custom active authority entries are possible for one operation
- If the active authority of the account is updated, all custom active authorities need to be confirmed in the update. Every unconfirmed one is deleted otherwise
- Extend
account_update
or create a new operation to allow changing the custom active permission - Operation-specific authorities (if present) must be evaluated in incoming transactions
- Additional committee parameters may be needed to limit the extend of usage of this feature
Notes: The implementation must not differentiate on which operation the custom active authority is applied, all operations are treated in same fashion
Milestones
We propose do split the implmentation into two milestones:
- Implementation of basic functionaliy to allow custom active permissions and authorities, including
range
,length
andany
asserts
- Evaluation of stateful asserts (performance) and if positive, implementation of
limit
andlimit_monthly
asserts
This approach allows as well to add other asserts at a later stage (with a new BSIP).
Discussion
To be found in the issue.
Summary for Shareholders
Bad publicity in terms of security can have very negative effect on the BTS value. This BSIP allows that traders can e.g. use a trading key, witnesses can use their witness key and a faucet can use a faucet key. If then for some reason the key or witness/faucet server becomes compromised, such a key can do little harm to the account holders, minimizing the risk.
This BSIP opens up a lot of use-cases as presented in Motivation section. The intention is to not alter any existing logic of the permission system, which reduces the risk of malfunctioning.
Copyright
This document is placed in the public domain.