Message Signing
Since the early days of cryptocurrencies, people have wanted to sign things with their private keys that are not normal blockchain transactions. For example, the original Bitcoin wallet contained 2 commands “signmessage” and “verifymessage” that would sign arbitrary messages with bitcoin pay-to-public-key-hash address (which could also hold a balance).
Tokenized Access
Moving forward to Nexa and native tokens and new use cases emerge. In particular, a token can be used as an access key to, for example, show the administrative pages of a web site or even allow physical access to a car or house (if the appropriate hardware lock is designed). The basic idea is that the entity protecting access (the challenger) stores the group identifier of a well known token or NFT. If a user can prove that they currently have signing authority over any token belonging to the same group, then that user is granted access.
To accomplish this, the challenger presents the user with a message consisting of random bytes. The user then signs that message with the same public/private keypair that currently “holds” the token. The challenger verifies this signed message. If correctly implemented, this provides extremely secure access because a password is never entered into a possibly compromised device, in a possibly compromised browser, running a possibly compromised web site. And that password is never sent (even encrypted/obfuscated) over the network.
Note that there are nitty gritty details needed to build a secure and robust implementation, which you can read about here. But in essence this still uses the basic “signmessage” and “verifymessage” system added to Bitcoin long ago. But the ‘signmessage’ system only works for “normal” pay-to-public-key-hash (P2PKH) addresses. What about multisig? What about arbitrary contracts?
Since the access token can be controlled by an arbitrary contract, the access it grants should be similarly controlled. Rather than create a whole separate set of protocols and data formats for this, it makes sense to reuse the transaction. For example, moving a token (to an arbitrary location provided by the challenger) proves that a user had access to the token. But unfortunately the user just gave their token to the challenger! What we need is something that looks like a transaction (to reuse all this development work), but will never be admitted into the blockchain so the token does not actually move.
Challenge Transactions
Enter Nexa’s concept of “Challenge Transactions”. A Challenge Transaction is formatted like a real transaction so all of the software to manipulate and sign transactions will work for Challenge Transactions with few (which I’ll discuss below) if any modifications.
But the Challenge Transaction has the high bit set in its version field. Every transaction with the version field so set is defined as forever invalid and inadmissible on the Nexa blockchain. This offers a simple way for signers to ensure that they are not being tricked into signing a valid transaction.
The Challenge Transaction can have any legal number of inputs (one input for every asset or address that the user wants to prove ownership of). But it must have a single output. This output must be a “data carrier” (OP_RETURN) output containing the challenger’s name and then some random data.
The user’s device then signs this Challenge Transaction and provides it to the challenger for verification. The challenger can now (mostly) use the normal transaction validation software already created for Nexa. The one issue here is that some of this code will return “invalid” after finding the first problem (such as an invalid version, or that the inputs and outputs don’t balance) because that’s more efficient. What we really want is code that will keep checking and tell us everything that is wrong and right about the transaction.
Fortunately the Nexa full node has an API accessible either via P2P (with caveats) or RPC called “validaterawtransaction”. This API returns everything that is incorrect about a transaction rather than quitting after the first problem. This turns out to be perfect for validating Challenge Transactions.
NiftyArt.cash has deployed just such a system for access to its admin pages. Although nothing in the site indicates it, this coin-like token gives administrative access when it’s provided as an asset by a connecting wallet. Stay tuned for an example and starter template web site that demonstrates these and other technologies!
Implementation Simplicity
One interesting property of this solution is that it pushes all access complexity out of the service and into the blockchain infrastructure. Imagine asking your bank to enhance their web site login for multisig. Or to add a deadman’s switch – that is, if you haven’t accessed the site at least once in a year, someone else you choose can gain access. This is not just a financial thing, it’s even useful for a less critical service like Facebook/Twitter: An organization wants to allow a social media manager to post on its behalf, but wants to be able to grab access back in case the relationship sours.
A token-based system with Challenge Transactions can capture all of these use cases within the blockchain and wallet infrastructure, and allow them to be applied to any site that allows token-based login, rather than requiring that each site implement custom code for each of the situations I just described, and a potentially infinite number of additional situations.
The community has long claimed that blockchain technology has many more use cases than “just” independent, uncensorable, peer-to-peer sound money. It is past time we explored and implemented these uses!