TLDR Version with demo and screenshots below.
Open Source Example: https://github.com/emmonspired/erc20-digital-signature-verify
None of this crypto stuff matters unless we execute and #BUIDL ways to increase adoption.
A Pleasant User Experience for Verifying & Accepting Ether & ERC20 Payments using Digital Signatures, Elliptic Curve Cryptography with MetaMask, EthJS and EthSigUtil In a Modern Web Framework like Angular
Abstract: Accepting payments in the form of Ether and ERC20 tokens is still a challenge due to the nature of how browsers were not designed with identity and payment mechanisms baked in. Generally, those selling a product wish to reach the broader global market, but are limited to credit card and Paypal payments that require permissioned systems and possibly paid APIs to work with. In addition, there are difficult problems to solve when deciding to handle customer payments, involving verifying who actually made a payment. Here is where MetaMask+EthJS+EthSigUtil come in. This suggested solution includes a 3 step technical workflow, and it is a surprisingly pleasant user experience: 1) register a public address with the site by digitally signing a challenge phrase with personal_sign. Signature of a hashed message is performed off-chain to prevent chosen cipher and replay attacks 2) server side personal_ecRecover is used to verify the digital signature was created by the address 3) allow acceptance of payment by giving the user easy access to seeing tokens and/or ether in a wallet on your site. Even if you do not want to manage customer sessions with this method, it is effective for solving the problem of accepting crypto payments and being able to verify a person that said they paid you, really did. A full demo is included and linked to at the bottom of this document to demonstrate the process. It uses Metamask + EthJS + EthSigUtil + TruffleBoxes + Angular components. At the backbone of all this, we use Elliptic Curve Cryptography.
Introduction: You want to accept Ether and ERC20 tokens as payment for your service, but you don’t have a way of performing KYC with a user, since this type of payment was fundamentally designed to be decentralized, which circumvents the entire banking infrastructure. This is by design, and avoids a centralized authority. In addition, you may not have the financial means to establish a business relationship with a bank, nor the legal right to establish API access with a payment processor. This proposes a solution to verifying payments from digital identities using signatures. You can then use this public address to associate payments with a customer on your site.
Challenges: Transactions for cryptocurrency and digital “Utility Tokens” are recorded on a global, open blockchain, and you might have people that scan the transactions sent to your smart contract or designated wallet addresses. There are many benefits to a public, open decentralized ledger, but there might also be bad actors on the system that wish to make false claims that it was them that paid you, and not the person that actually paid you. This is a problem on multiple levels. It takes time to fend off false claims by investigating and tracking down the IPs and discovering evidence postmortem in order to determine who the actual sender of cryptocurrency / token payment was. This archeological endeavor is fraught with error, especially if the genuine payer took precautions on his or her end to anonymize his location through a tangled web of VPNs. Even after wasting precious time investigating the situation, you might credit the wrong user with the purchase. This will result in you losing a customer, and possibly end up refunding the wrong individual.
Possible Method (Rejected - Traditional / Centralized): When a user establishes an account with your service, you generate a new address for that user to accept tokens to send to at the point of sale. Unfortunately, this means you have to keep track of a new private key, and a mapping of users to account keys. This is both mess, grows geometrically over time for each payment, and is hard to keep track of. Even worse, your centralized server becomes a target of DDoS and security attacks. For these reasons, I reject this approach and suggest a New Paradigm for accepting Payments and dealing with cryptocurrency / ERC20 token payments.
Proposed Solution (New Paradigm / Decentralized): Reverse the paradigm for security. Store as little as possible about your customer. Only store their PUBLIC address. How would this work? At the point a user enters their address, issue a strong cryptographic challenge. Send the user a message that is unique and random that must be digitally signed. The message will be clearly visible to the user, which makes the user confident that they are not signing a transaction with devious intent. This message is then sent into a *one-way hash, is digitally signed by the unlocked user’s account with the use of a Nonce and a private key on their own device, and the output is a digital signature that is sent to the server issuing the challenge. The server uses Elliptic Curve cryptography to recover the address used to sign the message, and compares that recovered address with the expected result.
What Makes This Possible: We already have all the tools available to make this happen. ECDSA technology has existed since the early 1990s, however, many modern browsers still don’t have identity of payments built in to the platform. A product called MetaMask offers users with an extremely easy way to securely store cryptographic key pairs. With this browser extension available on Chrome, a selected account acts as the “available” address that gets injected into a site that is Web3 enabled. These days we refer to Web3 enabled sites as the front-end UI for Dapps, apps that work with a decentralized blockchain like Ethereum. There are also plenty of other open source tools that have come available since the invention of the Bitcoin protocol and open source software through the most popular open source platform called Github. We will rely on several of the frameworks available, especially Web3JS, EthJS, and eth-sig-util. For the purposes of demo, we will use OpenZeppelin, the TruffleFramework, Angular and Node, as well as their dependencies.
Why This is So Powerful: With cryptographic key pairs made available to the user in a very user friendly way, it makes cryptocurrency, Token Payments and also DIGITAL SIGNATURES extremely painless to work with. No longer will you have to be a tech guru with a console based application and know-how of a complex set of instructions in order to perform basic security operations that lie at the heart of public/private key cryptography.
Digital Signatures provide a way to undeniably verify that only the owner of a private key could have possibly signed a particular message. 1) You can challenge a user to identify themself NOW, or at any point in the future, in real time, at the point of sale. 2) You can store a message signature that was signed by a user and hold 100% undeniable proof that the user authored it or had at one point in time. This is especially useful for assigning record of ownership, or maintaining contract and end user license agreements. 3) Because the message that is signed is first sent into a 1-way cryptographic hash, you can verify that the data was not manipulated in any way. The hash function has the properties of exhibiting the following properties: A) Irreversible; computationally infeasible to determine the message from its digest, B) Collision resistant; impractical to find more than one message that provides a given digest, and C) High avalanche effect; any small change has a significant change in digest.
In the proposed solution, No Ether is Required for signing. Signatures can be performed without the use of public blockchain, which means that replay attacks of signed messages are not possible, preventing a user from appearing as a certain user, and you could extend this idea by having the digital signature verification server issue a cookie to the user in order to stay logged in.
Concerns: Relying on public-key cryptography means that the user must protect his identity as if it was his money. His private key becomes his identity. If the user loses their private key or is compromised, there is no way to prevent other users from making payments from that address on their behalf. A user would still have to use the traditional methods of interacting with the website to re-establish a new payment address. Since we are dealing with payment methods and not full blown identities and logins in this solution, we do not suffer major consequences like we would if we were dealing with catastrophic loss of identity for a site.
This isn’t entirely new; what makes this special? True. We have had this cryptographically provable EC method since 1994, where y^2 = x^3 + ax + b. We have had tools like BitID, relying on public-key cryptography for e-commerce. The DIFFERENCE NOW, is that we finally have the tools to make the end-to end USER EXPERIENCE cleaner, seamless and enjoyable. It must be a user experience that is as painless as possible. That is what will allow us to have more widespread adoption of payments with cryptocurrency and ERC20 tokens. Using QR codes is less than ideal, let alone looking at one for very long. They are ugly and nearly impossible to visually verify accuracy.
Simple Prerequisite: Install Metamask.io Chrome Plugin. MetaMask “is a bridge that allows you to visit the distributed web of tomorrow in your browser today. It allows access to dApps without running a full node. Users securely manage identity and transactions. Upon installing and starting MetaMask for the first time, the user is given a 12 word seed phrase to restore accounts created within MetaMask. Users can Switch Accounts or Add new accounts as well. Private keys are stored locally and encrypted; they never leave the application, and are never sent to a server. When the user performs an action in the browser that requires a transaction to be signed, it asks Web3 to send a transaction, which prompts MetaMask for confirmation; the user accepts. No synchronization with a ethereum network is required for a user because nodes are maintained by Infura, remotely.
- Metamask is not a HARD requirement; any Injectable Web3 provider that supports the personal_sign and personal_ecRecover methods, as well as an intuitive UX would do. We use these methods as opposed to the eth_sign and eth_ecRecover to prevent chosen cipher attacks.
Workflow: 1) User adds a method of payment for Ether or ERC20 tokens with MetaMask installed and Account selected. 2) Website “challenges” user with readable text as well as a random message in the visible text. User accepts to proceed signing. 3) Back-end server uses elliptic curve functions to send in the digital signature and recover the public address used by the signer. 4) A match of the recovered signature and the expected signature is all that is needed to verify the user is who they say they are. 5) Optionally store this digital signature as proof of acceptance for a EULA agreement. 6) Allow wallet info to be displayed on the UI of the dApp for sending tokens.
Repercussions: Any site that offers eCommerce can offer Ether & ERC20 compliant tokens as a Method of Payment today. This technology will work no matter if you are a large multinational conglomerate, or if you are just a kid sitting at home dreaming up an idea for a decentralized platform to disrupt the online marketplace. This technique has extraordinary implications. You can can easily accept payments from around the world without a service like Paypal. You don’t need a relationship with a bank. You don’t need to store personal information about your customer. This is a new paradigm that flips ecommerce on its head, especially for the purchase of digital assets or IP.
Demonstration: Here’s how it looks in practice. The point of the project is to demonstrate how the majority of web applications in existence could start doing this now. The UI has not been styled; there is no point to waste time on that since each app will already have its own styling and branding. Any interaction that requires the user to be prompted to CANCEL or ACCEPT the fully transparent digital signature challenge, will rely on the use of the MetaMask browser extension.
Open Source Example: https://github.com/emmonspired/erc20-digital-signature-verify
Authentication / Verification Example
*User Signs a Random Message that is displayed to the user. This message is hashed and then is digitally signed by a Web3 provider, like MetaMask. In the future this could be some other provider that implements personal_sign like a Ledger / Nano, or even signed using a third party site like MyEtherWallet.com
*Example Code that takes the Digital Signature and extracts information from it in the Elliptic Curve personal_ecRecover function to undeniably verify a particular address signer.
Wallet Injection in the Browser
- Connect to Web3
- Display Wallet / Account Information
- Ability to Send ERC20 Tokens (Potential for improvement: instead of user specifying how many tokens to send, the application could present the user with an amount that fluctuates with the market value of ETH/USD or ETH/Token, or obviously a pegged price.
Not Included: Room for improvement in the Demo Open Source Code
- Node/Java backend; we simulate the verification step here with the click of a button, but it gets the overall point across and demonstrates the inputs/outputs required to verify.
- What to do to process payment on the backend, post blockchain transaction confirmation.
Dependencies: Tech stack includes, but is not limited to:
Truffle Framework, Truffle Boxes: LimelabsTech/limelabs-angular-box
Angular, SCSS, Typescript, Async/Await, Bootstrap3, Axios
Web3js, EthJS, EthSigUtil
These dependencies provide a user-driven working example for understanding and developing the base of a Web3 enabled application for working with the truffle framework and Angular. It also provides a basic example for working with ERC20 compliant tokens. Screenshots below.
Again, to give credit where it is due, several man-hours of research was poured over to come to this solution and standard for accepting payments while being able to verify them. I did not have to invent any of the following myself: ECDSA, MetaMask, EthJS, EthSigUtil, Angular, OpenZeppelin, and the many other open source projects that were relied upon to get here. I am just putting it all together in a demo in a user-friendly and developer-friendly package in hopes of sparking a decentralized payment fire and getting this in the hands of many developers.
Dan Emmons February 7, 2018
CBP | @emmonspired | LinkedIn Profile
Special thanks to Dan Finlay @danfinlay for all the work he has done sharing his work with the community, especially some of his examples that I incorporated into this Angular based solution.
Special thanks to MetaMask @metamask for all the work Infura has done to bring Ethereum blockchain 1 step closer to feeling like Ethereum is a native part of the dApps browser experience for a user.
Special thanks to Maxim Integrated for the massive amount of explanation and research provided regarding The Fundamentals of an ECDSA Authentication System.
Looks awesome! Thanks for #BUIDL'ing !
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Thank you for taking the time to read it. I plan on making a more concise version of a how-to guide in the future, but wanted to lay out the problem/solution first.
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit