invite_me: Onboarding to Ethereum chains with keybase.io identity verification and EIP-712

This is not a Blockchain-bullshit-only post. Head to https://github.com/ice09/onboarding-eip712 for a sample implementation of a private Testnet onboarding with Twitter, Reddit or Github Keybase proofs.

The challenge…

Creating a private Ethereum Proof-of-Authority testnet is actually quite easy, just follow the instructions of Parity or, for testing purposes only, cliquebait, and you’re done.

But how do you onboard new users, who want to participate in your testnet, if they don’t have any ETH to start with and you still want to stay as close to your production environment in terms of gas usage as possible and therefore don’t want to enable gasless transactions in your PoA testnet?

…and the public testnet solutions

Kovan PoA

The public (Parity-powered) Kovan PoA solves this problem by providing a “Faucet Service” which is verified by

Rinkeby PoA

The public (Geth-powered) Rinkeby PoA solves this problem by providing a “Faucet Service” which is verified by

However, these methods require trust or establish dependencies on the testnet providers, which you will and can most likely not introduce in your private net. 

Analysing the problem

There are (at least) two different user states which a user can have in your PoA private testnet:

  1. The user has an authorized account in one of the authority node wallets.
  2. The user is connected to the private testnet, but initially has no balance.

In Proof-of-Work (PoW), the non-authorized user could start mining and get ETH for contract development. This is the Ropsten solution. In PoA, mining is not possible, so the user has no possibility to transact on the chain, except for using usd_per_tx=0 or similar for no gas costs on the authority nodes, which is possible, but contradicts the security measures established by having gas usage for transactions to minimize code execution, prevent infinite loops, etc. Even more, the setup on a test stage should always be similar to the production environment.

Recentralizing for “Almost Know Your Customer”

keybase.io does a great job in identifying users without revealing their real life identity if they don’t want to. But they make it quite difficult for attackers to create several identities. So a good enough solution for onboarding otherwise unknown users could be to bind their testnet accounts to their keybase users.

The basic idea and the following approach is inspired by Aragon and one of their great blog posts, which every Ethereum/Solidity dev should take a look at.

In our setup, we changed two crucial factors:

  1. removed dependencies on a product (Aragon) and on the Oracle (oraclize.it) and
  2. introduced a middleware component as a new dependency, but which you control and can (and have to) host on your own server.

keybase allows for publishing files per HTTPS by copying them to KBFS file system. Thereby, someone reading a file from https://KEYBASE_USER.keybase.pub/invite_me.json can be sure that the file invite_me.json was stored by keybase KEYBASE_USER.

But this is just one proof, how can we be sure that the user really has the private key for the address he wants to be registered? We can just sign the message with the private key and ecrecover in a contract. 

Using this mechanism, we can be sure that:

  1. If the URL https://KEYBASE_USER.keybase.pub/invite_me.json gives back the correct JSON, the user is who he pretends to be, since he had to copy invite_me.json to KBFS
  2. The address (private key) belongs to the user, since he signed the message in invite_me.json and the signature is ecrecovered in the invite_me contract.

MetaMask does a great job in helping signing data with your Ethereum’s account private key. However, up to EIP-712 the signed data has been displayed as a non-human-readable Hex string.

This is unacceptable, especially in crypto, a field of very easy and unavoidable fraud attempts. 

Therefore, we are supporting EIP-712 by signing with a MetaMask version supporting the new eth_signTypedData method. EIP-712 is a major step forward and should be the only way users are required to sign data with their Ethereum account’s private key.

The following overview shows the process which let a new user register his keybase user to a new generated address. Afterwards, 10 ETH are sent to this address. The user can only register once. However, the contract owner can manually unregister users if necessary.

For the ETH transfer to happen, the user must

  • have the invite_me.json as generated by the frontend part stored in his KBFS public directory, so that it can be retrieved by the server side process at the keybase.pub domain
  • have at least one of these Keybase proofs: Twitter OR Github OR Reddit

Introducing invite_me

The complete process is implemented in the “DApp” invite_me, which consists of a JavaScript frontend and a web3j-powered Java backend component called verifier.

After completing the steps, you can see the 10 ETH loaded into your account in MetaMask.

Let me try this!

First, checkout this. Then, make sure that you have an understanding how the authorization and verification works and what the Java component verifier does and how they depend on each other.

Last, install it locally and try it out. And, most importantly, please comment here or in the reddit post if it doesn’t work for you or if you have remarks about the approach, obviously this is work in progress.

What comes next?

We’d like to try two different approaches:

  • Using 3box as a more decentralized (but not as mature) keybase alternative
  • Realizing a different use case: “Almost KYC Airdrops” 

Identity is the New Money

This post is inspired by the book with the same title, which we found in in this nice summary post by Alex PreukschatIn that blog post and especially in the book you will find all information about Self-Sovereign Identity. We will only refer to the concepts if they are feasible for our samples.

This is not a Blockchain-bullshit-only post. Head to https://github.com/ice09/identity for a sample implementation of the “federated” claim issuer sample.

The Story of Alice, Booze and her local Bank

