-
-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add secp256k1 key support for did:key #625
Conversation
fromKeyType "Ed25519" = fmap Ed25519PublicKey . parseUrlPiece | ||
fromKeyType "RSA" = fmap RSAPublicKey . parseUrlPiece | ||
fromKeyType "Secp256k1" = fmap Secp256k1PublicKey . parseUrlPiece | ||
fromKeyType _ = \_ -> Left "Invalid Public.Key type" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to do this dynamically with the Data.Data
module, but turned into a bit of a hassle, so I kept it simple.
@walkah Do I have to do anything special here for Nix and the Github actions? I added a C library https://github.com/bitcoin-core/secp256k1 using Nix ( Resources: |
The error I'm talking about: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we may need to apt-get install -y libsecp256k1-dev
in the github workflow for the ubuntu native builds, but my suggestion above seems to be working for nixos.
case publicKey of | ||
Secp256k1PublicKey pk -> | ||
-- `innerSig` is actually a recoverable signature, | ||
-- but since Ethereum (or Metamask?) often has a `v` value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-- but since Ethereum (or Metamask?) often has a `v` value | |
-- but since Ethereum often has a `v` value |
No need to mention Metamask here. Any Ethereum wallet(I would hope) would function in a consistent way 👍🏼 https://eips.ethereum.org/EIPS/eip-155
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, forgot to remove this! Regarding this, see the last paragraph in the PR description, would love your feedback on that 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, forgot to remove this! Regarding this, see the last paragraph in the PR description, would love your feedback on that 🙏
@icidasset sure! I think EIP-155 may be the key to distinguishing the two. as you mentioned, bitcoin and ethereum used to both have v
values of 27(or sometimes 28?), but, looking at EIP-155, it says v = CHAIN_ID * 2 + 35
or v = CHAIN_ID * 2 + 36
, so maybe we can just check if v >= 35
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point, I'll use v >= 35
, thanks! Do you know of any other chains that prefix and/or hash the content before signing it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good point, I'll use
v >= 35
, thanks! Do you know of any other chains that prefix and/or hash the content before signing it?
hmm 🤔 I believe Tezos and Cosmos prefix them, but I'm not entirely sure how it works across most other chains(I've mostly worked in ethereum). I can do some digging though!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'd be great! Especially if we want to support other chains than Ethereum in the future 👀
hs-ucan/library/Web/UCAN/Internal/Orphanage/Secp256k1/PublicKey.hs
Outdated
Show resolved
Hide resolved
…56k1/PublicKey.hs Co-authored-by: Andrew Vivash <[email protected]>
Still can't figure out why data-root lookups are returning a ;(async () => {
wn.setup.endpoints({
api: "http://runfission.test:1337",
lobby: "http://localhost:8001",
user: "fissionuser.test"
})
webnative.login()
})() |
I don't have a huge amount of context around this, but I just installed |
Hey @avivash! I can give you some pointers on project setup and running the server. First, a question -- are you using the nix shell in the project? You can use it by running Once that finishes and you are in the nix shell, you should be able to run $ helpme
____ _
/ ___|___ _ __ ___ _ __ ___ __ _ _ __ __| |___
| | / _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` / __|
| |__| (_) | | | | | | | | | | | (_| | | | | (_| \__ \
\____\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|___/
build | Build entire project
cli-install | Install the Fission CLI
quality | Run the complete test suite
repl | Enter the project REPL
server-debug | Run the Fission Server in debug verbose mode
server-install | Install the Fission Server
server-start | Run the currently installed Fission Server
server-update | Update & run the current server to the latest on the current branch
ssh-prod | SSH into the production environment
ssh-staging | SSH into the staging environment
watch | Autobuild with file watcher
welcome | Print the pretty welcome The Before you run the server, there's a bit of docker, server and DNS configuration that is documented here: https://github.com/fission-codes/fission/tree/main/fission-web-server#using-docker. I think that should be enough to get you up and running, but let me know if you'd like a sync chat to help out with any of it. |
Amazing! Thanks @bgins! I'll give that a try 🙏🏼 |
v2 = | ||
genericServerT Fission.RoutesV2 | ||
{ api = serverV2 | ||
, docs = v2Docs | ||
} | ||
|
||
serverV3 = | ||
genericServerT Fission.V3 | ||
{ user = genericServerT User.handlerV3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are your thoughts on versioning the other endpoints like ipfs
, app
, and auth
? Doesn't seem right on this PR, but maybe we will want to version/alias them to have a consistent set of routes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, maybe alias them to v1 or v0 sounds like a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm missing some context on the Ethereum/secp256k1 bits of this PR, but I did a bit of testing and the code looks good to me.
I tested the following:
✅ The database migrates with no issues
✅ Registering a user using walletauth
app. A user with an secp256k1 DID registers in the database.
✅ A user's public key can be updated on the update public key v3 route (tested with an Ed25519 PK).
One thing that I tried that failed was updating a user public key from Ed25519 to secp256k1. Not sure if that is a feature that we want.
A question about the old style public keys. Are those a compatibility layer while we migrate the database? Do we keep them around to support v2 routes?
There's more general testing I'd like to do, kicking the tires on other parts of the system overall, but I think that can happen when these changes are on staging.
I also ran into these issues, making calls from Insomnia. Seems to be down where we are calling on PowerDNS to resolve DNS records. Do we know if this is an issue in outside of this PR? If so, maybe we could test it on a pizza instance? Or move forward and test this part of the functionality on staging? |
If it's working locally - and tests are all passing - I'd vote to merge and deploy to staging for additional testing (and open subsequent issues if stuff comes up on staging). |
Awesome thanks!
Hmm, that should be possible. How did it fail?
Indeed, v2 routes still work with the old format. No database migration needed for those, they're automatically converted to the new style behind the scenes. Just happens to only support ED & RSA keys because of how we used to discerned those two. |
It fails with a 400 with this message in the response
The original key that was to be replaced was an Ed25519 key. |
Since updating public keys of the same type works I'm going to merge this in. I have to test transitioning between key types more extensively, but we can do that later (tracking in #629). |
This PR adds secp256k1 key support for
did:key
, the type of key used by Ethereum, Bitcoin and various other blockchains. We intend to use this initially for wallet auth, where we look up the public key of an Ethereum account and then construct a DID from that client side. In addition to that, we will also sign UCANs with those DIDs, which this PR also adds support for.Public key types
This PR changes how we store public keys in the database. Before we stored the public key bytes formatted as base64. This is now wrapped in a JSON object, along with the type of the public key. That affects the
Update Public Key
andUpdate Public Key via Email Challenge
API endpoints for which I created new V3 routes.New format:
Migration
I've written a DB migration that converts the old string format into the json-object format.
This can be found at fission-web-server/sql/1658241548_set_public_key_type.sql
You can run this migration multiple times, it detects both the old and new format.
SECP256K1 UCANs
UCANs with secp256k1 signatures can be created by using the
ES256K
algorithm (alg
field in the header). Thisalg
value is specified here: https://datatracker.ietf.org/doc/html/rfc8812#section-3.2 Not sure that's the correct spec, but it's the only one I found.Example: https://github.com/fission-codes/webnative-walletauth/blob/375c63881a300442ec3112bf6a7863fc22ecbb4a/src/webnative.ts#L155-L159
Ethereum signatures
This is currently specifically tuned to Ethereum. Normally the content that one would sign for a UCAN signature would be
${UCAN_HEADER}.${UCAN_PAYLOAD}
. But here this content will be:I made a module that is responsible for "wrapping" this data at
Web.UCAN.Signature.Secp256k1.Ethereum
.I guess to see if it's an Ethereum signatures we could detect if the recovery valuev
of the secp256k1 signature is bigger than or equal to 27 (specification: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#specification). Although I guess Bitcoin has av
value of 27 as well. Thoughts?Added an Ethereum check which looks for a
v
value of>= 35
.