Skip to content
Merged
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
19 changes: 10 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ ed448-goldilocks = { path = "ed448-goldilocks" }
hash2curve = { path = "hash2curve" }
primefield = { path = "primefield" }
primeorder = { path = "primeorder" }

crypto-common = { git = "https://github.com/RustCrypto/traits" }
ecdsa = { git = "https://github.com/RustCrypto/signatures" }
elliptic-curve = { git = "https://github.com/RustCrypto/traits" }
17 changes: 10 additions & 7 deletions bignp256/src/ecdh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@
//!
#![cfg_attr(feature = "getrandom", doc = "```")]
#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
//! // NOTE: requires 'getrandom' feature is enabled
//!
//! use bignp256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret};
//! use bignp256::{
//! EncodedPoint, PublicKey,
//! ecdh::EphemeralSecret,
//! elliptic_curve::Generate
//! };
//!
//! // Alice
//! let alice_secret = EphemeralSecret::generate();
Expand All @@ -23,22 +28,20 @@
//! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key());
//!
//! // Alice decodes Bob's serialized public key and computes a shared secret from it
//! let bob_public =
//! PublicKey::from_encoded_point(bob_pk_bytes).expect("bob's public key is invalid!"); // In real usage, don't panic, handle this!
//!
//! let bob_public = PublicKey::from_encoded_point(bob_pk_bytes)?;
//! let alice_shared = alice_secret.diffie_hellman(&bob_public.into());
//!
//! // Bob decodes Alice's serialized public key and computes the same shared secret
//! let alice_public =
//! PublicKey::from_encoded_point(alice_pk_bytes).expect("alice's public key is invalid!"); // In real usage, don't panic, handle this!
//!
//! let alice_public = PublicKey::from_encoded_point(alice_pk_bytes)?;
//! let bob_shared = bob_secret.diffie_hellman(&alice_public.into());
//!
//! // Both participants arrive on the same shared secret
//! assert_eq!(
//! alice_shared.raw_secret_bytes(),
//! bob_shared.raw_secret_bytes()
//! );
//! # Ok(())
//! # }
//! ```