Alice just turned 18 years old, being in good ol’ Germany she wants to celebrate this with a lot of booze, but her parents refused to buy it for her, since she can do this on her own now.

Currently, she can do this easily by showing her identity card when buying the drinks. The dealer would check her birthdate and verify her age.

This obviously has major shortcomings:

  • The ID could easily be altered, stolen or otherwise not belonging to the person showing it
  • The dealer gets a lot more information than necessary for this transaction, including a lot of sensitive personal data: name, address, height, etc.

So, the dealer would just have to verify that the person is older than 18 years, how could this work with Alice and eg. her local bank?

The book differentiates between identity and statements about this identity (claims), which entitle the person to do things. In our example, the fact that Alice turned 18 years old entitles her to buy and drink alcohol (in certain legislations). However, showing the identity card to the dealer mixes up two aspects very badly: the dealer has to check the identity information to derive the entitlement. This he has to do by himself, if for whatever reason (eg. the dealer not being able to calculate the age) he cannot derive the entitlement, Alice’s intention would be rejected. Also, only information which can be derived from the identity information can be used, if eg. Alice would be incapacitated and therefore not allowed to buy alcohol, the dealer wouldn’t know, since this information is not stated on her identity card.

In the world of cryptography and decentralized data storage (read: DLT), Alice’s bank could easily help her with an identity or better: entitlement verification service. Since Alice participated at the bank’s KYC process, the bank has a lot of information about Alice, one of these being her age. Now, if the local bank is trusted by the shop owner, this information would be enough for the owner: “As your local trusted bank, we verify that this customer is older than 18 years.”

Setup for Ethereum

In Ethereum, the easiest setup would be to use ERC 725/735. These standards (requests) provide all necessary equipment for identity creation and claims/endorse mechanism. Other standards and products are provided by uPort and standard bodies like the W3C DID.

The initial setup Alice has to execute, together with the claim issuers like the bank, a utility provider, an insurance company, etc. consists mainly of three steps which could easily be embedded into a mobile app:

  • Alice creates an identity ERC 725/735 (which might be one of multiple identities she has)
  • As a claim issuer, the bank adds a claim (using ERC 735 addClaim(…)) about Alice being older than 18 years. This claim is signed by the private key of the bank. The claim is stored with a returned ID and must be approved by Alice (1, 2).
  • Alice approves (using ERC 725 approve(claimId)) the bank’s claim on her identity.
  • Now, anyone can verify the claim about the topic she is interested in, eg. the fact that the identity is older than 18 years (4).

After the setup the process of verifying a claim is depicted below:

  • Alice signs a challenge of the shop owner with her private key (3).
  • With the derived public key of Alice, the shop owner can identify the claim in ERC 735 and check the signature of the trusted party, which is Alice’s bank (4), against the publicly available public key of the bank.

This would make a great use case for banks desperately looking for their next Blockchain use case: forget about value transfer, asset creation, settlement and whatnot, you are fighting against proven and established systems which might be embedded in complex processes but have been running stable, reliable and performant for years.

Identity verification on the contrary could be a completely new service offering and banks have the great advantage of having identified thousands of customers in strongly regulated processes, they have valuable data at their hand. The same is true for insurances, mobile providers, utility providers, governmental companies, etc.

But let’s say we want to decentralize even more, how could we go on?

Incentivizing Identity Verification

Couldn’t we incentivize people for doing something only they are able to do right: prove the identities of their social network?

There are some assumptions:

  1. People know their social environment best, especially their direct environment like family, best friends and neighbors.
  2. People want to earn (even few) money with something they – and only they – can do easily following a simple procedure

The process is almost equal to the process above, except that notaries are slashed if they defraud and earn fees if they behave according to the protocol. The slashing is complex and would have to be implemented by some governance mechanism. This step adds complexity, but is solvable and will be very similar to PoS. Most likely there will be a incentivization for detecting and proving fraud included into the protocol.

Incentivization is a great means for getting anonymous parties to agree on a fact. This works great for Blockchains and has also been proven theoretically by eg. game theory and the Nash equilibrium.

Therefore, with incentivization of notaries, their advantage of doing fraud is minimized.

Build a Social Network based on Trust

Trustlines is a decentralized, permissionless, open platform to host currency networks in which money is represented as IOUs issued by its participants. Trustlines implements money as bilateral peer-to-peer issued blockchain-based credit.

In the example above Bob gave Alice a creditline of 20 EUR and Alice Bob of 100 EUR, so they have bilateral creditlines which is a trustline. Bob gave Charly 30 EUR credit and Charly Bob 50 EUR. Now if Alice wants to pay Charly, whom she doesn’t know personally, the system finds a path between Alice and Charly (via Bob) and the creditlines will be used. If Alice pays Charly 10 EUR, Bob afterwards owes Charly 10 EUR and Alice owes Bob 10 EUR. The creditlines have been used and the remaining credit is lower or higher, depending on the direction of the payment.

There is no settlement in the system, if it is necessary or wanted by some party to settle, this is done outside of the system and then reflected in the system by an opposite transaction.

