FIO Identity

PLEASE NOTE: This is just a draft idea, exploring some possibilities of the FIO protocol. It is NOT final or even suggesting at this time a path for FIO to take.

The traditional financial world, for better or for worse, works with verified identity through KYC (Know Your Customers) and AML (Anti-Money Laundering) compliance requirements. Even though this is only 0.1% effective at preventing crime, it is the reality we live in today (until we change it). Some examples of the problem:

And yet, if FIO wants to help the billions of unbanked people who want access to decentralized open finance tools while also providing a decentralized (as opposed to centralized or federated) solution for those who still have to play the KYC/AML game, we should look at creating verified FIO addresss. Depending on the need, this may end up driving the decentralized business strategy for the FIO Protocol which benefits all participants as the network effect grows. Billions of people and the many thousands of organizations that want to serve them have a problem FIO is uniquely positioned to solve.

Problem

I want to interact with a real human being, not someone claiming to be someone else (or 1,000 someone else's). I don’t want to store the KYC or profile information for that human on my servers. I may not want to do KYC at all and just want verification that some other organization I trust did do KYC. If I do KYC, I want a mechanism to, with the permission of the human, expose aspects of that KYC to third parties, and be rewarded for it.

Imagine how much we could improve the credit process if Equifax, Experian, and TransUnion were decentralized and the data they collect was in our control?

Solution

I’ll walk through an example to explain how FIO might help with this situation.

John Doe controls the FIO address john@doe via their private key.

I want to interact with Organization A (kyc@a, account aaaaaaaaaaaa) which requires KYC. I go through whatever process they require (upload identity documents, FaceTec, etc). I also sign an authentication message with my john@doe private key, proving the human they just verified has control as of right now of john@doe. kyc@a derives from their key path two new secret keys. These key paths are stored in a vouches table scoped to aaaaaaaaaaaa to associate them with john@doe via data encrypted with kyc@a’s private key:

Table: vouches

index

scope

data

index

scope

data

0

aaaaaaaaaaaa

<encrypted text>

With data decrypted as:

fio_address

voucher_secret_key_path

voucher_data_secret_key_path

voucher_type

fio_address

voucher_secret_key_path

voucher_data_secret_key_path

voucher_type

john@doe

m/44'/194'/0'/0/1

m/44'/194'/0'/0/2

1

The voucher type of 1 would mean KYC. Other voucher types are described later.

The derived keys are then used to encrypt parts of a message on chain essentially saying “We’ve KYCed john@doe and collected the following information.” This data on chain might be stored in a vouchers table:

Table: vouchers

index

scope

voucher

voucher_data

index

scope

voucher

voucher_data

0

aaaaaaaaaaaa

<encrypted text>

<encrypted text>

The voucher content is encrypted with the secret from voucher_secret_key_path (the key from m/44'/194'/0'/0/1) and the voucher_data content is encrypted with voucher_data_secret_key_path (the key from m/44'/194'/0'/0/2). With each new entry, a new set of keys on the key path are used.

voucher
(decrypted via voucher_secret_key_path)

voucher_data
(decrypted via voucher_data_secret_key_path)

voucher
(decrypted via voucher_secret_key_path)

voucher_data
(decrypted via voucher_data_secret_key_path)

 

1 2 3 4 5 { "account": "abcdefghijkl", "fio_address": "john@doe", "data": ["first_name", "last_name", "date_of_birth", "country_of_citizenship", "country_of_residence"] }

 

1 2 3 4 5 { "account": "abcdefghijkl", "fio_address": "john@doe", "data": ["John", "Doe", "1/1/1980", "United States", "Puerto Rico"] }

kyc@a then presents information for john@doe to encrypt and sign which essentially says “Here’s the table index where kyc@a vouched for john@doe encrypted with this secret key.”

1 2 3 4 5 6 7 8 9 { "data": [{ "validator_account": "bbbbbbbbbbbb" "validator": "kyc@b", "vouchers_index": 0, "voucher_secret": "5KN6kXyaxs68b9QqauTf1g13FkawCPL4baVzwLy9NcozyzNcLtu", "voucher_data_secret": "5JM3esqkLk79MsF3pq9mYvjLRUciK4DUrCrj2GdAVfdNJhtaGRu" }] }

The voucher_data_secret could be used to verify the voucher_data was stored correctly. The voucher_data_secret could be stored by the user for later use or discarded.

This information would be used to construct a new transaction to add a record in the validations table, scoped for john@doe, like so:

Table: validations

index

scope

validation

index

scope

validation

0

abcdefghijkl

<encrypted text>

The decrypted validation content:

validator_acccount

validator_fio_address

vouchers_index

voucher_secret

validator_acccount

validator_fio_address

vouchers_index

voucher_secret

aaaaaaaaaaaa

kyc@a

0

5KN6kXyaxs68b9QqauTf1g13FkawCPL4baVzwLy9NcozyzNcLtu

This process is be repeated for organizations B (kyc@b), C (kyc@c), and D (kyc@d).

Organization E (kyc@e) authenticates john@doe and instead of asking for KYC, it presents a list of KYC validators or combinations of validators it will accept instead. For example, it could ask for Organization A (kyc@a) or Organization B (kyc@b) and Organization D (kyc@d) together or maybe some combination like “3 from the following list…”.

john@doe decides they trust Organization E (kyc@e)to know they have a relationship with kyc@b and kyc@d, but they’d prefer to keep their relationship with kyc@a private. john@doe sends an encrypted message via the chain with their shared key with kyc@e (similar to a FIO Request), with the following:

1 2 3 4 5 6 7 8 9 10 11 12 13 { "vouchers": [{ "validator_account": "bbbbbbbbbbbb" "validator": "kyc@b", "vouchers_index": 1, "voucher_secret": "5K3ztTvNeKrydGFLVPXYJJm5AzhXgo995B4kQtXXdvBZxVqssAb" }, { "validator_account": "dddddddddddd" "validator": "kyc@d", "vouchers_index": 3, "voucher_secret": "5KNygU3Qw8UdzXo5qBNouzk6Tyo8A5qf9yUDc2kYHPPA8SWf6yh" }] }

Organization E then verifies these vouchers on chain in the vouchers table using the vouchers_index and validator_account scope with the voucher itself decrypted with the voucher_secret. Note, they can only decrypt the voucher content with the voucher_secret, not the voucher_data content. This tells them which fields were validated, not the values themselves used for validation.

Organization E then saves a new record in the vouches table but with voucher_type 2 which essentially says “We acknowledge the identity of john@doe using validations we trust”:

New entry for vouches table:

index

scope

data

index

scope

data

1

eeeeeeeeeeee

<encrypted text>

with data being:

fio_address

voucher_key_path

voucher_data_key_path

voucher_type

fio_address

voucher_key_path

voucher_data_key_path

voucher_type

john@doe

m/44'/194'/0'/0/1

 

2

New entry for vouchers table:

index

scope

voucher

voucher_data

index

scope

voucher

voucher_data

1

eeeeeeeeeeee

<encrypted text>

 

Type 2 vouchers do not include voucher_data.

voucher
(decrypted with voucher_key_path)

voucher_data

voucher
(decrypted with voucher_key_path)

voucher_data

 

1 2 3 4 { "account": "john@doe", "data": ["kyc@b", "kyc@d"] }

 

1

New entry for validations table:

index

scope

validation

index

scope

validation

1

abcdefghijkl

<encrypted text>

The decrypted validation content:

validator_acccount

validator_fio_address

vouchers_index

voucher_secret

validator_acccount

validator_fio_address

vouchers_index

voucher_secret

eeeeeeeeeeee

kyc@e

1

5KN6kXyaxs68b9QqauTf1g13FkawCPL4baVzwLy9NcozyzNcLtu

Upon login to Organization D, if any of the validations used for verification have been updated for liveness, a new, updated record can be saved for that organization.

Useful Data

Some organizations presumedly want additional information about the user like their name or maybe their country, email, age, income, purchasing preferences, etc. Each time this information is requested, instead of giving it to the company which would then have to store it in a central location which becomes a target for data breaches and GDPR concerns, it can be stored encrypted on chain.

Table: profile

index

scope

field

value

vouchers

value_secret

index

scope

field

value

vouchers

value_secret

0

abcdefghijkl

first_name

<secret encrypted text>

<encrypted text>

<encrypted text>

1

abcdefghijkl

last_name

<secret encrypted text>

<encrypted text>

<encrypted text>

2

abcdefghijkl

email

<secret encrypted text>

<encrypted text>

<encrypted text>

Organizations can request specific data based on the fields in the profile or request a new entry be added. The value_secret can be shared with them so they can decrypt the content in the value field. They can not decrypt the content of the vouchers field. Both the vouchers and the value_secret are encrypted by john@doe’s private key.

value decrypted would be simple text like “John”, “Doe”, “john.doe@example.com”, etc.

vouchers decrypted would include:

1 2 3 4 5 6 7 8 9 10 11 { "vouchers": [{ "validator_account": "bbbbbbbbbbb", "validator_fio_address": "kyc@b", "vouchers_index": 0 }, { "validator_account": "bbbbbbbbbbb", "validator_fio_address": "kyc@b", "vouchers_index": 1 }] }

value_secret decrypted would be the plaintext secret used to decrypt this value.

The vouchers would be specific to the organizations which have vouched for that specific field value. The user can selectively choose which vouchers they want to expose when responding to a request for information.

The vouchers_index is the specific record in the vouchers table containing the voucher.

A response for information might look like:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 { "data": [{ "first_name": { "profile_index": 0, "scope": "abcdefghijkl", "value": "John", "value_secret": "5K7H5Ai2m86VFd3AByrX1d3R6Wbwv6dajJ4CvWHs3fCtkYVJ6yW", "vouchers": [{ "validator_account": "bbbbbbbbbbb", "validator_fio_address": "kyc@b", "vouchers_index": 1, "voucher_secret": "5K3ztTvNeKrydGFLVPXYJJm5AzhXgo995B4kQtXXdvBZxVqssAb" }, { "validator_account": "dddddddddddd", "validator_fio_address": "kyc@d", "vouchers_index": 3, "voucher_secret": "5KNygU3Qw8UdzXo5qBNouzk6Tyo8A5qf9yUDc2kYHPPA8SWf6yh" }] } }, { "last_name": { "profile_index": 1, "scope": "abcdefghijkl", "value": "Doe", "value_secret": "5KQFBfLWZPSvt4Z3GRh4Qv54UoLh1pfup7vnDV6dMZLCfCd786T", "vouchers": [{ "validator_account": "bbbbbbbbbbb", "validator_fio_address": "kyc@b", "vouchers_index": 1, "voucher_secret": "5K3ztTvNeKrydGFLVPXYJJm5AzhXgo995B4kQtXXdvBZxVqssAb" }, { "validator_account": "dddddddddddd", "validator_fio_address": "kyc@d", "vouchers_index": 3, "voucher_secret": "5KNygU3Qw8UdzXo5qBNouzk6Tyo8A5qf9yUDc2kYHPPA8SWf6yh" }] } }, { "email": { "profile_index": 3, "scope": "abcdefghijkl", "value": "john.doe@example", "value_secret": "5KSXxW9Uhiwuzf8ZfiC6yjeCaw94prVQHGmRyPR151hsmgxUzUx", "vouchers": [{ "validator_account": "bbbbbbbbbbb", "validator_fio_address": "kyc@b", "vouchers_index": 1, "voucher_secret": "5K3ztTvNeKrydGFLVPXYJJm5AzhXgo995B4kQtXXdvBZxVqssAb" }] } } ] }

The organization receives the information they need and can pull it from the chain in the future using the profile_index and scope. They have no need to store the information locally.

If the organization needed to validate this information, they could then look up the vouchers and send an encrypted message (via FIO Request) to a validator like kyc@a to validate the first_name of john@doe is “John” or answer a question like “Is john@doe over the age of 13?” Depending on the policies, kyc@a could ask for confirmation from john@doe via FIO Request before releasing the requested information to the organization.

Ideally we could add a “request for request” which would allow the validator to say “Send me a request for this amount so I can pay you for releasing this information to this organization.” The micro payment amount the organization pays to the validator when requesting the information would be more than the micro payment made to the person and the difference would be the validator’s profits.

Conclusion

This plan outlines a way for users to selectively validate their identity and personal information with multiple KYC vendors who don’t have to store the information on their local servers. Organizations requesting information can do so directly from the individual and receive a key to decrypt that information from the chain anytime they want it. They can also request validation of that information from the KYC provider that validated it. The user has the control to selectively expose which validators have verified their information and who can access that information in the future. The security focus of the validation company can now be entirely about key management instead of data management.

Areas for more exploration:

  • Zero knowledge proofs to ask questions about the data without needing the data itself.

  • Key rotation requirements to keep data freshly encrypted.

  • Potentially using transaction_id and the block log via history nodes instead of table indexes.

  • Get the correct key derivation path for FIO and/or a better approach as the examples here are most likely wrong.