Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions p256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ rand_core = { version = "0.5", features = ["getrandom" ]}
default = ["arithmetic", "std"]
arithmetic = []
rand = ["elliptic-curve/rand_core"]
expose-arithmetic = ["arithmetic"]
test-vectors = []
std = ["elliptic-curve/std"]

Expand Down
28 changes: 28 additions & 0 deletions p256/examples/sign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#[cfg(feature = "arithmetic")]
use p256::arithmetic::Scalar;

#[cfg(not(feature = "arithmetic"))]
fn main() {}

#[cfg(feature = "arithmetic")]
fn main() {
let secret_seed = [1u8; 32];
let secret_maybe_scalar = Scalar::from_bytes(secret_seed);
let secret_scalar = secret_maybe_scalar.unwrap();

let ephemeral_seed = [2u8; 32];
let ephemeral_maybe_scalar = Scalar::from_bytes(ephemeral_seed);
let ephemeral_scalar = ephemeral_maybe_scalar.unwrap();

let hashed_msg = [3u8; 32];

let masking_seed = [4u8; 32];
let masking_maybe_scalar = Scalar::from_bytes(masking_seed);
let masking_scalar = masking_maybe_scalar.unwrap();

let signature = secret_scalar
.try_sign_prehashed(ephemeral_scalar, Some(masking_scalar), &hashed_msg)
.unwrap();

println!("signature: {:02x?}", signature.as_ref());
}
11 changes: 10 additions & 1 deletion p256/src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
//! A pure-Rust implementation of group operations on secp256r1.

#[cfg(feature = "expose-arithmetic")]
pub mod field;
#[cfg(not(feature = "expose-arithmetic"))]
mod field;
#[cfg(feature = "expose-arithmetic")]
pub mod scalar;
#[cfg(not(feature = "expose-arithmetic"))]
mod scalar;
#[cfg(feature = "expose-arithmetic")]
pub mod util;
#[cfg(not(feature = "expose-arithmetic"))]
mod util;
Comment on lines +3 to 14
Copy link
Member

@tarcieri tarcieri Jun 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to figure out a better solution for this sort of gating.

One option would be to make the arithmetic module mod arithmetic (no pub), and then re-export the types it contains at the toplevel when the arithmetic feature is enabled.

Since doc_cfg tags everything with the requisite cargo features, I don't think this would be confusing:

https://docs.rs/p256/0.3.0/p256/arithmetic/index.html

I might open a separate PR for discussion on that idea (skipping the expose-arithmetic stuff for now)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the easiest solution will be to use the cfg_if crate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that would work too.

For what it's worth I opened a PR with my suggested refactoring and I like it:

#58

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmh, agreed. This is just a hack to allow use of the arithmetic in an experimental/hazmat manner outside the crate while core pieces are missing. I actually think the arithmetic should be public, but that's another topic - this PR is just to exemplify a possible ECDSA implementation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nickray now that #58 is merged, you can refactor this to use something like the following in the toplevel of the crate:

#[cfg(feature = "expose-arithmetic"))]
#[cfg_attr(docsrs, doc_cfg(feature = "expose-arithmetic"))]
pub use arithmetic::{field, scalar, util};


#[cfg(any(feature = "test-vectors", test))]
Expand Down Expand Up @@ -45,7 +54,7 @@ const CURVE_EQUATION_B: FieldElement = FieldElement([
/// A point on the secp256r1 curve in affine coordinates.
#[derive(Clone, Copy, Debug)]
pub struct AffinePoint {
x: FieldElement,
pub(crate) x: FieldElement,
y: FieldElement,
}

Expand Down
7 changes: 5 additions & 2 deletions p256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use getrandom::getrandom;

use super::util::{adc, mac, sbb};

/// The number of 64-bit limbs used to represent a [`FieldElement`].
const LIMBS: usize = 4;

/// Constant representing the modulus
/// p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1
pub const MODULUS: FieldElement = FieldElement([
Expand Down Expand Up @@ -38,7 +41,7 @@ const R2: FieldElement = FieldElement([
// The internal representation is in little-endian order. Elements are always in
// Montgomery form; i.e., FieldElement(a) = aR mod p, with R = 2^256.
#[derive(Clone, Copy, Debug)]
pub struct FieldElement(pub(crate) [u64; 4]);
pub struct FieldElement(pub(crate) [u64; LIMBS]);

impl ConditionallySelectable for FieldElement {
fn conditional_select(a: &FieldElement, b: &FieldElement, choice: Choice) -> FieldElement {
Expand Down Expand Up @@ -112,7 +115,7 @@ impl FieldElement {
/// Returns None if the byte array does not contain a big-endian integer in the range
/// [0, p).
pub fn from_bytes(bytes: [u8; 32]) -> CtOption<Self> {
let mut w = [0u64; 4];
let mut w = [0u64; LIMBS];

// Interpret the bytes as a big-endian integer w.
w[3] = u64::from_be_bytes(bytes[0..8].try_into().unwrap());
Expand Down
Loading