More information about the project is available on trustlines.network, we encourage you to inform yourself about its concepts of people powered money and complementary currencies and its potential to boost cryptocurrencies adoption and enhance accessibility for cryptocurrencies for all people.

Extra Trustlines Benefit: Socially proven Identity

However, for this blog post, a secondary aspect of Trustlines is more important: if you have a social network of trust, you have a social network of identities. This is immediately obvious by the simple fact that if you trust someone with a certain amount of money, you certainly know and trust this person, because you are in risk of losing money if your creditline is used. Depending on the social context this can be family members, good friends, co-workers and the amount of credit you give will mirror your amount of trust in these people.

Given a network with creditlines, people will most likely have creditlines with different people and a identity (and reputation) algorithm could value the amount of credit given and the number of creditlines for a probabilistic identity verification.

This might even be pseudonymous, as someone offering a service for money, I am most interested in a receiver to pay me money, which is related to his trustworthyness and therefore to the amount of creditlines given, not so much who this person actually is. If 10 people who have medium sized networks of creditlines have creditlines with the receiver, I am tending to assume that:

  1. This person actually exists
  2. This person is trustworthy for some amount to other people

For now, this is the only attribute of identity which Trustlines helps solving, but with very high accuracy: if a person actually exists and that this person is trustworthy to some degree.

We won’t have information about other identity attributes like gender, age, wealth, educational degrees and so on.

Let’s fix Identity now!

If you didn’t know a good use case for Blockchain technology, now you have it. This is one of the most natural use cases for a decentral, immutable database accessible by everyone without central control and the possibility to incentivize people.

This is a win for all involved parties, enhancing privacy and security and enabling service providers to make use of their already available data. As there is no “disruption” of any existing business model, but a creation of a completely new one, public identity management can only get better.

Ethereum Usecase: Identity Management (Take 2)

Identity verification is one of the hottest usecases for the blockchain. I already wrote on this topic few months ago with the idea of a fictive government binding hashed identity data to citizen’s ethereum address.

Recently, I ran into ShoCard, a mobile app which is able to locally store user’s identities (driver’s license, passport, tickets, credits cards, online accounts, …) on the mobile phone and seal this data by putting the hashes via the BlockCypher API on the blockchain. Furthermore, institutions, like banks for instance, can verify user’s identities and store this fact on blockchain too, effectively confirming that the sealed id record is correct.

I did the experiment of implementing ShoCard’s concept on the Ethereum blockchain. A very interesting point is that we only need one simple contract for the implementation of the concept. It simply binds a hash value to an address:

contract DataSeal {
address owner;
uint256 dataHash;
function DataSeal(uint256 _dataHash) {
owner = msg.sender;
dataHash = _dataHash;
}
}

First, for every user’s identity record of the form

idRecord = {idData_1, ..., idData_n, randomValue} 

we create in Ethereum a DataSeal instance storing idRecord‘s hash value.

idRecordSeal = new DataSeal(<idRecord hash>)

From now on, idRecord can not be modified without breaking idRecordSeal.

If we want to prove to X that our idRecord has been sealed by us, we will send to X the idRecordSeal address and idRecord signed with the private key of the Ethereum account used to instantiate idRecordSeal. Having this informaton, X can verify that idRecord matches the hash value in idRecordSeal contract and that the signature matches its owner.

So far, we have the proof that idRecord was created and sealed by us, but we have no proof yet that idRecord matches our real identity as documented on our id card. For instance, we could steal the id card from someone else and  seal it on the blockchain. In order to make the idRecord trustworthy, we need a trustworthy witness verifying our idRecord and committing the proof to the blockchain.

The most direct witness for this proof would be the public authority issuing the id cards to the citizens. The next best instance, could be a commonly accepted institution like the mailing company (see POSTIDENT solution of Deutsche Post AG) or a bank.

If the user has been successfully authenticated, the witness will produce

witnessRecord = {idRecordSeal, secretKey}

and create a new instance of the DataSeal contract with the hash of it:

witnessRecordSeal = new DataSeal(<witnessRecord hash>)

Finally the witness shares the following record with the user:

{witnessPublicAddress, witnessRecordSeal, secretKey}

Assuming that X is trusting W, and that we already were authenticated by W, we can pass to X

  1. the witness data {witnessPublicAddress, witnessRecordSeal, secretKey}
  2. our idRecord signed with the corresponding private key
  3. our idRecordSeal address

Now X, can check that idRecord hasn’t been modified, that we’re the owner of the record and it’s blockchain seal, and that we already were successfully authenticated by W. If X trusts W, then he doesn’t need any further verification of our identity and he can do business with us.

The concept is universal and it works with any kind of document. There are also usecases where no witness is needed at all. For instance I can seal my credit card data like this:

creditCardDataSeal = new DataSeal(<hashed credit card data>)

Every time I purchase something, I also sign my purchase with my Ethereum private key and the merchant can verify that credit card data is in my ownership. So even if someone steals my credit card, he won’t be able to purchase something with it, because the thief can not prove he’s the owner of the credit card.