-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
secp256r1
host function for signature verification (#1376)
### What Resolves #807 by adding a new host function `verify_sig_ecdsa_secp256r1` for ECDSA signature verification using secp256r1 curve. The function accepts following inputs: - `public_key: BytesObject` containing the 65-byte SEC-1 uncompressed ECDSA public key - `msg_digest: BytesObject` a 32-byte hash of the message - `signature`: the 64-byte signature `(r, s)` serialized as fixed-width big endian scalars The function is gated behind protocol 21 (`min_supported_protocol = 21`). PR with the associated XDR changes: stellar/stellar-xdr#178, stellar/rs-stellar-xdr#355 #### Metering and Calibration Two new cost types have been newly added: - `Sec1DecodePointUncompressed`: constant cost type representing the cost to decode the `public_key` - `VerifyEcdsaSecp256r1Sig` : constant cost type represent the cost of ECDSA sig verification A prevous cost type `ComputeEcdsaSecp256k1Sig` has been renamed to `DecodeEcdsaCurve256Sig`, which represents the cost of deserializing both the `secp256k1` and `secp256r1` signatures. Calibration: - each new cost type mentioned above have been benchmarked and calibrated. - plus a few experimental types have been added to answer key questions regarding the host interface (will provide a supplemental doc soon). #### Testing Unit tests have been added to test against various forms of invalid inputs. In addition, two set of test vectors has been added in integration test: - [NIST test vectors](https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip) - Google's [wycheproof](https://github.com/C2SP/wycheproof) test vectors
- Loading branch information
Showing
38 changed files
with
1,670 additions
and
248 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
/target | ||
.vscode | ||
/vendor | ||
lcov.info | ||
lcov.info | ||
.DS_Store |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 39 additions & 0 deletions
39
soroban-env-host/benches/common/cost_types/decode_ecdsa_curve256_sig.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
use crate::common::HostCostMeasurement; | ||
use ecdsa::signature::hazmat::PrehashSigner; | ||
use elliptic_curve::scalar::IsHigh; | ||
use k256::{ | ||
ecdsa::{Signature, SigningKey}, | ||
Secp256k1, | ||
}; | ||
use rand::{rngs::StdRng, RngCore}; | ||
use soroban_env_host::{ | ||
cost_runner::{DecodeEcdsaCurve256SigRun, DecodeEcdsaCurve256SigSample}, | ||
Host, | ||
}; | ||
|
||
pub(crate) struct DecodeEcdsaCurve256SigMeasure; | ||
|
||
impl HostCostMeasurement for DecodeEcdsaCurve256SigMeasure { | ||
type Runner = DecodeEcdsaCurve256SigRun<Secp256k1>; | ||
|
||
fn new_random_case( | ||
_host: &Host, | ||
rng: &mut StdRng, | ||
_input: u64, | ||
) -> DecodeEcdsaCurve256SigSample { | ||
let mut key_bytes = [0u8; 32]; | ||
rng.fill_bytes(&mut key_bytes); | ||
let signer = SigningKey::from_bytes(&key_bytes.into()).unwrap(); | ||
let mut msg_hash = [0u8; 32]; | ||
rng.fill_bytes(&mut msg_hash); | ||
let mut sig: Signature = signer.sign_prehash(&msg_hash).unwrap(); | ||
// in our host implementation, we are rejecting high `S`. so here we | ||
// normalize it to the low S before sending the result | ||
if bool::from(sig.s().is_high()) { | ||
sig = sig.normalize_s().unwrap(); | ||
} | ||
DecodeEcdsaCurve256SigSample { | ||
bytes: sig.to_vec(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
soroban-env-host/benches/common/cost_types/sec1_decode_point_uncompressed.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use crate::common::HostCostMeasurement; | ||
use p256::ecdsa::SigningKey; | ||
use rand::{rngs::StdRng, RngCore}; | ||
use soroban_env_host::{ | ||
cost_runner::{Sec1DecodePointSample, Sec1DecodePointUncompressedRun}, | ||
Host, | ||
}; | ||
|
||
pub(crate) struct Sec1DecodePointUncompressedMeasure {} | ||
|
||
impl HostCostMeasurement for Sec1DecodePointUncompressedMeasure { | ||
type Runner = Sec1DecodePointUncompressedRun; | ||
|
||
fn new_random_case(_host: &Host, rng: &mut StdRng, _input: u64) -> Sec1DecodePointSample { | ||
let mut key_bytes = [0u8; 32]; | ||
rng.fill_bytes(&mut key_bytes); | ||
let signer = SigningKey::from_bytes(&key_bytes.into()).unwrap(); | ||
let verifying_key = signer.verifying_key(); | ||
let bytes = verifying_key | ||
.to_encoded_point(false /* compress */) | ||
.to_bytes(); | ||
Sec1DecodePointSample { bytes } | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
soroban-env-host/benches/common/cost_types/verify_ecdsa_secp256r1_sig.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use crate::common::HostCostMeasurement; | ||
use ecdsa::signature::hazmat::PrehashSigner; | ||
use elliptic_curve::scalar::IsHigh; | ||
use p256::ecdsa::{Signature, SigningKey}; | ||
use rand::{rngs::StdRng, RngCore}; | ||
use soroban_env_host::{ | ||
cost_runner::{VerifyEcdsaSecp256r1SigRun, VerifyEcdsaSecp256r1SigSample}, | ||
xdr::Hash, | ||
Host, | ||
}; | ||
|
||
pub(crate) struct VerifyEcdsaSecp256r1SigMeasure {} | ||
|
||
impl HostCostMeasurement for VerifyEcdsaSecp256r1SigMeasure { | ||
type Runner = VerifyEcdsaSecp256r1SigRun; | ||
|
||
fn new_random_case( | ||
_host: &Host, | ||
rng: &mut StdRng, | ||
_input: u64, | ||
) -> VerifyEcdsaSecp256r1SigSample { | ||
let mut key_bytes = [0u8; 32]; | ||
rng.fill_bytes(&mut key_bytes); | ||
let signer = SigningKey::from_bytes(&key_bytes.into()).unwrap(); | ||
let mut msg_hash = [0u8; 32]; | ||
rng.fill_bytes(&mut msg_hash); | ||
let mut sig: Signature = signer.sign_prehash(&msg_hash).unwrap(); | ||
// in our host implementation, we are rejecting high `s`, we are doing it here too. | ||
if bool::from(sig.s().is_high()) { | ||
sig = sig.normalize_s().unwrap() | ||
} | ||
VerifyEcdsaSecp256r1SigSample { | ||
pub_key: signer.verifying_key().clone(), | ||
msg_hash: Hash::from(msg_hash), | ||
sig, | ||
} | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
soroban-env-host/benches/common/experimental/decode_secp256r1_sig.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
use crate::common::HostCostMeasurement; | ||
use ecdsa::signature::hazmat::PrehashSigner; | ||
use elliptic_curve::scalar::IsHigh; | ||
use rand::{rngs::StdRng, RngCore}; | ||
use soroban_env_host::{ | ||
cost_runner::{DecodeEcdsaCurve256SigSample, DecodeSecp256r1SigRun}, | ||
Host, | ||
}; | ||
|
||
pub(crate) struct DecodeSecp256r1SigMeasure {} | ||
|
||
impl HostCostMeasurement for DecodeSecp256r1SigMeasure { | ||
type Runner = DecodeSecp256r1SigRun; | ||
|
||
fn new_random_case( | ||
_host: &Host, | ||
rng: &mut StdRng, | ||
_input: u64, | ||
) -> DecodeEcdsaCurve256SigSample { | ||
use p256::ecdsa::{Signature, SigningKey}; | ||
|
||
let mut key_bytes = [0u8; 32]; | ||
rng.fill_bytes(&mut key_bytes); | ||
let signer = SigningKey::from_bytes(&key_bytes.into()).unwrap(); | ||
let mut msg_hash = [0u8; 32]; | ||
rng.fill_bytes(&mut msg_hash); | ||
let mut sig: Signature = signer.sign_prehash(&msg_hash).unwrap(); | ||
// in our host implementation, we are rejecting high `s`, we are doing it here too. | ||
if bool::from(sig.s().is_high()) { | ||
sig = sig.normalize_s().unwrap(); | ||
} | ||
DecodeEcdsaCurve256SigSample { | ||
bytes: sig.to_vec(), | ||
} | ||
} | ||
} |
Oops, something went wrong.