Since early 2019, Software Verde has had the pleasure of working with the city of Dublin, Ohio to create one of the world's first local government digital identity systems. In this blog post we want to highlight the various goals of the project and the technical challenges we faced in the process of building a working solution from the ground up.
The city of Dublin had three very clear, individually worthwhile goals: establishing blockchain-based digital identities, collecting survey responses via user's digital identities, and creating a points system that users with digital identities can use to receive various benefits throughout Dublin. We will dive into each of these one-by-one.
Dublin's core requirements were to allow for the sharing of individual pieces of data associated with a given user without having to share all of it (e.g. sharing one's age without sharing one's name) and that Dublin-authorized entities could receive data from users in this way while remaining confident that the provided data is an accurate representation of Dublin's knowledge of that user.
From the beginning, Software Verde wanted to add two additional constraints to digital identities. First, we wanted to make sure that Dublin could not falsify a user's data sharing consent. Second, we wanted users to be able to share small pieces of data with many parties without worrying that those parties could easily collude after-the-fact to create a more complete picture of the user's identity.
To fulfill all of these constraints, we quickly realized that registration for this system would have to be completed in-person with a city of Dublin employee. This employee validates documentation provided by the user and enters the information into the system. At the same time, the user installs the Dublin Identity app and generates the primary asymmetric key-pair (using secp256k1) that will comprise their identity. They provide the public key to the registration person, either using a QR code or by displaying/speaking-aloud a phrase that corresponds to the public key. This associates the validated information, input by the Dublin employee, with the keys stored on the user's device. Note that Dublin's servers never obtain the private key that will be used by the user to authenticate with the system, as well as to prove their identity to others. So at this point, Dublin has obtained a trusted set of information about the user but does not have the ability to masquerade as that user without using different keys (more on why this is important later).
Once users are registered they can request data from other users by generating a data request QR code that other users can scan. We identified two core use-cases that we needed to address: ephemeral requests (in which a one-time-access, in-person data share occurs) and sharing requests (in which access to data, including updates, is granted indefinitely unless it is later revoked).
When responding to a sharing request, a user scans the request QR code and, assuming the user approves of sharing the requested fields with the requestor (from here on, recipient), the user has the ability to create a secondary key-pair. If they do, they register the newly generated public key with Dublin using their primary key-pair and associate it with the user that generated the request. Dublin then obtains the requested information, signs it with a previously established key-pair that Dublin owns and provides it to the user. The user then signs this request with their newly generated secondary key-pair and includes all of the signed data to the recipient in a response QR code. So the response contains:
With this data the recipient is able to determine that Dublin has recently approved of the information provided (ideally within a matter of seconds) and that the user presenting the response is the owner of the public key that Dublin is associating the data with. The set of shared fields is tracked by Dubiln, allowing the recipient to request data for fields that are too large to fit into a QR code or to get updates to the data in the future. Additionally, the user sharing their data has the ability to view all shared fields and revoke access (or add additional access) as they see fit. Similarly, now that this relationship is established, the recipient could also choose to share their own data without requiring a reversed QR-code-handshake.
For an ephemeral request, the workflow is similar but with a few modifications. Firstly, no user public key is provided and there is, therefore, no signature from the user. Instead, a large random value (a nonce) is generated by the recipient and included in the request when it is generated. This nonce is passed along and included in the signed data returned by Dublin. This provides the recipient with confidence that the data Dublin returned was in association with the ephemeral request they generated, and therefore that the user who scanned the request is indeed the owner of the data.
You may be wondering what prevents the user from using another person's phone or having their phone pass off all the communication to a third-party who can service the request on their behalf. How does the recipient know that the owner of the data is in fact the person in front of them? We addressed this by making one of the requestable fields a photo of the user, taken during registration. For circumstances in which the data shared is at high risk for such abuse (e.g. collecting a user's age for entrance to a bar), the user's photo can be requested for additional verification.
Another important question to ask here is how Dublin can prove that all the secondary identities associated with a user actually originated from that user (as opposed to being generated by another user or a system administrator). Similarly, how would Dublin prove that a user did in fact authorize the sharing of data fields with another user? This is where the blockchain aspect of the project comes into play. Software Verde opted to use our custom blockchain application DocChain as it supports the storage of arbitrary amounts of data. With each action taken on the Dublin Identity servers (registering a user, creating a new secondary identity, sharing data, accessing shared data, etc.) a log document is sent to DocChain which includes, where applicable, the requested data from the user and their digital signature authorizing the request. These log documents are built into DocChain's blocks, providing an immutable history of actions taken in the Dublin Identity system (more information on how this works later). At any point in the future, an auditor could verify that each of the log documents for actions that require user authorization have a valid signature from the primary identity private key of the user in question. Keep in mind that this private key is only ever stored on the user's device, and therefore cannot be falsified without access to that device.
Dublin had the intuition that digital identities could be a launching point for many other digital services that would be more user-friendly and secure than their traditional analogs. They envisioned a system where users with digital identities could anonymously respond to surveys and where survey owners could trust that individuals only responded once while also being able to verify that a given user participated in the survey without knowing which response was theirs.
In the Dublin Identity system, users are able to create surveys with any number of questions ranging from yes/no, multiple choice, and free response. They register the survey with their mobile device, making their account the owner of the survey. They also generate a survey QR code that can be printed, distributed, or otherwise presented to other users. When a user scans the QR code they are able to load the content of the survey. They also receive information necessary for encrypting their responses in a way that only the survey owner can see. This response is also signed by a secondary identity (as is optional done when sharing data) that is automatically created to anonymously associate the user with the survey.
As a result, even though Dublin's servers broker the registration of and responses to the survey, they are unable to see the responses themselves. Similarly, the survey owner is able to see the responses but unable to determine who submitted the responses, since the mapping between the respondents' primary identities and survey identities is hidden within the Dublin Identity system.
Because the majority of this information is not visible to Dublin servers, and there is a strong need to make sure that the responses are counted accurately, we again enlisted the help of DocChain. DocChain already had processes for sharing encrypted documents with other users and fetching the set of documents shared with a given account (e.g. the survey owner's secondary identity specific to a given survey). This made the storage and retrieval of survey results a simple analogy to existing DocChain functionality. As a result, an auditor could easily verify the number and timing of responses submitted for a given survey with actually receiving access to the responses themselves.
As a second use-case for digital identities, Dublin imagined distributing something similar to coupons or rewards points to users. Those points could then be redeemed at certain special events or possibly businesses throughout Dublin in order to receive discounts or other special benefits. Over time we expanded the vision of this to make the points transferable between users to maximize their usefulness. Not all users of the system will necessarily be Dublin residents or regularly visit Dublin businesses, so this expansion may increase the effective value of the points for users that don't often find themselves in Dublin.
In order to accomplish this we have coupled our secondary identity process described above with the Simple Ledger Protocol (SLP) on the Bitcoin Cash (BCH) network. In essence, this allows users to submit specialized Bitcoin Cash transactions to transfer points to one another. To start, the city of Dublin will create submit an initial transaction that "mints" a large, arbitrary number of points (SLP tokens) to be distributed to users. The value of these points is in no way related to the value of Bitcoin Cash and Dublin can create more in the future should they desire to do so without affecting the value of the points.
During registration, a small amount of BCH (worth something on the order of pennies) is transferred to each user to fund the transactions that transfer points from user to user. You can think of it like Dublin writing point amounts on a bunch of index cards. Each user is then given a few dozen stamped envelopes (BCH) so that they can mail the cards (SLP tokens) to other users, provided that they know the intended recipient's address (Bitcoin Cash address). While the users could use the stamped envelopes for personal letters instead of sending the index cards, they would get more value out of redeeming the points. Ultimately, this boils down to the fact that though some actual value goes into seeding the process, SLP provides a convenient, traceable, and decentralized mechanism for implementing the points system.
That said, providing users with a few cents-worth of BCH has some trade-offs. Without a doubt it's an easy, straightforward way of making sure users can start exchanging Dublin points without needing to worry about how transactions are funded. But it also has the obvious downside of limiting how long this can continue without re-funding the user's accounts. Providing a continuous mechanism for funding these transactions could be one longer-term solution but could be abused by users wanting to slowly siphon off funds, initiate a denial-of-service attack by depleting the account(s) that would be providing the funds, or just cost the city money. So for this to work, additional controls would need to be put in place that would increase the complexity of such transfers, which are naturally somewhat computationally expensive to validate. Given that ~10 cents worth of BCH should allow for dozens of transactions per user, and we expect the points-economy to grow slowly, the decision was made that user account depletions could be handled over time manually. For example, a determination could be made of whether a given user is out of funds due to legitimate use of the system and, if so, an administrator could initiate a new funding transaction, akin to when the user initially registered their identity.
As mentioned above, we used our blockchain application DocChain for multiple aspects of this project. We therefore want to take a couple of moments to explain more directly how DocChain provides the guarantees expected of a blockchain system. Most notably an immutable, verifiable history of past actions.
DocChain is deployed as a small network of nodes that communicate with each other using effectively the same protocol used by Bitcoin Cash. ASIC miner devices ensure a high hash rate for this small network but ultimately someone with enough funds, network access, and know-how could attempt to make a 51% attack on this network, potentially degrading the auditability of the blockchain created by these nodes. To help combat this, block hashes are periodically submitted to the Bitcoin Cash network within transactions. These block publication transactions effectively anchor the Dublin-DocChain blockchain to certain points in time.
Dublin is able to configure both how frequently blocks are published, and the number of confirmations required before a hash is published. That is, when we want to publish a block hash, we do not want to publish the most recent one as there is a not insignificant chance that a longer chain may be created off of the prior block or even one before that. Instead, we submit the hash of an older block, by counting off how many blocks are ahead of it. For example, the 6th-oldest block holds a fairly low likelihood of being invalidated by an alternate chain, given that the DocChain nodes will always mine off of the longest chain they are aware of. As a result, Dublin may choose 6 confirmations as the block publishing offset. Since the block mining difficulty is tuned to average one block every 10 minutes, this leaves only the last hour unchecked. Fewer confirmations could be used to publish a more recent state at the risk of those blocks being naturally superseded by blocks on a forked chain.
Similarly, Dublin can configure how many blocks should be mined before one is published. For example, if set to 12 blocks, that would mean that a hash would be published roughly every 2 hours. The hash of the block to be published would be the one with the configured number of confirmations at the point that the 12th block is mined. Whatever the settings, an auditor would need to consider these factors when evaluating the validity of the blockchain state.
Software Verde has been extremely excited to be chosen to work with the city of Dublin on this project. As much of the tech industry, and increasingly the public sector, moves toward an increased reliance on public key infrastructure and blockchain technologies, we feel fortunate to be a part of this large step forward.
If you have any questions about this application or about what Software Verde can bring to the table for your organization, please email us at firstname.lastname@example.org.