pub use elliptic_curve::ecdh::diffie_hellman;
Expand Down
23 changes: 11 additions & 12 deletions bignp256/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@
//!
//! ## Usage
//!
//! NOTE: requires the `dsa` crate feature enabled, and `rand_core` dependency
//! with `getrandom` feature enabled.
#![cfg_attr(feature = "std", doc = "```")]
#![cfg_attr(not(feature = "std"), doc = "```ignore")]
//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
//! use getrandom::{SysRng, rand_core::TryRngCore};
#![cfg_attr(all(feature = "ecdsa", feature = "getrandom"), doc = "```")]
#![cfg_attr(not(all(feature = "ecdsa", feature = "getrandom")), doc = "```ignore")]
//! # fn main() -> Result<(), Box<dyn core::error::Error>> {
//! // NOTE: requires the `ecdsa` and `getrandom` crate features are enabled
//! use bignp256::{
//! ecdsa::{Signature, SigningKey, signature::Signer},
//! SecretKey
//! ecdsa::{SigningKey, Signature, signature::Signer},
//! elliptic_curve::{Generate, sec1::ToEncodedPoint},
//! SecretKey,
//! };
//!
//! // Signing
//! let secret_key = SecretKey::try_from_rng(&mut SysRng).unwrap(); // serialize with `::to_bytes()`
//! let signing_key = SigningKey::new(&secret_key)?;
//! let signing_key = SigningKey::generate(); // Serialize with `::to_bytes()`
//! let verifying_key_bytes = signing_key.verifying_key().to_bytes();
//!
//! let message = b"test message";
//! let signature: Signature = signing_key.sign(message);
//!
//! // Verifying
//! use bignp256::ecdsa::{VerifyingKey, signature::Verifier};
//! // Verification
//! use bignp256::{EncodedPoint, ecdsa::{VerifyingKey, signature::Verifier}};
//!
//! let verifying_key = VerifyingKey::from_bytes(&verifying_key_bytes)?;
//! verifying_key.verify(message, &signature)?;
Expand Down
50 changes: 36 additions & 14 deletions bignp256/src/ecdsa/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ use crate::{BignP256, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey, Sca
use belt_hash::{BeltHash, Digest};
use core::fmt::{self, Debug};
use elliptic_curve::{
Curve, Field, FieldBytesEncoding, Group, PrimeField,
Curve, Field, FieldBytesEncoding, Generate, Group, PrimeField,
array::{Array, sizes::U32, typenum::Unsigned},
ops::Reduce,
point::AffineCoordinates,
subtle::{Choice, ConstantTimeEq},
};
use rand_core::TryCryptoRng;
use signature::{Error, KeypairRef, MultipartSigner, Result, Signer, hazmat::PrehashSigner};

/// BignP256 secret key used for signing messages and producing signatures.
Expand All @@ -46,12 +47,6 @@ pub struct SigningKey {
}

impl SigningKey {
/// Create signing key from a signer's distinguishing identifier and
/// secret key.
pub fn new(secret_key: &SecretKey) -> Result<Self> {
Self::from_nonzero_scalar(secret_key.to_nonzero_scalar())
}

/// Parse signing key from big endian-encoded bytes.
pub fn from_bytes(bytes: &FieldBytes) -> Result<Self> {
Self::from_slice(bytes)
Expand All @@ -60,18 +55,19 @@ impl SigningKey {
/// Parse signing key from big endian-encoded byte slice containing a secret
/// scalar value.
pub fn from_slice(slice: &[u8]) -> Result<Self> {
let secret_scalar = NonZeroScalar::try_from(slice).map_err(|_| Error::new())?;
Self::from_nonzero_scalar(secret_scalar)
NonZeroScalar::try_from(slice)
.map(Into::into)
.map_err(|_| Error::new())
}

/// Create a signing key from a non-zero scalar.
pub fn from_nonzero_scalar(secret_scalar: NonZeroScalar) -> Result<Self> {
pub fn from_nonzero_scalar(secret_scalar: NonZeroScalar) -> Self {
let public_key = PublicKey::from_secret_scalar(&secret_scalar);
let verifying_key = VerifyingKey::new(public_key)?;
Ok(Self {

Self {
secret_scalar,
verifying_key,
})
verifying_key: public_key.into(),
}
}

/// Serialize as bytes.
Expand All @@ -96,6 +92,14 @@ impl SigningKey {
}
}

impl Generate for SigningKey {
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> core::result::Result<Self, R::Error> {
NonZeroScalar::try_generate_from_rng(rng).map(Into::into)
}
}

//
// `*Signer` trait impls
//
Expand Down Expand Up @@ -194,6 +198,24 @@ impl PartialEq for SigningKey {
}
}

impl From<NonZeroScalar> for SigningKey {
fn from(secret_scalar: NonZeroScalar) -> Self {
Self::from_nonzero_scalar(secret_scalar)
}
}

impl From<SecretKey> for SigningKey {
fn from(secret_key: SecretKey) -> Self {
secret_key.to_nonzero_scalar().into()
}
}

impl From<SigningKey> for SecretKey {
fn from(signing_key: SigningKey) -> Self {
signing_key.secret_scalar.into()
}
}

impl KeypairRef for SigningKey {
type VerifyingKey = VerifyingKey;
}
40 changes: 24 additions & 16 deletions bignp256/src/ecdsa/verifying.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,28 @@ use elliptic_curve::sec1::ToEncodedPoint;
///
/// The serialization leverages the encoding used by the [`PublicKey`] type,
/// which is a binary-oriented ASN.1 DER encoding.
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
pub struct VerifyingKey {
/// Signer's public key.
public_key: PublicKey,
}

impl VerifyingKey {
/// Initialize [`VerifyingKey`] from a signer's distinguishing identifier
/// and public key.
pub fn new(public_key: PublicKey) -> Result<Self> {
Ok(Self { public_key })
}

/// Initialize [`VerifyingKey`] from an affine point.
///
/// Returns an [`Error`] if the given affine point is the additive identity
/// (a.k.a. point at infinity).
pub fn from_affine(affine: AffinePoint) -> Result<Self> {
let public_key = PublicKey::from_affine(affine).map_err(|_| Error::new())?;
Self::new(public_key)
Ok(Self {
public_key: PublicKey::from_affine(affine).map_err(|_| Error::new())?,
})
}

/// Parse a [`VerifyingKey`] from a byte slice.
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
Ok(Self {
public_key: PublicKey::from_bytes(bytes).map_err(|_| Error::new())?,
})
}

/// Borrow the inner [`AffinePoint`] for this public key.
Expand All @@ -90,12 +92,6 @@ impl VerifyingKey {
hasher.finalize_fixed()
}

/// Parse a [`VerifyingKey`] from a byte slice.
pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
let public_key = PublicKey::from_bytes(bytes).map_err(|_| Error::new())?;
Self::new(public_key)
}

/// Serialize the [`VerifyingKey`] as a byte array.
#[cfg(feature = "alloc")]
pub fn to_bytes(&self) -> Box<[u8]> {
Expand Down Expand Up @@ -185,6 +181,18 @@ impl AsRef<AffinePoint> for VerifyingKey {
}
}

impl From<PublicKey> for VerifyingKey {
fn from(public_key: PublicKey) -> VerifyingKey {
VerifyingKey { public_key }
}
}

impl From<&PublicKey> for VerifyingKey {
fn from(public_key: &PublicKey) -> VerifyingKey {
VerifyingKey::from(*public_key)
}
}

impl From<VerifyingKey> for PublicKey {
fn from(verifying_key: VerifyingKey) -> PublicKey {
verifying_key.public_key
Expand All @@ -193,7 +201,7 @@ impl From<VerifyingKey> for PublicKey {

impl From<&VerifyingKey> for PublicKey {
fn from(verifying_key: &VerifyingKey) -> PublicKey {
verifying_key.public_key
PublicKey::from(*verifying_key)
}
}

Expand Down
46 changes: 17 additions & 29 deletions bignp256/src/secret_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::str::FromStr;
use der::{SecretDocument, asn1::OctetStringRef};

use crate::{ALGORITHM_OID, PublicKey, ScalarValue};
use elliptic_curve::{Error, array::typenum::Unsigned, zeroize::Zeroizing};
use elliptic_curve::{Error, Generate, array::typenum::Unsigned, zeroize::Zeroizing};
use pkcs8::{
AssociatedOid, DecodePrivateKey, EncodePrivateKey, ObjectIdentifier,
spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier},
Expand All @@ -24,28 +24,6 @@ pub struct SecretKey {
impl SecretKey {
const MIN_SIZE: usize = 24;

/// Generate a random [`SecretKey`].
///
/// # Panics
///
/// If the system's cryptographically secure RNG has an internal error.
#[cfg(feature = "getrandom")]
pub fn generate() -> Self {
Self {
inner: NonZeroScalar::generate().into(),
}
}

/// Generate a random [`SecretKey`].
#[cfg(feature = "arithmetic")]
pub fn try_from_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> core::result::Result<Self, R::Error> {
Ok(Self {
inner: NonZeroScalar::try_from_rng(rng)?.into(),
})
}

/// Borrow the inner secret [`elliptic_curve::ScalarValue`] value.
///
/// # ⚠️ Warning
Expand Down Expand Up @@ -117,6 +95,14 @@ impl SecretKey {
}
}

impl AssociatedAlgorithmIdentifier for SecretKey {
type Params = ObjectIdentifier;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> = AlgorithmIdentifier {
oid: ALGORITHM_OID,
parameters: Some(BignP256::OID),
};
}

impl From<SecretKey> for NonZeroScalar {
fn from(secret_key: SecretKey) -> NonZeroScalar {
secret_key.to_nonzero_scalar()
Expand All @@ -139,12 +125,14 @@ impl From<&NonZeroScalar> for SecretKey {
}
}

impl AssociatedAlgorithmIdentifier for SecretKey {
type Params = ObjectIdentifier;
const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params> = AlgorithmIdentifier {
oid: ALGORITHM_OID,
parameters: Some(BignP256::OID),
};
impl Generate for SecretKey {
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
rng: &mut R,
) -> core::result::Result<Self, R::Error> {
Ok(Self {
inner: ScalarValue::try_generate_from_rng(rng)?,
})
}
}

impl TryFrom<pkcs8::PrivateKeyInfoRef<'_>> for SecretKey {
Expand Down
Loading