Authereum uses different concepts around keys when referring to contract-based accounts: admin keys, dapp keys, and recovery keys. To better understand the concepts, let’s first start with some context.
Contract-based accounts are managed by a set of keys and the signatures of these keys are checked onchain to determine if the sender key is authorized to perform certain actions. If we think about a simple contract-based account like a multisig contract, the multisig maintains a list of authorized owners, which is list of addresses, that are allowed to send multisig transactions or call methods on the multisig. These owners have full control of the functions of the multisig.
This single tiered system of owners works for most cases but it falls through when trying to restrict what certain owners can do. For example, maybe in the contract controlling funds you want to have root owners and sub owners, where the sub owners are restricted on which methods they can call or how much ether they can withdraw from the contract on a specified time interval. For this additional complexity, the smart contract needs to behave like an Access Control List (ACL) where permissions for each owner are included in the contract. The ACL maintains the level of permissions each actor is able to perform on each object, such as state in this case.
One way to introduce dynamic rules and permissions into the contract one way is to use concepts borrowed from web authentication standards such JSON Web Tokens (JWT). We can have a root owner create an encoded token that lists the permissions allowed by the sub owner. The root owner then signs the encoded information and creates a signature. The token now can be used by the sub owner to performed authorized transactions. In the method transaction to the account contract, the child owner presents the encoded token to the contract and the contract then verifies that the encoded permissions were indeed granted by the root owner by recovering the signer from the signature.
In essence, the root owner attested that the sub owner has authority to perform those functions by creating a signed attestation which acts as proof for the contract when it’s trying to verify the method call.
Side note: this concept of attestation based transaction was first introduced in the Authereum genesis article, termed ‘auth keys’ and ‘login keys’ respectively. Authereum has since re-termed them to admin keys and dapp keys but you can think of them as root owners and sub owners respectively, where the sub owner keys are ephemeral keys generated for each dapp (dapp keys) and the permissions are granted by root owners (admin keys).
In Authereum, each contract-based account is managed by admin keys. The first admin key is generated client side when the user creates their account.
Private keys are generated in the browser using the Crypto.getRandomValues() browser API pseudorandom number generator (PRNG) which reads random bytes from /dev/urandom which is a source of random entropy collected from device driver noise at the kernel level and is considered to be a secured way for generating random bytes.
Admin keys are allowed to add other admin keys to manage the account contract or to simply have as a recovery backup. For example, an account contract can be managed by two separate trusted devices, where a unique admin key lives on each device. Each device in this case has full custody of the account contract since they are both admin keys. A user may add a device such as a hardware cold storage key, like a Ledger Nano, as an admin key but store away the hardware device to only be used in cases where the other admin keys are lost or forgotten since the hardware admin key can delete the lost addresses and add new known ones to the account contract. The user can add or remove admin keys in the Authereum web app or by sending transactions directly to the account contract as long as the sender is another admin key.
The initial admin key is generated and stored in the user’s browser local storage under the domain accounts.authereum.org. This means other websites cannot access the raw key directly because only scripts loaded under that domain can read that domain’s local storage. The admin key is encrypted in the client using a password-based key derivation function (PBKDF2) to generate the encryption key. For convenience, Authereum stores the encrypted admin key as as keystore on the server side. The user password is salted and hashed on the client side as well and the digest is stored on the server side. This allows users to authenticate with Authereum using their password and after verification Authereum then providers the user their encrypted keystore which is then decrypted using the password-based encryption key. The Authereum backend never sees a raw password or raw private key. All the encryption and hashing is done solely in the client side.
Authereum asks for email and password during registration for base level Sybil protection since Authereum is sponsoring the account deployment costs but most importantly to notify the user through email about activity going on with their account. Once the user has signed up, they can add additional admin keys and use those new keys to sign in instead of using their username and password. For example, a user can log into their Authereum account using their Ledger device if they so wish.
Authenticating a user in Authereum requires the user to sign a challenge string with an admin key in order to create a session token. Authereum automatically does this for the user when the user loads their primary admin key upon successful login. The key used for signing the challenge can be any admin key, hence they can use a hardware device or even an injected web3 account that is listed as an admin key to create the session token.
Valid session tokens are required when making requests from the web app to the backend in the form of a Bearer Authentication request header to provide the user additional information related to their own account, where the requesting account information is derived from the session token signature. The session token is in the form of a JWT.
A JWT-like standard for ethereum, ethwebtoken, is being worked on. This token standard will allow the same token to be used in the backend as well as in smart contracts.
It’s highly critical to note that additional admin keys should be kept and stored in a secured fashion since any compromised admin key can potentially compromise the entire account contract because they have full authority privileges on the account. It is possible however to requires n of m signatures to add additional admin keys, that way the attacker will need more than 1 admin key to add additional admin keys making the account more secure.
Now that we have a better understanding of the role of admin keys in the context of Authereum contract-based accounts, let’s take a dive into dapp keys. As mentioned earlier, the admin key that will be used for signing transactions is loaded into local storage under an Authereum controlled domain. It is in the best interest of Authereum to keep this admin key as secured as possible and restrict access to it from unwanted actors. This creates a small issue now; how can dapps that live under different domains use this key to sign transactions if they can’t access the signing key? It’d be unwise to clone the admin key on every dapp because then every dapp and third party scripts on the dapp would have full access to the user’s account contract. It’d also be uneconomical to generate a new admin key for each dapp and create an onchain transaction to add the new key as an admin key in the account contract.
If you recall earlier, we talked about how we can create an attestation to make claims on what set of permissions a child key should have. This works out perfectly because now an admin key can attest to the authenticity of other keys and the new key’s role. When a user needs to interact with a dapp, Authereum generates a new ephemeral key to be used for signing for signing transactions in the scope of that particular dapp. The login with Authereum process for a dapp initiates an Oauth2 style redirect or popup to accounts.authereum.org sending along the public address of the dapp key, where the user can now confirm the login requests which involves creating an signed attestation using the admin key. Upon creating a dapp key attestation signature, the popup is closed or user is redirected back to the dapp and may begin transacting with the dapp. The advantage of using a redirect or popup is that the url is easy to verify in order to prevent click jacking or spoof UIs pretending to be Authereum.
Authereum is offered as a web3 provider meaning that a dapp developer can use Authereum as a drop-in replacement for MetaMask or an injected web3 provider that it relies on. Using the Authereum SDK or Authereum web3 provider will sign transactions using the dapp key.
In order to invoke methods from the account contract, the transaction call must come from the account method. The account contract only accepts transaction signers from admin keys or signers that have been given rights via a signed attestation by an admin key. This means that the transaction must be relayed through a smart contract method that accepts the raw transaction data and the admin key attestation. The smart contract verifies that the attestation signer is an admin key of the account contract. Then it verifies that the attestation token is not expired and that the destination address and destination method ID is allowed to be called by the dapp key. This is a massive advantage of contract-based accounts in that it can restrict onchain which contracts and contract methods different keys are allowed to invoke. An analogy is ‘parental controls for dapps’, where dapp keys are restricted on what they can do and perform.
The signed transaction data from the dapp key is sent to the Authereum relayer. The relayer pulls in the admin key attestation and invokes the meta transaction method on the account key. Since the relayer is the one broadcasting the transaction, it is responsible for paying the transaction fee in ETH, but in the meta transaction call the relayer is appropriately refunded by the dapp key account owner in either ETH or a token such as Dai.
The account contract derives the signing address from the attestation and verifies that it’s a valid admin key. Part of the signature payload is also an expiration timestamp meaning that dapp keys are short lived and expire after a specified time. The timestamp is checked against the current blocktime to make sure it’s valid. If there’s a whitelisted method ID in the the signature payload then that is are also compared against the current destination method ID to make sure that the dapp key is allowed to make transactions to that specified method on the destination contract. Afterwards the contract makes a call function to the destination address passing in the transaction call data signed by the dapp key and an event is emitted with the execution status code. It’s important the meta transactions don’t revert during the call because otherwise the relayer won’t get compensated via the refund at the end of the execution process.
Like previously discussed, it’s not possible for another domain to access the local storage of another domain directly. How does a dapp on a different domain then use dapp keys to sign transactions? The answer to this is to communicate via an iframe. The Authereum SDK and web3 provider loads a hidden iframe on the dapp page to send message requests to the x.authereum.org subdomain holding the dapp keys in the browser’s local storage. In this architecture, there is no way for the dapp to be able to read the raw dapp keys because they are sandboxed. The dapp can only issue signing requests to the iframed hidden page.
Since Authereum owns the iframed page then it can monitor requests and alert the user of unsuspecting requests. The other advantage of this pattern is that all dapp keys can be wiped when the user desires or when the user logs out from the Authereum web app because all the dapp keys are managed in a central secured location. Doesn’t this mean that Authereum can censor dapp key transactions? The dapp key architecture is not censorship resistant because Authereum provides additional layers of security through the relayer meaning that all dapp key transactions must go through the Authereum relayer. The user however can interact with dapps using their admin key which bypasses all Authreum services and interacts directly with their account contract. At any point, the user can opt-out of Authereum services but still retain full custodianship of their contract-based account. Authereum offers additional services for convenience and security at the cost of being able to withhold dapp key transactions if it suspects they are malicious. Authereum calls this the Authereum Transaction Firewall (ATF) because it can prevent broadcasting dapp key transactions that originate from a different origin from where it was created. For example, if a dapp key is created on alicedapp.com but then the relayer sees a transaction coming from the origin bobdapp.com then the relayer can halt the broadcasting and notify the user through email or text message about the activity. The user then has the option to blacklist the origin domain from the suspecting transaction or allow that transaction to go through.
Another type of key used in Authereum are known as recovery keys. Their roles are very simple; to only add other admin keys. A user may add any address as a recovery key. When the user loses or has forgotten all their admin keys, the user may initiate the process of adding another admin key by invoking a recovery method on the account contract and passing in the admin key address. The recovery process doesn’t immediately add another admin key though. Instead it initiates a time-lock of a specified time which allows enough time for another admin key to cancel the recovery request, in the case that the recovery key itself has been compromised. After the timeout period, then the admin key will be added to the account.
To speed up the recovery process, the user has the option to require n of m (n>1) recovery keys in order to add a new admin key. This means that the user can add additional device addresses or account addresses of their closest trusted peers or family as recovery keys (social recovery), so in the case the user’s device is lost or keystore decryption password is forgotten, the user can submit signatures from the recovery keys to the contract-based account and once the threshold is met then the old admin key will be removed and the new admin key will be added.
This article covered the basics of admin key and dapp key concepts used in the Authereum key architecture. Admin keys are root account contract keys that have full access to the contract. Any admin key can add another admin key. Dapp keys are keys generated on a per-dapp instance. These keys are short lived and have limited power. An admin key must create an attestation for each dapp key, which makes claims to what privileges they have on the account contract. Recovery keys are only for adding new admin keys in the case where all admin keys are lost. Recovery keys initiate a time-lock period to give enough time to cancel the request. Authereum provides a relay service so transactions can be payed in a different token but also to provide additional security and notifications for the user.
At the time of this writing some of the features mentioned are in development and will be live soon. Make sure to sign up for the waitlist on authereum.org to get early access to Authereum. Don’t forget to follow us on twitter at @authereum.
Thanks for reading!
Update Jan 30 2020
Authereum migrated from authereum.org to the authereum.com domain and is using authereum.com instead of accounts.authereum.org for the wallet.