From eb276c5eadae5d5f78fc165929106979fae5a944 Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 17:13:38 +0300 Subject: [PATCH 1/8] Add pkcs8 module and move dsa to ecdsa --- Cargo.lock | 5 +- Cargo.toml | 4 + bign256/Cargo.toml | 14 +- bign256/src/arithmetic/scalar.rs | 2 +- bign256/src/ecdh.rs | 47 ++++++ bign256/src/{dsa.rs => ecdsa.rs} | 8 +- bign256/src/{dsa => ecdsa}/signing.rs | 0 bign256/src/{dsa => ecdsa}/verifying.rs | 29 ++-- bign256/src/lib.rs | 64 ++++---- bign256/src/public_key.rs | 190 +++++++++++++++++++++++ bign256/src/secret_key.rs | 158 +++++++++++++++++++ bign256/tests/dsa.rs | 21 +-- bign256/tests/ecdh.rs | 29 ++++ bign256/tests/examples/pkcs8-private.der | Bin 0 -> 65 bytes bign256/tests/examples/pkcs8-private.pem | 4 + bign256/tests/examples/pkcs8-public.der | Bin 0 -> 95 bytes bign256/tests/examples/pkcs8-public.pem | 4 + bign256/tests/pkcs8.rs | 86 ++++++++++ 18 files changed, 599 insertions(+), 66 deletions(-) create mode 100644 bign256/src/ecdh.rs rename bign256/src/{dsa.rs => ecdsa.rs} (95%) rename bign256/src/{dsa => ecdsa}/signing.rs (100%) rename bign256/src/{dsa => ecdsa}/verifying.rs (88%) create mode 100644 bign256/src/public_key.rs create mode 100644 bign256/src/secret_key.rs create mode 100644 bign256/tests/ecdh.rs create mode 100644 bign256/tests/examples/pkcs8-private.der create mode 100644 bign256/tests/examples/pkcs8-private.pem create mode 100644 bign256/tests/examples/pkcs8-public.der create mode 100644 bign256/tests/examples/pkcs8-public.pem create mode 100644 bign256/tests/pkcs8.rs diff --git a/Cargo.lock b/Cargo.lock index 2e2bc8af..9c045f4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,13 +54,16 @@ version = "0.14.0-pre" dependencies = [ "belt-hash", "criterion", + "der", "elliptic-curve", "hex", "hex-literal", + "pkcs8", "primeorder", "proptest", "rand_core", "rfc6979", + "sec1", "signature", ] @@ -218,8 +221,6 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "const-oid" version = "0.10.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e3352a27098ba6b09546e5f13b15165e6a88b5c2723afecb3ea9576b27e3ea" [[package]] name = "cpufeatures" diff --git a/Cargo.toml b/Cargo.toml index 126bda12..0845a36c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,7 @@ members = [ [profile.dev] opt-level = 2 + +[patch.crates-io] +#pkcs8 = { path = "/Users/makavity/dev/crypto/formats/pkcs8" } +const-oid = { path = "/Users/makavity/dev/crypto/formats/const-oid"} \ No newline at end of file diff --git a/bign256/Cargo.toml b/bign256/Cargo.toml index 23350900..12076348 100644 --- a/bign256/Cargo.toml +++ b/bign256/Cargo.toml @@ -24,22 +24,28 @@ primeorder = { version = "=0.14.0-pre.0", optional = true, path = "../primeorder signature = { version = "=2.3.0-pre.3", optional = true } belt-hash = { version = "=0.2.0-pre.3", optional = true, default-features = false } rfc6979 = { version = "=0.5.0-pre.3", optional = true } +rand_core = "0.6.4" +pkcs8 = { version = "0.11.0-pre.0", optional = true } +sec1 = { version = "0.8.0-pre.1", optional = true } +der = { version = "0.8.0-pre.0" } [dev-dependencies] criterion = "0.5" hex-literal = "0.4" proptest = "1" rand_core = { version = "0.6", features = ["getrandom"] } -hex = {version = "0.4" } +hex = { version = "0.4" } [features] -default = ["arithmetic", "pkcs8", "std", "dsa"] +default = ["arithmetic", "pkcs8", "std", "ecdsa", "pem"] alloc = ["elliptic-curve/alloc", "primeorder?/alloc"] std = ["alloc", "elliptic-curve/std", "signature?/std"] -dsa = ["arithmetic", "dep:rfc6979", "dep:signature", "dep:belt-hash"] +ecdsa = ["arithmetic", "dep:rfc6979", "dep:signature", "dep:belt-hash"] arithmetic = ["dep:primeorder", "elliptic-curve/arithmetic"] -pkcs8 = ["elliptic-curve/pkcs8"] +pem = ["pkcs8", "sec1/pem"] +pkcs8 = ["dep:pkcs8"] +ecdh = ["arithmetic", "elliptic-curve/ecdh"] [[bench]] name = "field" diff --git a/bign256/src/arithmetic/scalar.rs b/bign256/src/arithmetic/scalar.rs index 340f5169..2fecc778 100644 --- a/bign256/src/arithmetic/scalar.rs +++ b/bign256/src/arithmetic/scalar.rs @@ -15,7 +15,7 @@ mod scalar_impl; use self::scalar_impl::*; -use crate::{BignP256, FieldBytes, FieldBytesEncoding, SecretKey, ORDER_HEX, U256}; +use crate::{BignP256, FieldBytes, FieldBytesEncoding, ORDER_HEX, SecretKey, U256}; use core::{ iter::{Product, Sum}, ops::{AddAssign, MulAssign, Neg, Shr, ShrAssign, SubAssign}, diff --git a/bign256/src/ecdh.rs b/bign256/src/ecdh.rs new file mode 100644 index 00000000..bbe3681d --- /dev/null +++ b/bign256/src/ecdh.rs @@ -0,0 +1,47 @@ +//! Elliptic Curve Diffie-Hellman (Ephemeral) Support. +//! +//! This module contains a high-level interface for performing ephemeral +//! Diffie-Hellman key exchanges using the bign256 elliptic curve. +//! +//! # Usage +//! +//! This usage example is from the perspective of two participants in the +//! exchange, nicknamed "Alice" and "Bob". +//! +//! ``` +//! use bign256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; +//! use rand_core::OsRng; // requires 'getrandom' feature +//! +//! // Alice +//! let alice_secret = EphemeralSecret::random(&mut OsRng); +//! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); +//! +//! // Bob +//! let bob_secret = EphemeralSecret::random(&mut OsRng); +//! 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_sec1_bytes(bob_pk_bytes.as_ref()) +//! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! +//! +//! let alice_shared = alice_secret.diffie_hellman(&bob_public); +//! +//! // Bob decodes Alice's serialized public key and computes the same shared secret +//! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) +//! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! +//! +//! let bob_shared = bob_secret.diffie_hellman(&alice_public); +//! +//! // Both participants arrive on the same shared secret +//! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); +//! ``` + +pub use elliptic_curve::ecdh::diffie_hellman; + +use crate::BignP256; + +/// NIST P-256 Ephemeral Diffie-Hellman Secret. +pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; + +/// Shared secret value computed via ECDH key agreement. +pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; diff --git a/bign256/src/dsa.rs b/bign256/src/ecdsa.rs similarity index 95% rename from bign256/src/dsa.rs rename to bign256/src/ecdsa.rs index ffd084a7..5197eaf0 100644 --- a/bign256/src/dsa.rs +++ b/bign256/src/ecdsa.rs @@ -9,21 +9,21 @@ //! # fn example() -> Result<(), Box> { //! use rand_core::OsRng; // requires 'getrandom` feature //! use bign256::{ -//! dsa::{Signature, SigningKey, signature::Signer}, +//! ecdsa::{Signature, SigningKey, signature::Signer}, //! SecretKey //! }; //! //! // Signing //! let secret_key = SecretKey::random(&mut OsRng); // serialize with `::to_bytes()` //! let signing_key = SigningKey::new(&secret_key)?; -//! let verifying_key_bytes = signing_key.verifying_key().to_sec1_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 bign256::dsa::{VerifyingKey, signature::Verifier}; +//! use bign256::ecdsa::{VerifyingKey, signature::Verifier}; //! -//! let verifying_key = VerifyingKey::from_sec1_bytes(&verifying_key_bytes)?; +//! let verifying_key = VerifyingKey::from_bytes(&verifying_key_bytes)?; //! verifying_key.verify(message, &signature)?; //! # Ok(()) //! # } diff --git a/bign256/src/dsa/signing.rs b/bign256/src/ecdsa/signing.rs similarity index 100% rename from bign256/src/dsa/signing.rs rename to bign256/src/ecdsa/signing.rs diff --git a/bign256/src/dsa/verifying.rs b/bign256/src/ecdsa/verifying.rs similarity index 88% rename from bign256/src/dsa/verifying.rs rename to bign256/src/ecdsa/verifying.rs index 64ce212f..54438f8f 100644 --- a/bign256/src/dsa/verifying.rs +++ b/bign256/src/ecdsa/verifying.rs @@ -15,9 +15,7 @@ //! ``` use super::{Signature, BELT_OID}; -use crate::{ - AffinePoint, BignP256, EncodedPoint, FieldBytes, Hash, ProjectivePoint, PublicKey, Scalar, -}; +use crate::{AffinePoint, BignP256, EncodedPoint, FieldBytes, Hash, ProjectivePoint, PublicKey, Scalar}; use belt_hash::{ digest::{Digest, FixedOutput}, BeltHash, @@ -26,13 +24,11 @@ use elliptic_curve::{ array::{consts::U32, typenum::Unsigned, Array}, group::GroupEncoding, ops::{LinearCombination, Reduce}, - sec1::ToEncodedPoint, Curve, Field, Group, }; use signature::{hazmat::PrehashVerifier, Error, Result, Verifier}; -#[cfg(feature = "alloc")] -use alloc::boxed::Box; +use elliptic_curve::sec1::ToEncodedPoint; /// Bign256 public key used for verifying signatures are valid for a given /// message. @@ -88,22 +84,17 @@ impl VerifyingKey { hasher.update(msg); hasher.finalize_fixed() } - - /// Initialize [`VerifyingKey`] from a SEC1-encoded public key. - pub fn from_sec1_bytes(bytes: &[u8]) -> Result { - let public_key = PublicKey::from_sec1_bytes(bytes).map_err(|_| Error::new())?; + + /// Parse a [`VerifyingKey`] from a byte slice. + pub fn from_bytes(bytes: &[u8]) -> Result { + let public_key = PublicKey::from_bytes(bytes).map_err(|_| Error::new())?; Self::new(public_key) } - - /// Convert this [`VerifyingKey`] into the - /// `Elliptic-Curve-Point-to-Octet-String` encoding described in - /// SEC 1: Elliptic Curve Cryptography (Version 2.0) section 2.3.3 - /// (page 10). - /// - /// + + /// Serialize the [`VerifyingKey`] as a byte array. #[cfg(feature = "alloc")] - pub fn to_sec1_bytes(&self) -> Box<[u8]> { - self.public_key.to_sec1_bytes() + pub fn to_bytes(&self) -> Box<[u8]> { + self.public_key.to_bytes() } } diff --git a/bign256/src/lib.rs b/bign256/src/lib.rs index 2f6c5862..036459ff 100644 --- a/bign256/src/lib.rs +++ b/bign256/src/lib.rs @@ -1,5 +1,5 @@ // #![no_std] -#![no_std] +// #![no_std] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc = include_str!("../README.md")] #![doc( @@ -27,34 +27,37 @@ )] #[cfg(feature = "alloc")] -#[allow(unused_extern_crates)] extern crate alloc; +pub use elliptic_curve::{self, bigint::U256}; +use elliptic_curve::{bigint::ArrayEncoding, consts::U32, Error, FieldBytesEncoding}; + +#[cfg(feature = "arithmetic")] +pub use arithmetic::{AffinePoint, ProjectivePoint, scalar::Scalar}; + +/// Bign256 result type +pub type Result = core::result::Result; + #[cfg(feature = "arithmetic")] pub mod arithmetic; #[cfg(any(feature = "test-vectors", test))] pub mod test_vectors; -#[cfg(feature = "dsa")] -pub mod dsa; - -pub use elliptic_curve::{self, bigint::U256}; - +#[cfg(feature = "ecdsa")] +pub mod ecdsa; +#[cfg(feature = "ecdh")] +pub mod ecdh; #[cfg(feature = "arithmetic")] -pub use arithmetic::{scalar::Scalar, AffinePoint, ProjectivePoint}; +pub mod public_key; +#[cfg(feature = "arithmetic")] +pub mod secret_key; #[cfg(feature = "pkcs8")] -pub use elliptic_curve::pkcs8; - -use elliptic_curve::{ - array::Array, - bigint::ArrayEncoding, - consts::{U32, U33}, - FieldBytesEncoding, -}; +const ALGORITHM_OID: pkcs8::ObjectIdentifier = + pkcs8::ObjectIdentifier::new_unwrap("1.2.112.0.2.0.34.101.45.2.1"); -#[cfg(feature = "dsa")] +#[cfg(feature = "ecdsa")] type Hash = belt_hash::digest::Output; /// Order of BIGN P-256's elliptic curve group (i.e. scalar modulus) in hexadecimal. @@ -103,12 +106,9 @@ impl elliptic_curve::point::PointCompaction for BignP256 { #[cfg(feature = "pkcs8")] impl pkcs8::AssociatedOid for BignP256 { const OID: pkcs8::ObjectIdentifier = - pkcs8::ObjectIdentifier::new_unwrap("1.2.112.0.2.0.34.101.45.1"); + pkcs8::ObjectIdentifier::new_unwrap("1.2.112.0.2.0.34.101.45.3.1"); } -/// Compressed SEC1-encoded BIGN P256 curve point. -pub type CompressedPoint = Array; - /// BIGN P-256 field element serialized as bytes. /// /// Byte array containing a serialized field element value (base field or scalar). @@ -132,14 +132,26 @@ impl FieldBytesEncoding for U256 { pub type NonZeroScalar = elliptic_curve::NonZeroScalar; /// BIGN P-256 public key. +// #[cfg(feature = "arithmetic")] +// pub type PublicKey = elliptic_curve::PublicKey; + +/// Generic scalar type with primitive functionality.# #[cfg(feature = "arithmetic")] -pub type PublicKey = elliptic_curve::PublicKey; +pub type ScalarPrimitive = elliptic_curve::ScalarPrimitive; -/// BIGN P-256 secret key. -pub type SecretKey = elliptic_curve::SecretKey; +/// Elliptic curve BignP256 public key. +#[cfg(feature = "arithmetic")] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct PublicKey { + point: elliptic_curve::AffinePoint, +} -#[cfg(not(feature = "arithmetic"))] -impl elliptic_curve::sec1::ValidatePublicKey for BignP256 {} +/// Elliptic curve BignP256 Secret Key +#[cfg(feature = "arithmetic")] +#[derive(Copy, Clone, Debug)] +pub struct SecretKey { + inner: ScalarPrimitive, +} /// Bit representation of a BIGN P-256 scalar field element. #[cfg(feature = "bits")] diff --git a/bign256/src/public_key.rs b/bign256/src/public_key.rs new file mode 100644 index 00000000..f0c6eba4 --- /dev/null +++ b/bign256/src/public_key.rs @@ -0,0 +1,190 @@ +//! Public key types and traits + +use core::fmt::Display; +use core::str::FromStr; + +use elliptic_curve::{ + AffinePoint, + CurveArithmetic, + Error, + Group, + array::Array, + point::NonIdentity, + sec1::{FromEncodedPoint, ToEncodedPoint} +}; +use pkcs8::{ + AssociatedOid, + DecodePublicKey, + EncodePublicKey, + ObjectIdentifier, + spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier} +}; + +use crate::{ALGORITHM_OID, BignP256, EncodedPoint, NonZeroScalar, ProjectivePoint, PublicKey}; +impl PublicKey { + /// Convert an [`AffinePoint`] into a [`PublicKey`] + pub fn from_affine(point: AffinePoint) -> Result { + if ProjectivePoint::from(point).is_identity().into() { + Err(Error) + } else { + Ok(Self { point }) + } + } + + /// Compute a [`PublicKey`] from a secret [`NonZeroScalar`] value + /// (i.e. a secret key represented as a raw scalar value) + pub fn from_secret_scalar(scalar: &NonZeroScalar) -> Self { + // `NonZeroScalar` ensures the resulting point is not the identity + #[allow(clippy::arithmetic_side_effects)] + Self { + point: (::ProjectivePoint::generator() * scalar.as_ref()) + .to_affine(), + } + } + + /// Borrow the inner [`AffinePoint`] from this [`PublicKey`]. + /// + /// In ECC, public keys are elliptic curve points. + pub fn as_affine(&self) -> &AffinePoint { + &self.point + } + + /// Convert this [`PublicKey`] to a [`ProjectivePoint`] for the given curve + pub fn to_projective(&self) -> ProjectivePoint { + self.point.into() + } + + /// Convert this [`PublicKey`] to a [`NonIdentity`] of the inner [`AffinePoint`] + pub fn to_nonidentity(&self) -> NonIdentity> { + NonIdentity::new(self.point).unwrap() + } + + /// Get [`PublicKey`] from bytes + pub fn from_bytes(bytes: &[u8]) -> Result { + let mut bytes = Array::clone_from_slice(bytes); + // It is because public_key in little endian + bytes[..32].reverse(); + bytes[32..].reverse(); + + let point = EncodedPoint::from_untagged_bytes(&bytes); + let affine = AffinePoint::::from_encoded_point(&point); + if affine.is_none().into() { + Err(Error) + } + else { + Ok(Self { point: affine.unwrap() }) + } + } + + #[cfg(feature = "alloc")] + /// Get bytes from [`PublicKey`] + pub fn to_bytes(&self) -> Box<[u8]> { + let mut bytes = self.point.to_encoded_point(false).to_bytes(); + bytes[1..32 + 1].reverse(); + bytes[33..].reverse(); + bytes[1..].to_vec().into_boxed_slice() + } +} + +impl AsRef> for PublicKey { + fn as_ref(&self) -> &AffinePoint { + self.as_affine() + } +} +impl Copy for PublicKey {} +impl From>> for PublicKey { + fn from(value: NonIdentity>) -> Self { + Self::from(&value) + } +} + +impl From<&NonIdentity>> for PublicKey { + fn from(value: &NonIdentity>) -> Self { + Self { + point: value.to_point(), + } + } +} + +impl From for NonIdentity> { + fn from(value: PublicKey) -> Self { + Self::from(&value) + } +} + +impl From<&PublicKey> for NonIdentity> { + fn from(value: &PublicKey) -> Self { + PublicKey::to_nonidentity(value) + } +} + +#[cfg(feature = "pkcs8")] +impl AssociatedAlgorithmIdentifier for PublicKey { + type Params = ObjectIdentifier; + + const ALGORITHM_IDENTIFIER: AlgorithmIdentifier = AlgorithmIdentifier { + oid: ALGORITHM_OID, + parameters: Some(BignP256::OID), + }; +} + +#[cfg(feature = "pkcs8")] +impl TryFrom> for PublicKey { + type Error = pkcs8::spki::Error; + + fn try_from(spki: pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result { + Self::try_from(&spki) + } +} + +#[cfg(feature = "pkcs8")] +impl TryFrom<&pkcs8::SubjectPublicKeyInfoRef<'_>> for PublicKey { + type Error = pkcs8::spki::Error; + + fn try_from(spki: &pkcs8::SubjectPublicKeyInfoRef<'_>) -> pkcs8::spki::Result { + spki.algorithm.assert_oids(ALGORITHM_OID, BignP256::OID)?; + + let public_key_bytes = spki + .subject_public_key + .as_bytes() + .ok_or_else(|| der::Tag::BitString.value_error())?; + + Self::from_bytes(public_key_bytes).map_err(|_| pkcs8::spki::Error::KeyMalformed) + } +} + +#[cfg(all(feature = "alloc", feature = "pkcs8"))] +impl EncodePublicKey for PublicKey { + fn to_public_key_der(&self) -> pkcs8::spki::Result { + let pk_bytes = self.to_bytes(); + let subject_public_key = der::asn1::BitStringRef::new(0, &pk_bytes)?; + + pkcs8::SubjectPublicKeyInfo { + algorithm: Self::ALGORITHM_IDENTIFIER, + subject_public_key, + } + .try_into() + } +} + +#[cfg(feature = "pem")] +impl FromStr for PublicKey { + type Err = Error; + + fn from_str(s: &str) -> Result { + Self::from_public_key_pem(s).map_err(|_| Error) + } +} + +#[cfg(feature = "pem")] +impl Display for PublicKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + self.to_public_key_pem(Default::default()) + .expect("PEM encoding error") + ) + } +} + diff --git a/bign256/src/secret_key.rs b/bign256/src/secret_key.rs new file mode 100644 index 00000000..9390d1f6 --- /dev/null +++ b/bign256/src/secret_key.rs @@ -0,0 +1,158 @@ +//! Bign256 secret key. + +use core::str::FromStr; +use der::SecretDocument; + +use elliptic_curve::{array::typenum::Unsigned, Error, zeroize::Zeroizing}; +use pkcs8::{AssociatedOid, DecodePrivateKey, EncodePrivateKey, ObjectIdentifier, spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier}}; + +#[cfg(feature = "arithmetic")] +use crate::{BignP256, elliptic_curve::rand_core::CryptoRngCore, NonZeroScalar, Result}; +use crate::{ALGORITHM_OID, PublicKey, ScalarPrimitive, SecretKey}; +#[cfg(feature = "arithmetic")] +use crate::FieldBytes; + +impl SecretKey { + const MIN_SIZE: usize = 24; + + /// Generate a random [`SecretKey`]. + #[cfg(feature = "arithmetic")] + pub fn random(rng: &mut impl CryptoRngCore) -> Self { + Self { + inner: NonZeroScalar::random(rng).into(), + } + } + + /// Borrow the inner secret [`elliptic_curve::ScalarPrimitive`] value. + /// + /// # ⚠️ Warning + /// + /// This value is key material. + /// + /// Please treat it with the care it deserves! + pub fn as_scalar_primitive(&self) -> &ScalarPrimitive { + &self.inner + } + + /// Get the secret [`elliptic_curve::NonZeroScalar`] value for this key. + /// + /// # ⚠️ Warning + /// + /// This value is key material. + /// + /// Please treat it with the care it deserves! + #[cfg(feature = "arithmetic")] + pub fn to_nonzero_scalar(&self) -> NonZeroScalar { + (*self).into() + } + + /// Get the [`PublicKey`] which corresponds to this secret key + #[cfg(feature = "arithmetic")] + pub fn public_key(&self) -> PublicKey { + PublicKey::from_secret_scalar(&self.to_nonzero_scalar()) + } + + /// Deserialize secret key from an encoded secret scalar. + pub fn from_bytes(bytes: &FieldBytes) -> Result { + let inner: ScalarPrimitive = + Option::from(ScalarPrimitive::from_bytes(bytes)).ok_or(Error)?; + + if inner.is_zero().into() { + return Err(Error); + } + + Ok(Self { inner }) + } + + /// Deserialize secret key from an encoded secret scalar passed as a byte slice. + /// + /// The slice is expected to be a minimum of 24-bytes (192-bytes) and at most + /// `C::FieldBytesSize` bytes in length. + /// + /// Byte slices shorter than the field size are handled by zero padding the input. + /// + /// NOTE: this function is variable-time with respect to the input length. To avoid a timing + /// sidechannel, always ensure that the input has been pre-padded to `C::FieldBytesSize`. + pub fn from_slice(slice: &[u8]) -> Result { + if slice.len() == ::FieldBytesSize::USIZE { + Self::from_bytes(FieldBytes::from_slice(slice)) + } else if (Self::MIN_SIZE..::FieldBytesSize::USIZE) + .contains(&slice.len()) + { + let mut bytes = Zeroizing::new(FieldBytes::default()); + let offset = ::FieldBytesSize::USIZE + .saturating_sub(slice.len()); + bytes[offset..].copy_from_slice(slice); + Self::from_bytes(&bytes) + } else { + Err(Error) + } + } + + /// Serialize raw secret scalar as a big endian integer. + pub fn to_bytes(&self) -> FieldBytes { + self.inner.to_bytes() + } +} + +impl From for NonZeroScalar { + fn from(secret_key: SecretKey) -> NonZeroScalar { + secret_key.to_nonzero_scalar() + } +} + +#[cfg(feature = "arithmetic")] +impl From for SecretKey { + fn from(scalar: NonZeroScalar) -> SecretKey { + SecretKey::from(&scalar) + } +} + +#[cfg(feature = "arithmetic")] +impl From<&NonZeroScalar> for SecretKey { + fn from(scalar: &NonZeroScalar) -> SecretKey { + SecretKey { + inner: scalar.into(), + } + } +} + +impl AssociatedAlgorithmIdentifier for SecretKey { + type Params = ObjectIdentifier; + const ALGORITHM_IDENTIFIER: AlgorithmIdentifier = AlgorithmIdentifier { + oid: ALGORITHM_OID, + parameters: Some(BignP256::OID), + }; +} + +impl TryFrom> for SecretKey { + type Error = pkcs8::Error; + + fn try_from(private_key_info: pkcs8::PrivateKeyInfo<'_>) -> pkcs8::Result { + private_key_info + .algorithm + .assert_oids(ALGORITHM_OID, BignP256::OID)?; + Self::from_slice(private_key_info.private_key).map_err(|_| pkcs8::Error::KeyMalformed) + } +} + +#[cfg(feature = "pem")] +impl FromStr for SecretKey { + type Err = Error; + fn from_str(s: &str) -> std::result::Result { + Self::from_pkcs8_pem(s).map_err(|_| Error) + } +} + +impl EncodePrivateKey for SecretKey { + fn to_pkcs8_der(&self) -> pkcs8::Result { + let algorithm_identifier = pkcs8::AlgorithmIdentifierRef { + oid: ALGORITHM_OID, + parameters: Some((&BignP256::OID).into()), + }; + + let ec_private_key = self.to_bytes(); + let pkcs8_key = pkcs8::PrivateKeyInfo::new(algorithm_identifier, &ec_private_key); + Ok(SecretDocument::encode_msg(&pkcs8_key)?) + } +} diff --git a/bign256/tests/dsa.rs b/bign256/tests/dsa.rs index 4ef5428d..96c88604 100644 --- a/bign256/tests/dsa.rs +++ b/bign256/tests/dsa.rs @@ -1,23 +1,24 @@ //! bign256 DSA Tests -#![cfg(feature = "dsa")] +#![cfg(feature = "ecdsa")] + +use elliptic_curve::ops::Reduce; +use hex_literal::hex; +use proptest::prelude::*; use bign256::{ - dsa::{ + ecdsa::{ signature::{Signer, Verifier}, Signature, SigningKey, VerifyingKey, }, NonZeroScalar, Scalar, U256, }; -use elliptic_curve::ops::Reduce; -use hex_literal::hex; -use proptest::prelude::*; -const PUBLIC_KEY: [u8; 65] = hex!( - "04 - D07F8590A8F77BF84F1EF10C6DE44CF5DDD52B4C9DE4CE3FE0799D1750561ABD - 909AD9B92A4DB89A4A050959DA2E0C1926281B466D68913417C8E86103A6C67A" +const PUBLIC_KEY: [u8; 64] = hex!( + "BD1A5650 179D79E0 3FCEE49D 4C2BD5DD F54CE46D 0CF11E4F F87BF7A8 90857FD0" + "7AC6A603 61E8C817 3491686D 461B2826 190C2EDA 5909054A 9AB84D2A B9D99A90" ); + const MSG: &[u8] = b"testing"; const SIG: [u8; 48] = hex!( "63F59C523FF1780851143114FFBC5C13" @@ -26,7 +27,7 @@ const SIG: [u8; 48] = hex!( #[test] fn verify_test_vector() { - let vk = VerifyingKey::from_sec1_bytes(&PUBLIC_KEY).unwrap(); + let vk = VerifyingKey::from_bytes(&PUBLIC_KEY).unwrap(); let sig = Signature::try_from(&SIG).unwrap(); assert!(vk.verify(MSG, &sig).is_ok()); } diff --git a/bign256/tests/ecdh.rs b/bign256/tests/ecdh.rs new file mode 100644 index 00000000..7dd58fb4 --- /dev/null +++ b/bign256/tests/ecdh.rs @@ -0,0 +1,29 @@ +#![cfg(feature = "ecdh")] +#[test] +fn ecdh() { + use bign256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; + use rand_core::OsRng; // requires 'getrandom' feature + + // Alice + let alice_secret = EphemeralSecret::random(&mut OsRng); + let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); + + // Bob + let bob_secret = EphemeralSecret::random(&mut OsRng); + 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_sec1_bytes(bob_pk_bytes.as_ref()) + .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! + + let alice_shared = alice_secret.diffie_hellman(&bob_public); + + // Bob decodes Alice's serialized public key and computes the same shared secret + let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) + .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! + + let bob_shared = bob_secret.diffie_hellman(&alice_public); + + // Both participants arrive on the same shared secret + assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); +} \ No newline at end of file diff --git a/bign256/tests/examples/pkcs8-private.der b/bign256/tests/examples/pkcs8-private.der new file mode 100644 index 0000000000000000000000000000000000000000..4b293bb76fb9f215d58eb67a226230d85dfd2704 GIT binary patch literal 65 zcmXr8XJTY9kYMA|Dqvt@P)gNhVnnc+8CewM)3)yLF1Ac}HU3~Ur{t4_iH7`Jb|a^G NJeA7vhl(F%0sx3Y5V8OO literal 0 HcmV?d00001 diff --git a/bign256/tests/examples/pkcs8-private.pem b/bign256/tests/examples/pkcs8-private.pem new file mode 100644 index 00000000..e581587f --- /dev/null +++ b/bign256/tests/examples/pkcs8-private.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MD8CAQAwGAYKKnAAAgAiZS0CAQYKKnAAAgAiZS0DAQQgH2a1uEtzOWdFM/AynHTy +GDQoH+0HMkKeDHkjX8Jz4mk= +-----END PRIVATE KEY----- diff --git a/bign256/tests/examples/pkcs8-public.der b/bign256/tests/examples/pkcs8-public.der new file mode 100644 index 0000000000000000000000000000000000000000..f5b0cf251e1d8a7ed25b7547cfe48c50fe98a55f GIT binary patch literal 95 zcmXqrHIQKA(kftJVo*xeWnx6InHiZK88+RRS(5Ww*J6UqdnY%`R|bC<6>&d5xXYep uk74X5N9~msd@J5O_`ZBs-O5zmT}Q2(sxKY-9of=0().unwrap(); + + // Ensure key parses equivalently to DER + let der_key = SecretKey::from_pkcs8_der(&PKCS8_PRIVATE_KEY_DER[..]).unwrap(); + assert_eq!(secret_key.to_bytes(), der_key.to_bytes()); +} + +#[test] +#[cfg(feature = "pem")] +fn decode_pkcs8_public_key_from_pem() { + let public_key = PKCS8_PUBLIC_KEY_PEM.parse::().unwrap(); + + // Ensure key parses equivalently to DER + let der_key = PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); + assert_eq!(public_key, der_key); +} + +#[test] +#[cfg(feature = "pem")] +fn encode_pkcs8_private_key_to_der() { + let original_secret_key = SecretKey::from_pkcs8_der(&PKCS8_PRIVATE_KEY_DER[..]).unwrap(); + let reencoded_secret_key = original_secret_key.to_pkcs8_der(); + assert_eq!(reencoded_secret_key.unwrap().to_bytes().to_vec(), &PKCS8_PRIVATE_KEY_DER[..]); +} + +#[test] +#[cfg(feature = "pem")] +fn encode_pkcs8_public_key_to_der() { + let original_public_key = + PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); + let reencoded_public_key = original_public_key.to_public_key_der().unwrap(); + assert_eq!(reencoded_public_key.as_ref(), &PKCS8_PUBLIC_KEY_DER[..]); +} + +#[test] +#[cfg(feature = "pem")] +fn encode_pkcs8_private_key_to_pem() { + let original_secret_key = SecretKey::from_pkcs8_der(&PKCS8_PRIVATE_KEY_DER[..]).unwrap(); + let reencoded_secret_key = original_secret_key + .to_pkcs8_pem(Default::default()) + .unwrap(); + assert_eq!(reencoded_secret_key.as_str(), PKCS8_PRIVATE_KEY_PEM); +} + +#[test] +#[cfg(feature = "pem")] +fn encode_pkcs8_public_key_to_pem() { + let original_public_key = + PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); + let reencoded_public_key = original_public_key.to_string(); + assert_eq!(reencoded_public_key.as_str(), PKCS8_PUBLIC_KEY_PEM); +} From 3e9f2aa4a013882f158458c559fb000caf269c0e Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 17:16:06 +0300 Subject: [PATCH 2/8] remove patch --- Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0845a36c..126bda12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,3 @@ members = [ [profile.dev] opt-level = 2 - -[patch.crates-io] -#pkcs8 = { path = "/Users/makavity/dev/crypto/formats/pkcs8" } -const-oid = { path = "/Users/makavity/dev/crypto/formats/const-oid"} \ No newline at end of file From 4c56ebd70b11a8ad6ea0d4042cc69ba8d61b7414 Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 20:38:40 +0300 Subject: [PATCH 3/8] add ecdh + fixes --- Cargo.lock | 5 + bign256/Cargo.toml | 10 +- bign256/src/ecdh.rs | 248 ++++++++++++++++++++++++++++----- bign256/src/ecdsa/verifying.rs | 4 +- bign256/src/lib.rs | 12 +- bign256/src/public_key.rs | 43 ++++-- bign256/tests/ecdh.rs | 4 +- bign256/tests/pkcs8.rs | 2 +- 8 files changed, 269 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c045f4d..7bddb719 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,9 +55,12 @@ dependencies = [ "belt-hash", "criterion", "der", + "digest", "elliptic-curve", "hex", "hex-literal", + "hkdf", + "hmac", "pkcs8", "primeorder", "proptest", @@ -221,6 +224,8 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "const-oid" version = "0.10.0-pre.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e3352a27098ba6b09546e5f13b15165e6a88b5c2723afecb3ea9576b27e3ea" [[package]] name = "cpufeatures" diff --git a/bign256/Cargo.toml b/bign256/Cargo.toml index 12076348..d053f311 100644 --- a/bign256/Cargo.toml +++ b/bign256/Cargo.toml @@ -27,7 +27,11 @@ rfc6979 = { version = "=0.5.0-pre.3", optional = true } rand_core = "0.6.4" pkcs8 = { version = "0.11.0-pre.0", optional = true } sec1 = { version = "0.8.0-pre.1", optional = true } -der = { version = "0.8.0-pre.0" } +der = { version = "0.8.0-pre.0" } + +digest = { version = "0.11.0-pre.8", optional = true } +hkdf = { version = "0.13.0-pre.3", optional = true } +hmac = { version = "0.13.0-pre.3", optional = true } [dev-dependencies] criterion = "0.5" @@ -37,7 +41,7 @@ rand_core = { version = "0.6", features = ["getrandom"] } hex = { version = "0.4" } [features] -default = ["arithmetic", "pkcs8", "std", "ecdsa", "pem"] +default = ["arithmetic", "pkcs8", "std", "ecdsa", "pem", "ecdh"] alloc = ["elliptic-curve/alloc", "primeorder?/alloc"] std = ["alloc", "elliptic-curve/std", "signature?/std"] @@ -45,7 +49,7 @@ ecdsa = ["arithmetic", "dep:rfc6979", "dep:signature", "dep:belt-hash"] arithmetic = ["dep:primeorder", "elliptic-curve/arithmetic"] pem = ["pkcs8", "sec1/pem"] pkcs8 = ["dep:pkcs8"] -ecdh = ["arithmetic", "elliptic-curve/ecdh"] +ecdh = ["arithmetic", "elliptic-curve/ecdh", "dep:digest", "dep:hkdf", "dep:hmac", "dep:belt-hash"] [[bench]] name = "field" diff --git a/bign256/src/ecdh.rs b/bign256/src/ecdh.rs index bbe3681d..5579864d 100644 --- a/bign256/src/ecdh.rs +++ b/bign256/src/ecdh.rs @@ -1,47 +1,225 @@ -//! Elliptic Curve Diffie-Hellman (Ephemeral) Support. +//! Elliptic Curve Diffie-Hellman Support. //! -//! This module contains a high-level interface for performing ephemeral -//! Diffie-Hellman key exchanges using the bign256 elliptic curve. +//! # ECDH Ephemeral (ECDHE) Usage //! -//! # Usage +//! Ephemeral Diffie-Hellman provides a one-time key exchange between two peers +//! using a randomly generated set of keys for each exchange. //! -//! This usage example is from the perspective of two participants in the -//! exchange, nicknamed "Alice" and "Bob". +//! In practice ECDHE is used as part of an [Authenticated Key Exchange (AKE)][AKE] +//! protocol (e.g. [SIGMA]), where an existing cryptographic trust relationship +//! can be used to determine the authenticity of the ephemeral keys, such as +//! a digital signature. Without such an additional step, ECDHE is insecure! +//! (see security warning below) //! -//! ``` -//! use bign256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; -//! use rand_core::OsRng; // requires 'getrandom' feature +//! See the documentation for the [`EphemeralSecret`] type for more information +//! on performing ECDH ephemeral key exchanges. //! -//! // Alice -//! let alice_secret = EphemeralSecret::random(&mut OsRng); -//! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); +//! # Static ECDH Usage //! -//! // Bob -//! let bob_secret = EphemeralSecret::random(&mut OsRng); -//! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); +//! Static ECDH key exchanges are supported via the low-level +//! [`diffie_hellman`] function. //! -//! // Alice decodes Bob's serialized public key and computes a shared secret from it -//! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref()) -//! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! -//! -//! let alice_shared = alice_secret.diffie_hellman(&bob_public); -//! -//! // Bob decodes Alice's serialized public key and computes the same shared secret -//! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) -//! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! -//! -//! let bob_shared = bob_secret.diffie_hellman(&alice_public); -//! -//! // Both participants arrive on the same shared secret -//! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); -//! ``` +//! [AKE]: https://en.wikipedia.org/wiki/Authenticated_Key_Exchange +//! [SIGMA]: https://webee.technion.ac.il/~hugo/sigma-pdf.pdf + +// use crate::{ +// point::AffineCoordinates, AffinePoint, Curve, CurveArithmetic, FieldBytes, NonZeroScalar, +// ProjectivePoint, PublicKey, +// }; +// use core::borrow::Borrow; +// use digest::{crypto_common::BlockSizeUser, Digest}; +// use group::Curve as _; +// use hkdf::{hmac::SimpleHmac, Hkdf}; +// use rand_core::CryptoRngCore; +// use zeroize::{Zeroize, ZeroizeOnDrop}; + +use core::borrow::Borrow; +use belt_hash::BeltHash; +use elliptic_curve::point::AffineCoordinates; +use hkdf::Hkdf; +use hmac::SimpleHmac; +use rand_core::CryptoRngCore; +use elliptic_curve::zeroize::{Zeroize, ZeroizeOnDrop}; +use crate::{AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey}; + +/// Low-level Elliptic Curve Diffie-Hellman (ECDH) function. +/// +/// Whenever possible, we recommend using the high-level ECDH ephemeral API +/// provided by [`EphemeralSecret`]. +/// +/// However, if you are implementing a protocol which requires a static scalar +/// value as part of an ECDH exchange, this API can be used to compute a +/// [`SharedSecret`] from that value. +/// +/// Note that this API operates on the low-level [`NonZeroScalar`] and +/// [`AffinePoint`] types. If you are attempting to use the higher-level +/// [`SecretKey`][`crate::SecretKey`] and [`PublicKey`] types, you will +/// need to use the following conversions: +/// +/// ```ignore +/// let shared_secret = elliptic_curve::ecdh::diffie_hellman( +/// secret_key.to_nonzero_scalar(), +/// public_key.as_affine() +/// ); +/// ``` +pub fn diffie_hellman( + secret_key: impl Borrow, + public_key: impl Borrow, +) -> SharedSecret +{ + let public_point = ProjectivePoint::from(*public_key.borrow()); + let secret_point = (public_point * secret_key.borrow().as_ref()).to_affine(); + SharedSecret::new(secret_point) +} + +/// Ephemeral Diffie-Hellman Secret. +/// +/// These are ephemeral "secret key" values which are deliberately designed +/// to avoid being persisted. +/// +/// To perform an ephemeral Diffie-Hellman exchange, do the following: +/// +/// - Have each participant generate an [`EphemeralSecret`] value +/// - Compute the [`PublicKey`] for that value +/// - Have each peer provide their [`PublicKey`] to their counterpart +/// - Use [`EphemeralSecret`] and the other participant's [`PublicKey`] +/// to compute a [`SharedSecret`] value. +/// +/// # ⚠️ SECURITY WARNING ⚠️ +/// +/// Ephemeral Diffie-Hellman exchanges are unauthenticated and without a +/// further authentication step are trivially vulnerable to man-in-the-middle +/// attacks! +/// +/// These exchanges should be performed in the context of a protocol which +/// takes further steps to authenticate the peers in a key exchange. +pub struct EphemeralSecret +{ + scalar: NonZeroScalar, +} + +impl EphemeralSecret +{ + /// Generate a cryptographically random [`EphemeralSecret`]. + pub fn random(rng: &mut impl CryptoRngCore) -> Self { + Self { + scalar: NonZeroScalar::random(rng), + } + } -pub use elliptic_curve::ecdh::diffie_hellman; + /// Get the public key associated with this ephemeral secret. + /// + /// The `compress` flag enables point compression. + pub fn public_key(&self) -> PublicKey { + PublicKey::from_secret_scalar(&self.scalar) + } -use crate::BignP256; + /// Compute a Diffie-Hellman shared secret from an ephemeral secret and the + /// public key of the other participant in the exchange. + pub fn diffie_hellman(&self, public_key: &PublicKey) -> SharedSecret { + diffie_hellman(self.scalar, public_key.as_affine()) + } +} -/// NIST P-256 Ephemeral Diffie-Hellman Secret. -pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; +impl From<&EphemeralSecret> for PublicKey +{ + fn from(ephemeral_secret: &EphemeralSecret) -> Self { + ephemeral_secret.public_key() + } +} + +impl Zeroize for EphemeralSecret +{ + fn zeroize(&mut self) { + self.scalar.zeroize() + } +} + +impl ZeroizeOnDrop for EphemeralSecret {} + +impl Drop for EphemeralSecret +{ + fn drop(&mut self) { + self.zeroize(); + } +} /// Shared secret value computed via ECDH key agreement. -pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; +pub struct SharedSecret { + /// Computed secret value + secret_bytes: FieldBytes, +} + +impl SharedSecret { + /// Create a new [`SharedSecret`] from an [`AffinePoint`] for this curve. + #[inline] + fn new(point: AffinePoint) -> Self + { + Self { + secret_bytes: point.x(), + } + } + + /// Use [HKDF] (HMAC-based Extract-and-Expand Key Derivation Function) to + /// extract entropy from this shared secret. + /// + /// This method can be used to transform the shared secret into uniformly + /// random values which are suitable as key material. + /// + /// The `D` type parameter is a cryptographic digest function. + /// `sha2::Sha256` is a common choice for use with HKDF. + /// + /// The `salt` parameter can be used to supply additional randomness. + /// Some examples include: + /// + /// - randomly generated (but authenticated) string + /// - fixed application-specific value + /// - previous shared secret used for rekeying (as in TLS 1.3 and Noise) + /// + /// After initializing HKDF, use [`Hkdf::expand`] to obtain output key + /// material. + /// + /// [HKDF]: https://en.wikipedia.org/wiki/HKDF + pub fn extract(&self, salt: Option<&[u8]>) -> Hkdf> + { + Hkdf::new(salt, &self.secret_bytes) + } + + /// This value contains the raw serialized x-coordinate of the elliptic curve + /// point computed from a Diffie-Hellman exchange, serialized as bytes. + /// + /// When in doubt, use [`SharedSecret::extract`] instead. + /// + /// # ⚠️ WARNING: NOT UNIFORMLY RANDOM! ⚠️ + /// + /// This value is not uniformly random and should not be used directly + /// as a cryptographic key for anything which requires that property + /// (e.g. symmetric ciphers). + /// + /// Instead, the resulting value should be used as input to a Key Derivation + /// Function (KDF) or cryptographic hash function to produce a symmetric key. + /// The [`SharedSecret::extract`] function will do this for you. + pub fn raw_secret_bytes(&self) -> &FieldBytes { + &self.secret_bytes + } +} + +impl From for SharedSecret { + /// NOTE: this impl is intended to be used by curve implementations to + /// instantiate a [`SharedSecret`] value from their respective + /// [`AffinePoint`] type. + /// + /// Curve implementations should provide the field element representing + /// the affine x-coordinate as `secret_bytes`. + fn from(secret_bytes: FieldBytes) -> Self { + Self { secret_bytes } + } +} + +impl ZeroizeOnDrop for SharedSecret {} + +impl Drop for SharedSecret { + fn drop(&mut self) { + self.secret_bytes.zeroize() + } +} diff --git a/bign256/src/ecdsa/verifying.rs b/bign256/src/ecdsa/verifying.rs index 54438f8f..5bd78176 100644 --- a/bign256/src/ecdsa/verifying.rs +++ b/bign256/src/ecdsa/verifying.rs @@ -84,13 +84,13 @@ impl VerifyingKey { hasher.update(msg); hasher.finalize_fixed() } - + /// Parse a [`VerifyingKey`] from a byte slice. pub fn from_bytes(bytes: &[u8]) -> Result { 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]> { diff --git a/bign256/src/lib.rs b/bign256/src/lib.rs index 036459ff..94926936 100644 --- a/bign256/src/lib.rs +++ b/bign256/src/lib.rs @@ -30,7 +30,9 @@ extern crate alloc; pub use elliptic_curve::{self, bigint::U256}; -use elliptic_curve::{bigint::ArrayEncoding, consts::U32, Error, FieldBytesEncoding}; +use elliptic_curve::{ + bigint::ArrayEncoding, consts::U32, Error, FieldBytesEncoding, +}; #[cfg(feature = "arithmetic")] pub use arithmetic::{AffinePoint, ProjectivePoint, scalar::Scalar}; @@ -44,10 +46,10 @@ pub mod arithmetic; #[cfg(any(feature = "test-vectors", test))] pub mod test_vectors; -#[cfg(feature = "ecdsa")] -pub mod ecdsa; #[cfg(feature = "ecdh")] pub mod ecdh; +#[cfg(feature = "ecdsa")] +pub mod ecdsa; #[cfg(feature = "arithmetic")] pub mod public_key; #[cfg(feature = "arithmetic")] @@ -142,7 +144,8 @@ pub type ScalarPrimitive = elliptic_curve::ScalarPrimitive; /// Elliptic curve BignP256 public key. #[cfg(feature = "arithmetic")] #[derive(Clone, Debug, Eq, PartialEq)] -pub struct PublicKey { +pub struct PublicKey +{ point: elliptic_curve::AffinePoint, } @@ -153,6 +156,7 @@ pub struct SecretKey { inner: ScalarPrimitive, } + /// Bit representation of a BIGN P-256 scalar field element. #[cfg(feature = "bits")] pub type ScalarBits = elliptic_curve::ScalarBits; diff --git a/bign256/src/public_key.rs b/bign256/src/public_key.rs index f0c6eba4..2e567dd4 100644 --- a/bign256/src/public_key.rs +++ b/bign256/src/public_key.rs @@ -5,22 +5,17 @@ use core::str::FromStr; use elliptic_curve::{ AffinePoint, - CurveArithmetic, - Error, - Group, array::Array, - point::NonIdentity, - sec1::{FromEncodedPoint, ToEncodedPoint} + CurveArithmetic, + Error, Group, point::NonIdentity, sec1::{FromEncodedPoint, ToEncodedPoint}, }; use pkcs8::{ AssociatedOid, - DecodePublicKey, - EncodePublicKey, - ObjectIdentifier, - spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier} + DecodePublicKey, EncodePublicKey, ObjectIdentifier, spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier}, }; use crate::{ALGORITHM_OID, BignP256, EncodedPoint, NonZeroScalar, ProjectivePoint, PublicKey}; + impl PublicKey { /// Convert an [`AffinePoint`] into a [`PublicKey`] pub fn from_affine(point: AffinePoint) -> Result { @@ -70,9 +65,22 @@ impl PublicKey { let affine = AffinePoint::::from_encoded_point(&point); if affine.is_none().into() { Err(Error) + } else { + Ok(Self { + point: affine.unwrap(), + }) } - else { - Ok(Self { point: affine.unwrap() }) + } + + /// Get [`PublicKey`] from encoded point + pub fn from_encoded_point(point: EncodedPoint) -> Result { + let affine = AffinePoint::::from_encoded_point(&point); + if affine.is_none().into() { + Err(Error) + } else { + Ok(Self { + point: affine.unwrap(), + }) } } @@ -84,6 +92,12 @@ impl PublicKey { bytes[33..].reverse(); bytes[1..].to_vec().into_boxed_slice() } + + #[cfg(feature = "alloc")] + /// Get encoded point from [`PublicKey`] + pub fn to_encoded_point(&self) -> EncodedPoint { + self.point.to_encoded_point(false) + } } impl AsRef> for PublicKey { @@ -167,6 +181,12 @@ impl EncodePublicKey for PublicKey { } } +impl From for EncodedPoint { + fn from(value: PublicKey) -> Self { + value.point.to_encoded_point(false) + } +} + #[cfg(feature = "pem")] impl FromStr for PublicKey { type Err = Error; @@ -187,4 +207,3 @@ impl Display for PublicKey { ) } } - diff --git a/bign256/tests/ecdh.rs b/bign256/tests/ecdh.rs index 7dd58fb4..08bf0bc1 100644 --- a/bign256/tests/ecdh.rs +++ b/bign256/tests/ecdh.rs @@ -13,13 +13,13 @@ fn ecdh() { 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_sec1_bytes(bob_pk_bytes.as_ref()) + 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 alice_shared = alice_secret.diffie_hellman(&bob_public); // Bob decodes Alice's serialized public key and computes the same shared secret - let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) + 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 bob_shared = bob_secret.diffie_hellman(&alice_public); diff --git a/bign256/tests/pkcs8.rs b/bign256/tests/pkcs8.rs index 8e28db05..785041d9 100644 --- a/bign256/tests/pkcs8.rs +++ b/bign256/tests/pkcs8.rs @@ -3,7 +3,7 @@ use hex_literal::hex; use pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey}; -use bign256::{BignP256, PublicKey, SecretKey}; +use bign256::{PublicKey, SecretKey}; const PKCS8_PRIVATE_KEY_DER: &[u8; 65] = include_bytes!("examples/pkcs8-private.der"); #[cfg(feature = "pem")] From e2cc8a3c9c074873ffa780d9225c58b7b534d006 Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 20:40:25 +0300 Subject: [PATCH 4/8] fix clippy + fmt --- bign256/src/arithmetic/scalar.rs | 2 +- bign256/src/ecdh.rs | 31 ++++++++++++------------------- bign256/src/ecdsa/verifying.rs | 4 +++- bign256/src/lib.rs | 10 +++------- bign256/src/public_key.rs | 16 ++++++++-------- bign256/src/secret_key.rs | 13 ++++++++----- bign256/tests/ecdh.rs | 17 ++++++++++------- bign256/tests/pkcs8.rs | 11 ++++++----- 8 files changed, 51 insertions(+), 53 deletions(-) diff --git a/bign256/src/arithmetic/scalar.rs b/bign256/src/arithmetic/scalar.rs index 2fecc778..340f5169 100644 --- a/bign256/src/arithmetic/scalar.rs +++ b/bign256/src/arithmetic/scalar.rs @@ -15,7 +15,7 @@ mod scalar_impl; use self::scalar_impl::*; -use crate::{BignP256, FieldBytes, FieldBytesEncoding, ORDER_HEX, SecretKey, U256}; +use crate::{BignP256, FieldBytes, FieldBytesEncoding, SecretKey, ORDER_HEX, U256}; use core::{ iter::{Product, Sum}, ops::{AddAssign, MulAssign, Neg, Shr, ShrAssign, SubAssign}, diff --git a/bign256/src/ecdh.rs b/bign256/src/ecdh.rs index 5579864d..34b491e1 100644 --- a/bign256/src/ecdh.rs +++ b/bign256/src/ecdh.rs @@ -33,14 +33,14 @@ // use rand_core::CryptoRngCore; // use zeroize::{Zeroize, ZeroizeOnDrop}; -use core::borrow::Borrow; +use crate::{AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey}; use belt_hash::BeltHash; +use core::borrow::Borrow; use elliptic_curve::point::AffineCoordinates; +use elliptic_curve::zeroize::{Zeroize, ZeroizeOnDrop}; use hkdf::Hkdf; use hmac::SimpleHmac; use rand_core::CryptoRngCore; -use elliptic_curve::zeroize::{Zeroize, ZeroizeOnDrop}; -use crate::{AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey}; /// Low-level Elliptic Curve Diffie-Hellman (ECDH) function. /// @@ -65,9 +65,9 @@ use crate::{AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, PublicKey}; pub fn diffie_hellman( secret_key: impl Borrow, public_key: impl Borrow, -) -> SharedSecret -{ +) -> SharedSecret { let public_point = ProjectivePoint::from(*public_key.borrow()); + #[allow(clippy::arithmetic_side_effects)] let secret_point = (public_point * secret_key.borrow().as_ref()).to_affine(); SharedSecret::new(secret_point) } @@ -93,13 +93,11 @@ pub fn diffie_hellman( /// /// These exchanges should be performed in the context of a protocol which /// takes further steps to authenticate the peers in a key exchange. -pub struct EphemeralSecret -{ +pub struct EphemeralSecret { scalar: NonZeroScalar, } -impl EphemeralSecret -{ +impl EphemeralSecret { /// Generate a cryptographically random [`EphemeralSecret`]. pub fn random(rng: &mut impl CryptoRngCore) -> Self { Self { @@ -121,15 +119,13 @@ impl EphemeralSecret } } -impl From<&EphemeralSecret> for PublicKey -{ +impl From<&EphemeralSecret> for PublicKey { fn from(ephemeral_secret: &EphemeralSecret) -> Self { ephemeral_secret.public_key() } } -impl Zeroize for EphemeralSecret -{ +impl Zeroize for EphemeralSecret { fn zeroize(&mut self) { self.scalar.zeroize() } @@ -137,8 +133,7 @@ impl Zeroize for EphemeralSecret impl ZeroizeOnDrop for EphemeralSecret {} -impl Drop for EphemeralSecret -{ +impl Drop for EphemeralSecret { fn drop(&mut self) { self.zeroize(); } @@ -153,8 +148,7 @@ pub struct SharedSecret { impl SharedSecret { /// Create a new [`SharedSecret`] from an [`AffinePoint`] for this curve. #[inline] - fn new(point: AffinePoint) -> Self - { + fn new(point: AffinePoint) -> Self { Self { secret_bytes: point.x(), } @@ -180,8 +174,7 @@ impl SharedSecret { /// material. /// /// [HKDF]: https://en.wikipedia.org/wiki/HKDF - pub fn extract(&self, salt: Option<&[u8]>) -> Hkdf> - { + pub fn extract(&self, salt: Option<&[u8]>) -> Hkdf> { Hkdf::new(salt, &self.secret_bytes) } diff --git a/bign256/src/ecdsa/verifying.rs b/bign256/src/ecdsa/verifying.rs index 5bd78176..63442f3d 100644 --- a/bign256/src/ecdsa/verifying.rs +++ b/bign256/src/ecdsa/verifying.rs @@ -15,7 +15,9 @@ //! ``` use super::{Signature, BELT_OID}; -use crate::{AffinePoint, BignP256, EncodedPoint, FieldBytes, Hash, ProjectivePoint, PublicKey, Scalar}; +use crate::{ + AffinePoint, BignP256, EncodedPoint, FieldBytes, Hash, ProjectivePoint, PublicKey, Scalar, +}; use belt_hash::{ digest::{Digest, FixedOutput}, BeltHash, diff --git a/bign256/src/lib.rs b/bign256/src/lib.rs index 94926936..a74cfd6f 100644 --- a/bign256/src/lib.rs +++ b/bign256/src/lib.rs @@ -30,12 +30,10 @@ extern crate alloc; pub use elliptic_curve::{self, bigint::U256}; -use elliptic_curve::{ - bigint::ArrayEncoding, consts::U32, Error, FieldBytesEncoding, -}; +use elliptic_curve::{bigint::ArrayEncoding, consts::U32, Error, FieldBytesEncoding}; #[cfg(feature = "arithmetic")] -pub use arithmetic::{AffinePoint, ProjectivePoint, scalar::Scalar}; +pub use arithmetic::{scalar::Scalar, AffinePoint, ProjectivePoint}; /// Bign256 result type pub type Result = core::result::Result; @@ -144,8 +142,7 @@ pub type ScalarPrimitive = elliptic_curve::ScalarPrimitive; /// Elliptic curve BignP256 public key. #[cfg(feature = "arithmetic")] #[derive(Clone, Debug, Eq, PartialEq)] -pub struct PublicKey -{ +pub struct PublicKey { point: elliptic_curve::AffinePoint, } @@ -156,7 +153,6 @@ pub struct SecretKey { inner: ScalarPrimitive, } - /// Bit representation of a BIGN P-256 scalar field element. #[cfg(feature = "bits")] pub type ScalarBits = elliptic_curve::ScalarBits; diff --git a/bign256/src/public_key.rs b/bign256/src/public_key.rs index 2e567dd4..68530c73 100644 --- a/bign256/src/public_key.rs +++ b/bign256/src/public_key.rs @@ -4,17 +4,17 @@ use core::fmt::Display; use core::str::FromStr; use elliptic_curve::{ - AffinePoint, array::Array, - CurveArithmetic, - Error, Group, point::NonIdentity, sec1::{FromEncodedPoint, ToEncodedPoint}, + point::NonIdentity, + sec1::{FromEncodedPoint, ToEncodedPoint}, + AffinePoint, CurveArithmetic, Error, Group, }; use pkcs8::{ - AssociatedOid, - DecodePublicKey, EncodePublicKey, ObjectIdentifier, spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier}, + spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier}, + AssociatedOid, DecodePublicKey, EncodePublicKey, ObjectIdentifier, }; -use crate::{ALGORITHM_OID, BignP256, EncodedPoint, NonZeroScalar, ProjectivePoint, PublicKey}; +use crate::{BignP256, EncodedPoint, NonZeroScalar, ProjectivePoint, PublicKey, ALGORITHM_OID}; impl PublicKey { /// Convert an [`AffinePoint`] into a [`PublicKey`] @@ -71,7 +71,7 @@ impl PublicKey { }) } } - + /// Get [`PublicKey`] from encoded point pub fn from_encoded_point(point: EncodedPoint) -> Result { let affine = AffinePoint::::from_encoded_point(&point); @@ -92,7 +92,7 @@ impl PublicKey { bytes[33..].reverse(); bytes[1..].to_vec().into_boxed_slice() } - + #[cfg(feature = "alloc")] /// Get encoded point from [`PublicKey`] pub fn to_encoded_point(&self) -> EncodedPoint { diff --git a/bign256/src/secret_key.rs b/bign256/src/secret_key.rs index 9390d1f6..f4e70a1a 100644 --- a/bign256/src/secret_key.rs +++ b/bign256/src/secret_key.rs @@ -3,14 +3,17 @@ use core::str::FromStr; use der::SecretDocument; -use elliptic_curve::{array::typenum::Unsigned, Error, zeroize::Zeroizing}; -use pkcs8::{AssociatedOid, DecodePrivateKey, EncodePrivateKey, ObjectIdentifier, spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier}}; +use elliptic_curve::{array::typenum::Unsigned, zeroize::Zeroizing, Error}; +use pkcs8::{ + spki::{AlgorithmIdentifier, AssociatedAlgorithmIdentifier}, + AssociatedOid, DecodePrivateKey, EncodePrivateKey, ObjectIdentifier, +}; -#[cfg(feature = "arithmetic")] -use crate::{BignP256, elliptic_curve::rand_core::CryptoRngCore, NonZeroScalar, Result}; -use crate::{ALGORITHM_OID, PublicKey, ScalarPrimitive, SecretKey}; #[cfg(feature = "arithmetic")] use crate::FieldBytes; +#[cfg(feature = "arithmetic")] +use crate::{elliptic_curve::rand_core::CryptoRngCore, BignP256, NonZeroScalar, Result}; +use crate::{PublicKey, ScalarPrimitive, SecretKey, ALGORITHM_OID}; impl SecretKey { const MIN_SIZE: usize = 24; diff --git a/bign256/tests/ecdh.rs b/bign256/tests/ecdh.rs index 08bf0bc1..7b070d8f 100644 --- a/bign256/tests/ecdh.rs +++ b/bign256/tests/ecdh.rs @@ -1,7 +1,7 @@ #![cfg(feature = "ecdh")] #[test] fn ecdh() { - use bign256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; + use bign256::{ecdh::EphemeralSecret, EncodedPoint, PublicKey}; use rand_core::OsRng; // requires 'getrandom' feature // Alice @@ -13,17 +13,20 @@ fn ecdh() { 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).expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! let alice_shared = alice_secret.diffie_hellman(&bob_public); // 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).expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! let bob_shared = bob_secret.diffie_hellman(&alice_public); // Both participants arrive on the same shared secret - assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); -} \ No newline at end of file + assert_eq!( + alice_shared.raw_secret_bytes(), + bob_shared.raw_secret_bytes() + ); +} diff --git a/bign256/tests/pkcs8.rs b/bign256/tests/pkcs8.rs index 785041d9..7d434a6f 100644 --- a/bign256/tests/pkcs8.rs +++ b/bign256/tests/pkcs8.rs @@ -54,14 +54,16 @@ fn decode_pkcs8_public_key_from_pem() { fn encode_pkcs8_private_key_to_der() { let original_secret_key = SecretKey::from_pkcs8_der(&PKCS8_PRIVATE_KEY_DER[..]).unwrap(); let reencoded_secret_key = original_secret_key.to_pkcs8_der(); - assert_eq!(reencoded_secret_key.unwrap().to_bytes().to_vec(), &PKCS8_PRIVATE_KEY_DER[..]); + assert_eq!( + reencoded_secret_key.unwrap().to_bytes().to_vec(), + &PKCS8_PRIVATE_KEY_DER[..] + ); } #[test] #[cfg(feature = "pem")] fn encode_pkcs8_public_key_to_der() { - let original_public_key = - PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); + let original_public_key = PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); let reencoded_public_key = original_public_key.to_public_key_der().unwrap(); assert_eq!(reencoded_public_key.as_ref(), &PKCS8_PUBLIC_KEY_DER[..]); } @@ -79,8 +81,7 @@ fn encode_pkcs8_private_key_to_pem() { #[test] #[cfg(feature = "pem")] fn encode_pkcs8_public_key_to_pem() { - let original_public_key = - PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); + let original_public_key = PublicKey::from_public_key_der(&PKCS8_PUBLIC_KEY_DER[..]).unwrap(); let reencoded_public_key = original_public_key.to_string(); assert_eq!(reencoded_public_key.as_str(), PKCS8_PUBLIC_KEY_PEM); } From 518c1026ff26f6fb2627a0ef639207b088512911 Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 20:53:11 +0300 Subject: [PATCH 5/8] fix no_std --- bign256/src/ecdsa/verifying.rs | 3 +++ bign256/src/lib.rs | 5 ++--- bign256/src/public_key.rs | 7 ++++--- bign256/src/secret_key.rs | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/bign256/src/ecdsa/verifying.rs b/bign256/src/ecdsa/verifying.rs index 63442f3d..51cab335 100644 --- a/bign256/src/ecdsa/verifying.rs +++ b/bign256/src/ecdsa/verifying.rs @@ -14,6 +14,9 @@ //! 9. Return YES. //! ``` +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + use super::{Signature, BELT_OID}; use crate::{ AffinePoint, BignP256, EncodedPoint, FieldBytes, Hash, ProjectivePoint, PublicKey, Scalar, diff --git a/bign256/src/lib.rs b/bign256/src/lib.rs index a74cfd6f..99ba984e 100644 --- a/bign256/src/lib.rs +++ b/bign256/src/lib.rs @@ -1,5 +1,4 @@ -// #![no_std] -// #![no_std] +#![no_std] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc = include_str!("../README.md")] #![doc( @@ -58,7 +57,7 @@ const ALGORITHM_OID: pkcs8::ObjectIdentifier = pkcs8::ObjectIdentifier::new_unwrap("1.2.112.0.2.0.34.101.45.2.1"); #[cfg(feature = "ecdsa")] -type Hash = belt_hash::digest::Output; +type Hash = digest::Output; /// Order of BIGN P-256's elliptic curve group (i.e. scalar modulus) in hexadecimal. const ORDER_HEX: &str = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD95C8ED60DFB4DFC7E5ABF99263D6607"; diff --git a/bign256/src/public_key.rs b/bign256/src/public_key.rs index 68530c73..c2209293 100644 --- a/bign256/src/public_key.rs +++ b/bign256/src/public_key.rs @@ -1,7 +1,8 @@ //! Public key types and traits -use core::fmt::Display; -use core::str::FromStr; +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, fmt}; +use core::{fmt::Display, str::FromStr}; use elliptic_curve::{ array::Array, @@ -198,7 +199,7 @@ impl FromStr for PublicKey { #[cfg(feature = "pem")] impl Display for PublicKey { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "{}", diff --git a/bign256/src/secret_key.rs b/bign256/src/secret_key.rs index f4e70a1a..00d111b9 100644 --- a/bign256/src/secret_key.rs +++ b/bign256/src/secret_key.rs @@ -142,7 +142,7 @@ impl TryFrom> for SecretKey { #[cfg(feature = "pem")] impl FromStr for SecretKey { type Err = Error; - fn from_str(s: &str) -> std::result::Result { + fn from_str(s: &str) -> core::result::Result { Self::from_pkcs8_pem(s).map_err(|_| Error) } } From 2c6b8716217b6c0a426e2ea5180e7b77e96479e4 Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 21:03:12 +0300 Subject: [PATCH 6/8] maybe fix alloc --- bign256/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bign256/Cargo.toml b/bign256/Cargo.toml index d053f311..ad789ecd 100644 --- a/bign256/Cargo.toml +++ b/bign256/Cargo.toml @@ -49,7 +49,7 @@ ecdsa = ["arithmetic", "dep:rfc6979", "dep:signature", "dep:belt-hash"] arithmetic = ["dep:primeorder", "elliptic-curve/arithmetic"] pem = ["pkcs8", "sec1/pem"] pkcs8 = ["dep:pkcs8"] -ecdh = ["arithmetic", "elliptic-curve/ecdh", "dep:digest", "dep:hkdf", "dep:hmac", "dep:belt-hash"] +ecdh = ["arithmetic", "elliptic-curve/ecdh", "dep:digest", "dep:hkdf", "dep:hmac", "dep:belt-hash", "alloc"] [[bench]] name = "field" From 75a9c114112196010c5545f98e1ec3e7ac8c786b Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 21:11:32 +0300 Subject: [PATCH 7/8] fix tests for no_std platforms --- bign256/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bign256/src/lib.rs b/bign256/src/lib.rs index 99ba984e..f449270b 100644 --- a/bign256/src/lib.rs +++ b/bign256/src/lib.rs @@ -26,6 +26,7 @@ )] #[cfg(feature = "alloc")] +#[allow(unused_extern_crates)] extern crate alloc; pub use elliptic_curve::{self, bigint::U256}; From f50ac39d4746e860beef6c63d5ed150ec5f8ea5e Mon Sep 17 00:00:00 2001 From: Alexandr Kitaev Date: Fri, 10 May 2024 21:17:42 +0300 Subject: [PATCH 8/8] fix dead code linter --- bign256/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/bign256/src/lib.rs b/bign256/src/lib.rs index f449270b..135b9f6b 100644 --- a/bign256/src/lib.rs +++ b/bign256/src/lib.rs @@ -54,6 +54,7 @@ pub mod public_key; pub mod secret_key; #[cfg(feature = "pkcs8")] +#[allow(dead_code)] const ALGORITHM_OID: pkcs8::ObjectIdentifier = pkcs8::ObjectIdentifier::new_unwrap("1.2.112.0.2.0.34.101.45.2.1");