Skip to main content

Native Program for verifying secp256r1 sig.

Summary

Adding a Native Program to support the verification of signatures generated on the secp256r1 curve. Analogous to the support for secp256k1 and ed25519 signatures that already exists in form of the KeccakSecp256k11111111111111111111111111111 and Ed25519SigVerify111111111111111111111111111 native programs

Motivation

Solana should have option to secure your funds in a self custodial manner that doesn't just airgap your private key with a hardware wallet (which even then remains as a single point of failure). Arguably, multi-signature wallets fit into this equation as they enable the dependency on multiple private keys. However in practice the UX takes too much of a hit, as having to sign a transaction a minimum of 3 seperate times and having to write down 3 seed phrases is too cumbersome. It would be ideal to have an authetication form that relies on a more familiar second factor, such as a users mobile device.

Passkeys & WebAuthn are a standardized implementation of this. They enable users to save keypairs associated to different services natively on the secure element of their mobile device. To authenticate with those services, the user uses their biometrics to sign a message with the stored private key.

And although this is meant to enable password-less logins in web2, it makes for an excellent candidate as a second factor of on-chain authentication.

Going past just securing funds, this would support other beneficial account abstractions that make use of the simple UX of WebAuthn and Passkeys.

Note:

Although WebAuthn supports the following curves:

  • P-256
  • P-384
  • P-521
  • ed25519

P-256 is the only one suported by both Android & IOS (IOS being the more restrictive of the two), hence the goal being to implement secp256r1 signature verification

General Documentation:

WebAuthn

Passkeys

Alternatives Considered

We have discussed the following alternatives:

1.) Realising signature verification with a syscall similar to secp256k1_recover() instead of a native program. This would ease integration for developers, since no instruction introspection would be required when utilizing the syscall.

New Terminology

None

Detailed Design

Implementation would be as follows:

Program

ID: Secp256r1SigVerify1111111111111111111111111

The program instruction will be composed of the following:

  • A first u8 as the count for the number of signatures to check
  • Single byte of padding
  • The following struct serialized, for each signature to verify
struct Secp256r1SignatureOffsets {
signature_offset: u16, // offset to secp256r1 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to public key of 32 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get msg data
}

Multiple signatures can be verified. If any of the signatures fail to verify, an error is returned.

Should be analogous to KeccakSecp256k11111111111111111111111111111 and Ed25519SigVerify111111111111111111111111111. View reference details at sdk/src/ed25519_instruction.rs

Implementation

The crates ecdsa and p256 are a good starting point for the implementation. Due to a current dependency version conflict of zeroize between curve25519-dalek and solana-program, using these crates will require a fix/bump of zeroize inside curve25519-dalek. See issue #26688

Compute Cost

Once the implementation is finished, benchmarking should take place on a sufficiently powerful machine in order to determine average compute time. Pricing would be based on the 33ns/CU convention. For the sake of ensuring proper efficiency, a comparison to similar implementations on polygon/optimism/ethereum would be conducted.

This is in line with how previous native programs for EC group operations and arithmetic were evaluated/benchmarked. See PR#27961 & PR#28503

Impact

Would enable the on-chain usage of Passkeys and the WebAuthn Standard.

By extension this would also enable the creation of account abstractions and forms of Two-Factor Authentication around those keypairs.

Security Considerations

  • Ensure parity of test results and parameters with those found in SEC2 for the secp256r1 curve
  • Ensure signature malleability is prevented/accounted for

Backwards Compatibility

Transactions using the instruction could not be used on Solana versions which don't implement this feature. A Feature gate should be used to enable this feature when the majority of the cluster is using the required version. Transactions that do not use this feature are not impacted.