It seems like this industry agreed that a user should be able to interact with many different chains using the same public key. Bech32 addresses are freely converted between chains whenever possible and many teams ask about how to convert between a Cosmos public key and an Ethereum pubkey.
Problem
For secp256k1 keys this brings a few challenges such as
- You can't convert address -> pubkey since
address = hash(pubkey)
(i.e. one way function of the pubkey)
- The public key representation in Ethereum is different (65 bytes uncompressed) from Cosmos (33 bytes compressed)
- The Cosmos pubkey format is usually a JSON object containing a tendermint-specific algorithm identifier and base64 encoded data, making it very verbose
- Ethereum public keys are not easily available as they are not stored on chain directly
- For a user it is hard or impossible to understand that they act with the same identity in public because the differences in compression + hashing + address encoding obfuscate that. So it is likely they end up giving information to chain analysis tools they are not aware of.
Properties
In order to solve those challenges I propose a simple printable public key representation that can become the user's primary identifier and blockchain-specific addresses are derives from it.
In my opinion this should have the followsing properties:
- Compact: as short as possible
- Unique: there is exactly one representation for each curve point. This allows using string equality for checking identity equality
- Future proof: staring with secp256k1 but having an algorithm/curve identifier for other types of pubic keys
- Double-clickable: double click should select the public on all relevant operating systems
- Chain agnostic: this is about the keypair, not how it is used
A few encodings we use will fail those tests, e.g.
{"type": "tendermint/PubKeySecp256k1", "value": "AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP" }
is not compact nor unique or double-clickable
AtQaCqFnshaZQp6rIkvAPyzThvCvXSDO+9AzbxVErqJP
is not unique and not future-proof as the curve is not included
cosmospub1addwnpepqd8sgxq7aw348ydctp3n5ajufgxp395hksxjzc6565yfp56scupfqhlgyg5
is not chain agnostic because it contains the chain prefix as well as an Amino prefix. It's also not unique because bech32 encoding is case-insensitive.
-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEuDj/ROW8F3vyEYnQdmCC/J2EMiaIf8l2\nA3EQC37iCm/wyddb+6ezGmvKGXRJbutW3jVwcZVdg8Sxutqgshgy6Q==\n-----END PUBLIC KEY-----\n
(PEM) is not compact and not unique
3056301006072a8648ce3d020106052b8104000a03420004b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9
(DER+hex) is not compact
04b838ff44e5bc177bf21189d0766082fc9d843226887fc9760371100b7ee20a6ff0c9d75bfba7b31a6bca1974496eeb56de357071955d83c4b1badaa0b21832e9
(uncompressed fixed length + hex) is not compact
Turns out none of those formats is really too popular and user facing. As long as you only interact with one chain, it can usually be hidden prettty well. In Ethereum we usually only talk about private keys and addresses and the public key is a temporary value. Even ecrecover
returns an address while the underlying algorithm creates a public key.
Possibilities
Given a public key representation above, we can do a few nice things:
- Show the user their HD path 60 and 118 public key side-by-side
- Derive an Ethereum address from a publey (decompress, keccak256, hex encode)
- Derive many Cosmos addresses (hash sha256 + ripemd160, bech32 encode for many chains)
- Verify off-chain signatures without any lookup
Next steps
I would very much appreciate feedback on this idea or problem statement. Does it make sense? What am I missing? Is there demand? If there is some sort of consensus this is valuable, we can build it.