Skip to content

P256

The P256 guest library uses openvm-ecc-guest to provide elliptic curve operations over the Secp256r1 curve. It is intended as a patch for the p256 rust crate and can be swapped in for accelerated signature verification usage. Note that signing from a private key is not supported.

Example ECDSA verification

See a working example here.

To use the P256 guest library for ECDSA verification, add the following dependencies to Cargo.toml:

openvm-algebra-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.1" }
openvm-ecc-guest = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.1" }
openvm-p256 = { git = "https://github.com/openvm-org/openvm.git", tag = "v2.0.1", package = "p256" }

The example verifies a P256 ECDSA signature from a SEC1-encoded public key. The 04 byte prefix on the public key indicates an uncompressed SEC1 point, followed by the 32-byte x-coordinate and 32-byte y-coordinate.

use hex_literal::hex;
use openvm as _;
use openvm_p256::ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey};
 
openvm::init!();
 
fn main() {
    // Adapted from the FIPS 186-4 ECDSA test vectors for P-256 with SHA-384.
    let public_key = hex!(
        "04
         e0e7b99bc62d8dd67883e39ed9fa0657789c5ff556cc1fd8dd1e2a55e9e3f243
         63fbfd0232b95578075c903a4dbf85ad58f8350516e1ec89b0ee1f5e1362da69"
    );
    let verifier = VerifyingKey::from_sec1_bytes(&public_key).unwrap();
    let signature = Signature::from_scalars(
        hex!("f5087878e212b703578f5c66f434883f3ef414dc23e2e8d8ab6a8d159ed5ad83"),
        hex!("306b4c6c20213707982dffbb30fba99b96e792163dd59dbe606e734328dd7c8a"),
    )
    .unwrap();
    let prehash = hex!(
        "d9c83b92fa0979f4a5ddbd8dd22ab9377801c3c31bf50f932ace0d2146e2574da0d5552dbed4b18836280e9f94558ea6"
    );
    verifier.verify_prehash(&prehash, &signature).unwrap();
}

Config parameters

For the guest program to build successfully, all used moduli and curves must be declared in the .toml config file in the following format:

[app_vm_config.modular]
supported_moduli = ["115792089210356248762697446949407573530086143415290314195533631308867097853951", "115792089210356248762697446949407573529996955224135760342422259061068512044369"]
 
[[app_vm_config.ecc.supported_curves]]
struct_name = "P256Point"
modulus = "115792089210356248762697446949407573530086143415290314195533631308867097853951"
scalar = "115792089210356248762697446949407573529996955224135760342422259061068512044369"
a = "115792089210356248762697446949407573530086143415290314195533631308867097853948"
b = "41058363725152142129326129780047268409114441015993725554835256314039467401291"

The supported_moduli parameter is a list of moduli that the guest program will use. As mentioned in the algebra extension chapter, the order of moduli in [app_vm_config.modular] must match the order in the moduli_init! macro.

The ecc.supported_curves parameter is a list of supported curves that the guest program will use. They must be provided in decimal format in the .toml file. For multiple curves create multiple [[app_vm_config.ecc.supported_curves]] sections. The order of curves in [[app_vm_config.ecc.supported_curves]] must match the order in the sw_init! macro. Also, the struct_name field must be the name of the elliptic curve struct created by sw_declare!.