├── .gitignore ├── bignp256 ├── .gitignore ├── src │ ├── test_vectors.rs │ ├── arithmetic.rs │ ├── ecdh.rs │ └── arithmetic │ │ └── field.rs ├── tests │ ├── examples │ │ ├── pkcs8-public.der │ │ ├── pkcs8-private.der │ │ ├── pkcs8-private.pem │ │ └── pkcs8-public.pem │ ├── scalar.rs │ ├── projective.rs │ └── dsa.rs ├── LICENSE-MIT ├── CHANGELOG.md ├── benches │ ├── field.rs │ └── scalar.rs └── Cargo.toml ├── clippy.toml ├── ed448-goldilocks ├── src │ ├── curve │ │ ├── scalar_mul │ │ │ ├── window.rs │ │ │ ├── double_base.rs │ │ │ ├── double_and_add.rs │ │ │ └── window │ │ │ │ └── wnaf.rs │ │ ├── scalar_mul.rs │ │ └── twedwards.rs │ ├── curve.rs │ ├── sign │ │ ├── context.rs │ │ └── error.rs │ ├── edwards.rs │ └── field.rs ├── LICENSE-MIT └── Cargo.toml ├── codecov.yml ├── .cargo └── audit.toml ├── p192 ├── src │ ├── test_vectors.rs │ ├── arithmetic.rs │ ├── ecdsa.rs │ └── arithmetic │ │ └── field.rs ├── tests │ └── projective.rs ├── LICENSE-MIT ├── CHANGELOG.md └── Cargo.toml ├── p224 ├── src │ ├── test_vectors.rs │ ├── test_vectors │ │ └── data │ │ │ └── wycheproof.blb │ ├── ecdh.rs │ ├── arithmetic.rs │ └── arithmetic │ │ └── field.rs ├── tests │ └── projective.rs ├── LICENSE-MIT ├── Cargo.toml └── CHANGELOG.md ├── p384 ├── src │ ├── test_vectors.rs │ ├── test_vectors │ │ └── data │ │ │ └── wycheproof.blb │ ├── ecdh.rs │ ├── arithmetic │ │ └── field.rs │ └── arithmetic.rs ├── tests │ ├── projective.rs │ └── affine.rs ├── LICENSE-MIT └── benches │ ├── field.rs │ └── scalar.rs ├── p521 ├── src │ ├── test_vectors.rs │ ├── test_vectors │ │ └── data │ │ │ └── wycheproof.blb │ ├── arithmetic │ │ ├── util.rs │ │ └── field │ │ │ └── loose.rs │ └── ecdh.rs ├── tests │ └── projective.rs ├── LICENSE-MIT ├── benches │ ├── field.rs │ └── scalar.rs ├── CHANGELOG.md └── Cargo.toml ├── k256 ├── src │ ├── test_vectors.rs │ ├── test_vectors │ │ ├── data │ │ │ ├── wycheproof.blb │ │ │ └── wycheproof-p1316.blb │ │ └── ecdsa.rs │ ├── arithmetic │ │ └── dev.rs │ ├── arithmetic.rs │ └── ecdh.rs ├── proptest-regressions │ └── arithmetic │ │ └── scalar.txt ├── LICENSE-MIT └── benches │ └── ecdsa.rs ├── p256 ├── src │ ├── test_vectors.rs │ ├── test_vectors │ │ └── data │ │ │ └── wycheproof.blb │ ├── ecdh.rs │ └── arithmetic.rs ├── tests │ ├── examples │ │ ├── pkcs8-public-key.der │ │ ├── pkcs8-private-key.der │ │ ├── pkcs8-public-key.pem │ │ └── pkcs8-private-key.pem │ ├── scalar.rs │ └── ecdsa.rs ├── LICENSE-MIT └── benches │ ├── field.rs │ └── scalar.rs ├── sm2 ├── tests │ └── examples │ │ ├── pkcs8-private-key.der │ │ ├── pkcs8-public-key.der │ │ ├── pkcs8-public-key.pem │ │ └── pkcs8-private-key.pem ├── LICENSE-MIT ├── src │ ├── distid.rs │ ├── arithmetic │ │ └── field.rs │ └── arithmetic.rs ├── CHANGELOG.md └── Cargo.toml ├── bp256 ├── src │ ├── arithmetic.rs │ ├── r1 │ │ ├── ecdsa.rs │ │ └── arithmetic.rs │ ├── t1 │ │ ├── ecdsa.rs │ │ └── arithmetic.rs │ ├── lib.rs │ ├── t1.rs │ ├── r1.rs │ └── arithmetic │ │ └── field.rs ├── LICENSE-MIT ├── Cargo.toml └── README.md ├── bp384 ├── src │ ├── arithmetic.rs │ ├── r1 │ │ ├── ecdsa.rs │ │ └── arithmetic.rs │ ├── t1 │ │ ├── ecdsa.rs │ │ └── arithmetic.rs │ ├── lib.rs │ ├── t1.rs │ ├── r1.rs │ └── arithmetic │ │ └── field.rs ├── LICENSE-MIT ├── Cargo.toml └── README.md ├── .github ├── dependabot.yml └── workflows │ ├── security-audit.yml │ ├── hash2curve.yml │ ├── primefield.yml │ ├── workspace.yml │ ├── primeorder.yml │ ├── bp256.yml │ ├── bp384.yml │ ├── sm2.yml │ └── p521.yml ├── .typos.toml ├── hash2curve ├── CHANGELOG.md ├── src │ ├── oprf.rs │ ├── lib.rs │ ├── map2curve.rs │ └── hash2field.rs ├── Cargo.toml ├── LICENSE-MIT └── README.md ├── primefield ├── CHANGELOG.md ├── src │ ├── error.rs │ └── lib.rs ├── Cargo.toml └── LICENSE-MIT ├── Cargo.toml ├── SECURITY.md ├── primeorder ├── LICENSE-MIT ├── Cargo.toml └── src │ └── lib.rs └── x448 ├── LICENSE-MIT ├── Cargo.toml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.sw* 3 | -------------------------------------------------------------------------------- /bignp256/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | allow-unwrap-in-tests = true 2 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve/scalar_mul/window.rs: -------------------------------------------------------------------------------- 1 | pub mod wnaf; 2 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | patch: off 4 | project: off 5 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod scalar_mul; 2 | pub(crate) mod twedwards; 3 | -------------------------------------------------------------------------------- /.cargo/audit.toml: -------------------------------------------------------------------------------- 1 | [advisories] 2 | ignore = [ 3 | "RUSTSEC-2021-0127", # serde_cbor is unmaintained 4 | ] 5 | -------------------------------------------------------------------------------- /p192/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp192r1 test vectors. 2 | 3 | #[cfg(test)] 4 | pub mod ecdsa; 5 | pub mod group; 6 | -------------------------------------------------------------------------------- /p224/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp224r1 test vectors. 2 | 3 | #[cfg(test)] 4 | pub mod ecdsa; 5 | pub mod group; 6 | -------------------------------------------------------------------------------- /p384/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp384r1 test vectors. 2 | 3 | #[cfg(test)] 4 | pub mod ecdsa; 5 | pub mod group; 6 | -------------------------------------------------------------------------------- /p521/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp521r1 test vectors. 2 | 3 | #[cfg(test)] 4 | pub mod ecdsa; 5 | pub mod group; 6 | -------------------------------------------------------------------------------- /bignp256/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp256r1 test vectors. 2 | 3 | #[cfg(test)] 4 | pub mod field; 5 | pub mod group; 6 | -------------------------------------------------------------------------------- /k256/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp256k1 test vectors 2 | 3 | #[cfg(test)] 4 | pub mod ecdsa; 5 | pub mod field; 6 | pub mod group; 7 | -------------------------------------------------------------------------------- /p256/src/test_vectors.rs: -------------------------------------------------------------------------------- 1 | //! secp256r1 test vectors. 2 | 3 | #[cfg(test)] 4 | pub mod ecdsa; 5 | pub mod field; 6 | pub mod group; 7 | -------------------------------------------------------------------------------- /bignp256/tests/examples/pkcs8-public.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/bignp256/tests/examples/pkcs8-public.der -------------------------------------------------------------------------------- /p256/tests/examples/pkcs8-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/p256/tests/examples/pkcs8-public-key.der -------------------------------------------------------------------------------- /sm2/tests/examples/pkcs8-private-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/sm2/tests/examples/pkcs8-private-key.der -------------------------------------------------------------------------------- /sm2/tests/examples/pkcs8-public-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/sm2/tests/examples/pkcs8-public-key.der -------------------------------------------------------------------------------- /bignp256/tests/examples/pkcs8-private.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/bignp256/tests/examples/pkcs8-private.der -------------------------------------------------------------------------------- /bp256/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic for the brainpoolP256 elliptic curve. 2 | 3 | pub(crate) mod field; 4 | pub(crate) mod scalar; 5 | -------------------------------------------------------------------------------- /bp384/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic for the brainpoolP384 elliptic curve. 2 | 3 | pub(crate) mod field; 4 | pub(crate) mod scalar; 5 | -------------------------------------------------------------------------------- /k256/src/test_vectors/data/wycheproof.blb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/k256/src/test_vectors/data/wycheproof.blb -------------------------------------------------------------------------------- /p224/src/test_vectors/data/wycheproof.blb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/p224/src/test_vectors/data/wycheproof.blb -------------------------------------------------------------------------------- /p256/src/test_vectors/data/wycheproof.blb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/p256/src/test_vectors/data/wycheproof.blb -------------------------------------------------------------------------------- /p256/tests/examples/pkcs8-private-key.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/p256/tests/examples/pkcs8-private-key.der -------------------------------------------------------------------------------- /p384/src/test_vectors/data/wycheproof.blb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/p384/src/test_vectors/data/wycheproof.blb -------------------------------------------------------------------------------- /p521/src/test_vectors/data/wycheproof.blb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/p521/src/test_vectors/data/wycheproof.blb -------------------------------------------------------------------------------- /k256/src/test_vectors/data/wycheproof-p1316.blb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustCrypto/elliptic-curves/HEAD/k256/src/test_vectors/data/wycheproof-p1316.blb -------------------------------------------------------------------------------- /bignp256/tests/examples/pkcs8-private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MD8CAQAwGAYKKnAAAgAiZS0CAQYKKnAAAgAiZS0DAQQgH2a1uEtzOWdFM/AynHTy 3 | GDQoH+0HMkKeDHkjX8Jz4mk= 4 | -----END PRIVATE KEY----- 5 | -------------------------------------------------------------------------------- /sm2/tests/examples/pkcs8-public-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAECNd64EwBzEwRBDYN2K9rb33zNCg9 3 | fBpq/VZSQHuHvuUBTipXw2wVDRYyTcZk4x5kMjWWCcTnmEelsWHIxzZMig== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /bignp256/tests/examples/pkcs8-public.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MF0wGAYKKnAAAgAiZS0CAQYKKnAAAgAiZS0DAQNBALLYmXRs6y04kBzvQkY56jD9 3 | onIL58G6PwS8MV3yQSupOA6o7OD3p7p+qWUtusU7gnvSwvtZhIaY3i6mdZYF65Y= 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /p256/tests/examples/pkcs8-public-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHKz/tV8vLO/YnYnrN0smgRUkUoAt 3 | 7qCZFgaBN9g5z3/EgaREkjBNfvZqwRe+/oOo0I8VXytS+fYY3URwKQSODw== 4 | -----END PUBLIC KEY----- 5 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve/scalar_mul.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod double_and_add; 2 | // pub(crate) mod double_base; 3 | pub(crate) mod variable_base; 4 | pub(crate) mod window; 5 | 6 | pub(crate) use double_and_add::double_and_add; 7 | pub(crate) use variable_base::variable_base; 8 | -------------------------------------------------------------------------------- /p256/tests/examples/pkcs8-private-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaWJBcVYaYzQN4OfY 3 | afKgVJJVjhoEhotqn4VKhmeIGI2hRANCAAQcrP+1Xy8s79idies3SyaBFSRSgC3u 4 | oJkWBoE32DnPf8SBpESSME1+9mrBF77+g6jQjxVfK1L59hjdRHApBI4P 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /sm2/tests/examples/pkcs8-private-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgS7jfUFciKZWSy+1C 3 | g7NUoT/10/7rOgZgxb3zyHxVlJmhRANCAAQI13rgTAHMTBEENg3Yr2tvffM0KD18 4 | Gmr9VlJAe4e+5QFOKlfDbBUNFjJNxmTjHmQyNZYJxOeYR6WxYcjHNkyK 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: github-actions 9 | directory: "/" 10 | schedule: 11 | interval: weekly 12 | open-pull-requests-limit: 10 13 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = [ 3 | ".git/", 4 | "bignp256/tests/pkcs8.rs", 5 | "p224/src/arithmetic.rs", 6 | "p384/src/arithmetic.rs", 7 | "p384/tests/affine.rs", 8 | ] 9 | 10 | [default.extend-words] 11 | # Authenticated Key Exchange 12 | "AKE" = "AKE" 13 | # Claus P. Schnorr 14 | "Claus" = "Claus" 15 | -------------------------------------------------------------------------------- /hash2curve/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.2.0 (UNRELEASED) 8 | - Initial release 9 | 10 | -------------------------------------------------------------------------------- /primefield/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.14.0 (UNRELEASED) 8 | - Initial release 9 | 10 | -------------------------------------------------------------------------------- /primefield/src/error.rs: -------------------------------------------------------------------------------- 1 | //! Error types. 2 | 3 | use core::fmt; 4 | 5 | /// Error type. 6 | pub struct Error; 7 | 8 | impl fmt::Display for Error { 9 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 10 | write!(f, "field error") 11 | } 12 | } 13 | 14 | /// Result type. 15 | pub type Result = core::result::Result; 16 | -------------------------------------------------------------------------------- /k256/proptest-regressions/arithmetic/scalar.txt: -------------------------------------------------------------------------------- 1 | # Seeds for failure cases proptest has generated in the past. It is 2 | # automatically read and these particular cases re-run before any 3 | # novel cases are generated. 4 | # 5 | # It is recommended to check this file in to source control so that 6 | # everyone who runs the test benefits from these saved cases. 7 | cc 6511feae44fafd76e794999ecd3410c4a507306bbea8776dc08bb6f44160332a # shrinks to a = Scalar(Uint(0x0000000000000000000000000000000000000008000000000000000000000000)), b = 256 8 | -------------------------------------------------------------------------------- /p384/tests/projective.rs: -------------------------------------------------------------------------------- 1 | //! Projective arithmetic tests. 2 | 3 | #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] 4 | 5 | use elliptic_curve::{ 6 | PrimeField, 7 | sec1::{self, ToEncodedPoint}, 8 | }; 9 | use p384::{ 10 | AffinePoint, ProjectivePoint, Scalar, 11 | test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS}, 12 | }; 13 | use primeorder::{Double, test_projective_arithmetic}; 14 | 15 | test_projective_arithmetic!( 16 | AffinePoint, 17 | ProjectivePoint, 18 | Scalar, 19 | ADD_TEST_VECTORS, 20 | MUL_TEST_VECTORS 21 | ); 22 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "bignp256", 5 | "bp256", 6 | "bp384", 7 | "ed448-goldilocks", 8 | "hash2curve", 9 | "k256", 10 | "p192", 11 | "p224", 12 | "p256", 13 | "p384", 14 | "p521", 15 | "primefield", 16 | "primeorder", 17 | "sm2", 18 | "x448" 19 | ] 20 | 21 | [profile.dev] 22 | opt-level = 2 23 | 24 | [patch.crates-io] 25 | ed448-goldilocks = { path = "ed448-goldilocks" } 26 | hash2curve = { path = "hash2curve" } 27 | primefield = { path = "primefield" } 28 | primeorder = { path = "primeorder" } 29 | -------------------------------------------------------------------------------- /p192/tests/projective.rs: -------------------------------------------------------------------------------- 1 | //! Projective arithmetic tests. 2 | 3 | #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] 4 | 5 | use elliptic_curve::{ 6 | group::ff::PrimeField, 7 | sec1::{self, ToEncodedPoint}, 8 | }; 9 | use p192::{ 10 | AffinePoint, ProjectivePoint, Scalar, 11 | test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS}, 12 | }; 13 | use primeorder::{Double, test_projective_arithmetic}; 14 | 15 | test_projective_arithmetic!( 16 | AffinePoint, 17 | ProjectivePoint, 18 | Scalar, 19 | ADD_TEST_VECTORS, 20 | MUL_TEST_VECTORS 21 | ); 22 | -------------------------------------------------------------------------------- /p224/tests/projective.rs: -------------------------------------------------------------------------------- 1 | //! Projective arithmetic tests. 2 | 3 | #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] 4 | 5 | use elliptic_curve::{ 6 | group::ff::PrimeField, 7 | sec1::{self, ToEncodedPoint}, 8 | }; 9 | use p224::{ 10 | AffinePoint, ProjectivePoint, Scalar, 11 | test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS}, 12 | }; 13 | use primeorder::{Double, test_projective_arithmetic}; 14 | 15 | test_projective_arithmetic!( 16 | AffinePoint, 17 | ProjectivePoint, 18 | Scalar, 19 | ADD_TEST_VECTORS, 20 | MUL_TEST_VECTORS 21 | ); 22 | -------------------------------------------------------------------------------- /p521/tests/projective.rs: -------------------------------------------------------------------------------- 1 | //! Projective arithmetic tests. 2 | 3 | #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] 4 | 5 | use elliptic_curve::{ 6 | group::ff::PrimeField, 7 | sec1::{self, ToEncodedPoint}, 8 | }; 9 | use p521::{ 10 | AffinePoint, ProjectivePoint, Scalar, 11 | test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS}, 12 | }; 13 | use primeorder::{Double, test_projective_arithmetic}; 14 | 15 | test_projective_arithmetic!( 16 | AffinePoint, 17 | ProjectivePoint, 18 | Scalar, 19 | ADD_TEST_VECTORS, 20 | MUL_TEST_VECTORS 21 | ); 22 | -------------------------------------------------------------------------------- /bp256/src/r1/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Digital Signature Algorithm (ECDSA) 2 | 3 | pub use super::BrainpoolP256r1; 4 | 5 | /// ECDSA/brainpoolP256r1 signature (fixed-size) 6 | pub type Signature = ecdsa::Signature; 7 | 8 | /// ECDSA/brainpoolP256r1 signature (ASN.1 DER encoded) 9 | pub type DerSignature = ecdsa::der::Signature; 10 | 11 | impl ecdsa::EcdsaCurve for BrainpoolP256r1 { 12 | const NORMALIZE_S: bool = false; 13 | } 14 | 15 | #[cfg(feature = "sha256")] 16 | impl ecdsa::hazmat::DigestAlgorithm for BrainpoolP256r1 { 17 | type Digest = sha2::Sha256; 18 | } 19 | -------------------------------------------------------------------------------- /bp256/src/t1/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Digital Signature Algorithm (ECDSA) 2 | 3 | pub use super::BrainpoolP256t1; 4 | 5 | /// ECDSA/brainpoolP256t1 signature (fixed-size) 6 | pub type Signature = ecdsa::Signature; 7 | 8 | /// ECDSA/brainpoolP256t1 signature (ASN.1 DER encoded) 9 | pub type DerSignature = ecdsa::der::Signature; 10 | 11 | impl ecdsa::EcdsaCurve for BrainpoolP256t1 { 12 | const NORMALIZE_S: bool = false; 13 | } 14 | 15 | #[cfg(feature = "sha256")] 16 | impl ecdsa::hazmat::DigestAlgorithm for BrainpoolP256t1 { 17 | type Digest = sha2::Sha256; 18 | } 19 | -------------------------------------------------------------------------------- /bp384/src/r1/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Digital Signature Algorithm (ECDSA) 2 | 3 | pub use super::BrainpoolP384r1; 4 | 5 | /// ECDSA/brainpoolP384r1 signature (fixed-size) 6 | pub type Signature = ecdsa::Signature; 7 | 8 | /// ECDSA/brainpoolP384r1 signature (ASN.1 DER encoded) 9 | pub type DerSignature = ecdsa::der::Signature; 10 | 11 | impl ecdsa::EcdsaCurve for BrainpoolP384r1 { 12 | const NORMALIZE_S: bool = false; 13 | } 14 | 15 | #[cfg(feature = "sha384")] 16 | impl ecdsa::hazmat::DigestAlgorithm for BrainpoolP384r1 { 17 | type Digest = sha2::Sha384; 18 | } 19 | -------------------------------------------------------------------------------- /bp384/src/t1/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Digital Signature Algorithm (ECDSA) 2 | 3 | pub use super::BrainpoolP384t1; 4 | 5 | /// ECDSA/brainpoolP384t1 signature (fixed-size) 6 | pub type Signature = ecdsa::Signature; 7 | 8 | /// ECDSA/brainpoolP384t1 signature (ASN.1 DER encoded) 9 | pub type DerSignature = ecdsa::der::Signature; 10 | 11 | impl ecdsa::EcdsaCurve for BrainpoolP384t1 { 12 | const NORMALIZE_S: bool = false; 13 | } 14 | 15 | #[cfg(feature = "sha384")] 16 | impl ecdsa::hazmat::DigestAlgorithm for BrainpoolP384t1 { 17 | type Digest = sha2::Sha384; 18 | } 19 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve/scalar_mul/double_base.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_snake_case)] 2 | 3 | use super::double_and_add; 4 | use crate::curve::twedwards::extended::ExtendedPoint; 5 | use crate::field::Scalar; 6 | /// XXX: Really in-efficient way to do double base scala mul 7 | /// Replace it with endomorphism from pornin or use naf form 8 | /// Computes aA + bB where B is the TwistedEdwards basepoint 9 | pub(crate) fn double_base_scalar_mul(a: &Scalar, A: &ExtendedPoint, b: &Scalar) -> ExtendedPoint { 10 | let part_a = double_and_add(A, a); 11 | let part_b = double_and_add(&ExtendedPoint::GENERATOR, b); 12 | part_a.add(&part_b) 13 | } 14 | -------------------------------------------------------------------------------- /p256/tests/scalar.rs: -------------------------------------------------------------------------------- 1 | //! Scalar arithmetic tests. 2 | 3 | #![cfg(feature = "arithmetic")] 4 | 5 | use elliptic_curve::ops::{Invert, Reduce}; 6 | use p256::{FieldBytes, Scalar}; 7 | use proptest::prelude::*; 8 | 9 | prop_compose! { 10 | fn scalar()(bytes in any::<[u8; 32]>()) -> Scalar { 11 | >::reduce(&bytes.into()) 12 | } 13 | } 14 | 15 | proptest! { 16 | #[test] 17 | fn invert_and_invert_vartime_are_equivalent(w in scalar()) { 18 | let inv: Option = w.invert().into(); 19 | let inv_vartime: Option = w.invert_vartime().into(); 20 | prop_assert_eq!(inv, inv_vartime); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bignp256/tests/scalar.rs: -------------------------------------------------------------------------------- 1 | //! Scalar arithmetic tests. 2 | 3 | #![cfg(feature = "arithmetic")] 4 | 5 | use bignp256::{FieldBytes, Scalar}; 6 | use elliptic_curve::ops::{Invert, Reduce}; 7 | use proptest::prelude::*; 8 | 9 | prop_compose! { 10 | fn scalar()(bytes in any::<[u8; 32]>()) -> Scalar { 11 | >::reduce(&bytes.into()) 12 | } 13 | } 14 | 15 | proptest! { 16 | #[test] 17 | fn invert_and_invert_vartime_are_equivalent(w in scalar()) { 18 | let inv: Option = w.invert().into(); 19 | let inv_vartime: Option = w.invert_vartime().into(); 20 | prop_assert_eq!(inv, inv_vartime); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /k256/src/arithmetic/dev.rs: -------------------------------------------------------------------------------- 1 | //! Development helper functions. 2 | 3 | use num_bigint::{BigUint, ToBigUint}; 4 | use num_traits::cast::ToPrimitive; 5 | 6 | /// Converts a byte array (big-endian) to BigUint. 7 | pub fn bytes_to_biguint(bytes: &[u8; 32]) -> BigUint { 8 | bytes 9 | .iter() 10 | .enumerate() 11 | .map(|(i, w)| w.to_biguint().unwrap() << ((31 - i) * 8)) 12 | .sum() 13 | } 14 | 15 | /// Converts a BigUint to a byte array (big-endian). 16 | pub fn biguint_to_bytes(x: &BigUint) -> [u8; 32] { 17 | let mask = BigUint::from(u8::MAX); 18 | let mut bytes = [0u8; 32]; 19 | for i in 0..32 { 20 | bytes[i] = ((x >> ((31 - i) * 8)) as BigUint & &mask).to_u8().unwrap(); 21 | } 22 | bytes 23 | } 24 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Security updates are applied only to the most recent release. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | If you have discovered a security vulnerability in this project, please report 10 | it privately. **Do not disclose it as a public issue.** This gives us time to 11 | work with you to fix the issue before public exposure, reducing the chance that 12 | the exploit will be used before a patch is released. 13 | 14 | Please disclose it at [security advisory](https://github.com/RustCrypto/elliptic-curves/security/advisories/new). 15 | 16 | This project is maintained by a team of volunteers on a reasonable-effort basis. 17 | As such, please give us at least 90 days to work on a fix before public exposure. 18 | -------------------------------------------------------------------------------- /.github/workflows/security-audit.yml: -------------------------------------------------------------------------------- 1 | name: Security Audit 2 | on: 3 | pull_request: 4 | paths: 5 | - .github/workflows/security-audit.yml 6 | - Cargo.lock 7 | push: 8 | branches: master 9 | paths: Cargo.lock 10 | schedule: 11 | - cron: "0 0 * * *" 12 | 13 | jobs: 14 | security_audit: 15 | name: Security Audit 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v6 19 | - uses: dtolnay/rust-toolchain@master 20 | with: 21 | toolchain: stable 22 | - uses: actions/cache@v5 23 | with: 24 | path: ~/.cargo/bin 25 | key: ${{ runner.os }}-cargo-audit-v0.22.0 26 | - uses: rustsec/audit-check@v2 27 | with: 28 | token: ${{ secrets.GITHUB_TOKEN }} 29 | -------------------------------------------------------------------------------- /p256/tests/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! ECDSA tests. 2 | 3 | #![cfg(feature = "arithmetic")] 4 | 5 | use elliptic_curve::ops::Reduce; 6 | use p256::{ 7 | FieldBytes, NonZeroScalar, 8 | ecdsa::{SigningKey, VerifyingKey}, 9 | }; 10 | use proptest::prelude::*; 11 | 12 | prop_compose! { 13 | fn signing_key()(bytes in any::<[u8; 32]>()) -> SigningKey { 14 | >::reduce(&bytes.into()).into() 15 | } 16 | } 17 | 18 | proptest! { 19 | #[test] 20 | fn recover_from_msg(sk in signing_key()) { 21 | let msg = b"example"; 22 | let (signature, v) = sk.sign_recoverable(msg).unwrap(); 23 | let recovered_vk = VerifyingKey::recover_from_msg(msg, &signature, v).unwrap(); 24 | prop_assert_eq!(sk.verifying_key(), &recovered_vk); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /hash2curve/src/oprf.rs: -------------------------------------------------------------------------------- 1 | use digest::FixedOutput; 2 | use digest::Update; 3 | use elliptic_curve::PrimeCurve; 4 | use elliptic_curve::array::typenum::IsLess; 5 | use elliptic_curve::consts::{True, U65536}; 6 | 7 | use crate::{ExpandMsg, GroupDigest}; 8 | 9 | /// Elliptic curve parameters used by OPRF. 10 | pub trait OprfParameters: 11 | GroupDigest< 12 | ExpandMsg: ExpandMsg< 13 | Self::SecurityLevel, 14 | Hash: Default + FixedOutput> + Update, 15 | >, 16 | > + PrimeCurve 17 | { 18 | /// The `ID` parameter which identifies a particular elliptic curve 19 | /// as defined in [section 4 of RFC9497][oprf]. 20 | /// 21 | /// [oprf]: https://www.rfc-editor.org/rfc/rfc9497.html#name-ciphersuites 22 | const ID: &'static [u8]; 23 | } 24 | -------------------------------------------------------------------------------- /k256/src/test_vectors/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! ECDSA/secp256k1 test vectors 2 | 3 | use ecdsa_core::dev::TestVector; 4 | use hex_literal::hex; 5 | 6 | /// ECDSA/secp256k1 test vectors 7 | pub const ECDSA_TEST_VECTORS: &[TestVector] = &[TestVector { 8 | d: &hex!("ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f"), 9 | q_x: &hex!("779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcd"), 10 | q_y: &hex!("e94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f"), 11 | k: &hex!("49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a"), 12 | m: &hex!("4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a"), 13 | r: &hex!("241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795"), 14 | s: &hex!("021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e"), 15 | }]; 16 | -------------------------------------------------------------------------------- /bignp256/tests/projective.rs: -------------------------------------------------------------------------------- 1 | //! Projective arithmetic tests. 2 | 3 | #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] 4 | 5 | use bignp256::{ 6 | AffinePoint, ProjectivePoint, Scalar, 7 | test_vectors::group::{ADD_TEST_VECTORS, MUL_TEST_VECTORS}, 8 | }; 9 | use elliptic_curve::{ 10 | group::{GroupEncoding, ff::PrimeField}, 11 | sec1::{self, ToEncodedPoint}, 12 | }; 13 | use primeorder::{Double, test_projective_arithmetic}; 14 | 15 | test_projective_arithmetic!( 16 | AffinePoint, 17 | ProjectivePoint, 18 | Scalar, 19 | ADD_TEST_VECTORS, 20 | MUL_TEST_VECTORS 21 | ); 22 | 23 | #[test] 24 | fn projective_identity_to_bytes() { 25 | // This is technically an invalid SEC1 encoding, but is preferable to panicking. 26 | assert_eq!([0; 33], ProjectivePoint::IDENTITY.to_bytes().as_slice()); 27 | } 28 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve/scalar_mul/double_and_add.rs: -------------------------------------------------------------------------------- 1 | use crate::curve::twedwards::extended::ExtendedPoint; 2 | use crate::curve::twedwards::extensible::ExtensiblePoint; 3 | use subtle::{Choice, ConditionallySelectable}; 4 | 5 | /// Traditional double and add algorithm 6 | pub(crate) fn double_and_add(point: &ExtendedPoint, s_bits: [bool; 448]) -> ExtensiblePoint { 7 | let mut result = ExtensiblePoint::IDENTITY; 8 | 9 | // NB, we reverse here, so we are going from MSB to LSB 10 | // XXX: Would be great if subtle had a From for Choice. But maybe that is not it's purpose? 11 | for bit in s_bits.into_iter().rev() { 12 | result = result.double(); 13 | 14 | let mut p = ExtendedPoint::IDENTITY; 15 | p.conditional_assign(point, Choice::from(bit as u8)); 16 | result = result.to_extended().add_extended(&p); 17 | } 18 | 19 | result 20 | } 21 | -------------------------------------------------------------------------------- /hash2curve/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hash2curve" 3 | version = "0.14.0-rc.4" 4 | description = "hash2curve algorithm implementation" 5 | authors = ["RustCrypto Developers"] 6 | license = "Apache-2.0 OR MIT" 7 | documentation = "https://docs.rs/hash2curve" 8 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/hash2curve" 9 | repository = "https://github.com/RustCrypto/elliptic-curves" 10 | readme = "README.md" 11 | categories = ["cryptography", "no-std"] 12 | keywords = ["hash2curve", "crypto", "ecc"] 13 | edition = "2024" 14 | rust-version = "1.85" 15 | 16 | [dependencies] 17 | digest = { version = "0.11.0-rc.4" } 18 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["arithmetic"] } 19 | 20 | [dev-dependencies] 21 | hex-literal = "1" 22 | sha2 = { version = "0.11.0-rc.3", default-features = false } 23 | sha3 = { version = "0.11.0-rc.3", default-features = false } 24 | -------------------------------------------------------------------------------- /hash2curve/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | #![doc = include_str!("../README.md")] 4 | #![doc( 5 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", 6 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" 7 | )] 8 | #![allow(non_snake_case)] 9 | #![forbid(unsafe_code)] 10 | #![warn( 11 | clippy::unwrap_used, 12 | clippy::mod_module_files, 13 | missing_copy_implementations, 14 | missing_debug_implementations, 15 | missing_docs, 16 | trivial_casts, 17 | trivial_numeric_casts, 18 | unused, 19 | unused_attributes, 20 | unused_imports, 21 | unused_mut, 22 | unused_must_use 23 | )] 24 | 25 | mod group_digest; 26 | mod hash2field; 27 | mod map2curve; 28 | mod oprf; 29 | 30 | pub use group_digest::*; 31 | pub use hash2field::*; 32 | pub use map2curve::*; 33 | pub use oprf::*; 34 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/sign/context.rs: -------------------------------------------------------------------------------- 1 | /// Ed448 contexts as used by Ed448ph. 2 | /// 3 | /// Contexts are domain separator strings that can be used to isolate uses of 4 | /// the algorithm between different protocols (which is very hard to reliably do 5 | /// otherwise) and between different uses within the same protocol. 6 | /// 7 | /// To create a context, call either of the following: 8 | /// 9 | /// - [`SigningKey::with_context`](crate::SigningKey::with_context) 10 | /// - [`VerifyingKey::with_context`](crate::VerifyingKey::with_context) 11 | #[derive(Copy, Clone, Debug)] 12 | pub struct Context<'k, 'v, K> { 13 | pub(crate) key: &'k K, 14 | pub(crate) value: &'v [u8], 15 | } 16 | 17 | impl<'k, 'v, K> Context<'k, 'v, K> { 18 | /// Maximum length of a context string. 19 | pub const MAX_LENGTH: usize = 255; 20 | 21 | /// Borrow the key 22 | pub fn key(&self) -> &'k K { 23 | self.key 24 | } 25 | 26 | /// Borrow the value 27 | pub fn value(&self) -> &'v [u8] { 28 | self.value 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /primefield/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "primefield" 3 | version = "0.14.0-rc.1" 4 | description = "Macros for generating prime field implementations" 5 | authors = ["RustCrypto Developers"] 6 | license = "Apache-2.0 OR MIT" 7 | documentation = "https://docs.rs/primefield" 8 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/primefield" 9 | repository = "https://github.com/RustCrypto/elliptic-curves" 10 | readme = "README.md" 11 | categories = ["cryptography", "no-std"] 12 | keywords = ["crypto", "ecc", "field", "prime"] 13 | edition = "2024" 14 | rust-version = "1.85" 15 | 16 | [dependencies] 17 | bigint = { package = "crypto-bigint", version = "0.7.0-rc.10", default-features = false, features = ["hybrid-array"] } 18 | ff = { version = "=0.14.0-pre.0", package = "rustcrypto-ff", default-features = false } 19 | subtle = { version = "2.6", default-features = false, features = ["const-generics"] } 20 | rand_core = { version = "0.10.0-rc-2", default-features = false } 21 | zeroize = { version = "1.7", default-features = false } 22 | -------------------------------------------------------------------------------- /primefield/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", 5 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" 6 | )] 7 | #![forbid(unsafe_code)] 8 | #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] 9 | #![doc = include_str!("../README.md")] 10 | 11 | mod dev; 12 | mod error; 13 | mod macros; 14 | mod monty; 15 | 16 | pub use crate::{ 17 | error::{Error, Result}, 18 | monty::{MontyFieldBytes, MontyFieldElement, MontyFieldParams, compute_t}, 19 | }; 20 | pub use array::typenum::consts; 21 | pub use bigint; 22 | pub use bigint::hybrid_array as array; 23 | pub use ff; 24 | pub use rand_core; 25 | pub use subtle; 26 | pub use zeroize; 27 | 28 | /// Byte order used when encoding/decoding field elements as bytestrings. 29 | #[derive(Debug)] 30 | pub enum ByteOrder { 31 | /// Big endian. 32 | BigEndian, 33 | 34 | /// Little endian. 35 | LittleEndian, 36 | } 37 | -------------------------------------------------------------------------------- /p521/src/arithmetic/util.rs: -------------------------------------------------------------------------------- 1 | //! Utility functions. 2 | 3 | /// Convert an 17-element array of `u32` into a 9-element array of `u64`, 4 | /// assuming integer arrays are in little-endian order. 5 | #[cfg(target_pointer_width = "32")] 6 | pub(crate) const fn u32x17_to_u64x9(w: &[u32; 17]) -> [u64; 9] { 7 | let mut ret = [0u64; 9]; 8 | let mut i = 0; 9 | 10 | while i < 8 { 11 | ret[i] = (w[i * 2] as u64) | ((w[(i * 2) + 1] as u64) << 32); 12 | i += 1; 13 | } 14 | 15 | ret[i] = w[i * 2] as u64; 16 | ret 17 | } 18 | 19 | /// Convert a 9-element array of `u64` into an 17-element array of `u32`, 20 | /// assuming integers are in little-endian order. 21 | #[cfg(target_pointer_width = "32")] 22 | pub(crate) const fn u64x9_to_u32x17(w: &[u64; 9]) -> [u32; 17] { 23 | let mut ret = [0u32; 17]; 24 | let mut i = 0; 25 | 26 | while i < 8 { 27 | ret[i * 2] = (w[i] & 0xFFFFFFFF) as u32; 28 | ret[(i * 2) + 1] = (w[i] >> 32) as u32; 29 | i += 1; 30 | } 31 | 32 | ret[i * 2] = (w[i] & 0xFFFFFFFF) as u32; 33 | debug_assert!((w[i] >> 32) == 0); 34 | 35 | ret 36 | } 37 | -------------------------------------------------------------------------------- /p192/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /p224/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /sm2/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /bignp256/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /bp256/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /bp384/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /hash2curve/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /k256/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2024 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /p256/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /p384/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2021 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /p521/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2022 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /primefield/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /primeorder/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2023 RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /x448/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2025 Kevaundray Wedderburn, RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /ed448-goldilocks/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2025 Kevaundray Wedderburn, RustCrypto Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/edwards.rs: -------------------------------------------------------------------------------- 1 | /// This module contains the code for the Goldilocks curve. 2 | /// The goldilocks curve is the (untwisted) Edwards curve with affine equation x^2 + y^2 = 1 - 39081x^2y^2 3 | /// Scalar Multiplication for this curve is pre-dominantly delegated to the Twisted Edwards variation using a (doubling) isogeny 4 | /// Passing the point back to the Goldilocks curve using the dual-isogeny clears the cofactor. 5 | /// The small remainder of the Scalar Multiplication is computed on the untwisted curve. 6 | /// See for details 7 | /// 8 | /// This isogeny strategy does not clear the cofactor on the Goldilocks curve unless the Scalar is a multiple of 4. 9 | /// or the point is known to be in the q-torsion subgroup. 10 | /// Hence, one will need to multiply by the cofactor to ensure it is cleared when using the Goldilocks curve. 11 | /// If this is a problem, one can use a different isogeny strategy (Decaf) 12 | pub(crate) mod affine; 13 | pub(crate) mod extended; 14 | mod scalar; 15 | pub use affine::{AffinePoint, CompressedEdwardsY}; 16 | pub use extended::EdwardsPoint; 17 | pub use scalar::{EdwardsScalar, EdwardsScalarBytes, WideEdwardsScalarBytes}; 18 | -------------------------------------------------------------------------------- /p192/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.14.0 (UNRELEASED) 8 | ### Added 9 | - `bits` feature ([#868]) 10 | - `elliptic_curve::ops::Invert` implementation ([#971]) 11 | 12 | ## Changed 13 | - Update to `elliptic-curve` v0.14 ([#1011]) 14 | - Update to `ecdsa` v0.17 ([#1011]) 15 | - Update to `sec1` v0.8 ([#1011]) 16 | - Update to `secdect` v0.3 ([#1084]) 17 | - Update to `rand_core` v0.9 ([#1125]) 18 | - Update to `hybrid-array` v0.3 ([#1125]) 19 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1125]) 20 | - Relax MSRV policy and allow MSRV bumps in patch releases 21 | 22 | [#868]: https://github.com/RustCrypto/elliptic-curves/pull/868 23 | [#971]: https://github.com/RustCrypto/elliptic-curves/pull/971 24 | [#1011]: https://github.com/RustCrypto/elliptic-curves/pull/1011 25 | [#1084]: https://github.com/RustCrypto/elliptic-curves/pull/1084 26 | [#1125]: https://github.com/RustCrypto/elliptic-curves/pull/1125 27 | 28 | ## 0.13.0 (2023-04-15) 29 | - Initial release 30 | -------------------------------------------------------------------------------- /primeorder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "primeorder" 3 | version = "0.14.0-rc.1" 4 | description = """ 5 | Pure Rust implementation of complete addition formulas for prime order elliptic 6 | curves (Renes-Costello-Batina 2015). Generic over field elements and curve 7 | equation coefficients 8 | """ 9 | authors = ["RustCrypto Developers"] 10 | license = "Apache-2.0 OR MIT" 11 | documentation = "https://docs.rs/primeorder" 12 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/primeorder" 13 | repository = "https://github.com/RustCrypto/elliptic-curves" 14 | readme = "README.md" 15 | categories = ["cryptography", "no-std"] 16 | keywords = ["crypto", "ecc"] 17 | edition = "2024" 18 | rust-version = "1.85" 19 | 20 | [dependencies] 21 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["arithmetic", "sec1"] } 22 | 23 | # optional dependencies 24 | serdect = { version = "0.4", optional = true, default-features = false } 25 | 26 | [features] 27 | alloc = ["elliptic-curve/alloc"] 28 | std = ["alloc", "elliptic-curve/std"] 29 | 30 | dev = [] 31 | hash2curve = [] 32 | serde = ["elliptic-curve/serde", "serdect"] 33 | 34 | [package.metadata.docs.rs] 35 | all-features = true 36 | -------------------------------------------------------------------------------- /x448/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "x448" 3 | version = "0.14.0-pre.1" 4 | authors = ["RustCrypto Developers"] 5 | categories = ["cryptography"] 6 | keywords = ["cryptography", "crypto", "x448", "diffie-hellman", "curve448", ] 7 | homepage = "https://docs.rs/x448/" 8 | repository = "https://github.com/RustCrypto/elliptic-curves/tree/master/x448" 9 | documentation = "https://docs.rs/ed448-goldilocks" 10 | license = "Apache-2.0 OR MIT" 11 | edition = "2024" 12 | rust-version = "1.85" 13 | readme = "README.md" 14 | description = "Pure Rust implementation of X448, an elliptic curve Diffie-Hellman function" 15 | 16 | [dependencies] 17 | ed448-goldilocks = { version = "0.14.0-pre.4", default-features = false } 18 | rand_core = { version = "0.10.0-rc-2", default-features = false } 19 | 20 | # optional dependencies 21 | serdect = { version = "0.4", optional = true } 22 | 23 | [dependencies.zeroize] 24 | version = "1" 25 | default-features = false 26 | features = ["zeroize_derive"] 27 | 28 | [dev-dependencies] 29 | rand = "0.10.0-rc.1" 30 | 31 | [features] 32 | default = ["getrandom"] 33 | getrandom = ["ed448-goldilocks/getrandom"] 34 | static_secrets = [] 35 | serde = ["dep:serdect", "ed448-goldilocks/serde"] 36 | 37 | [package.metadata.docs.rs] 38 | all-features = true 39 | -------------------------------------------------------------------------------- /bignp256/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.14.0 (UNRELEASED) 8 | ### Added 9 | - ECDH and PKCS8 support ([#1046]) 10 | - `bits`, `serde`, and `test-vectors` features ([#1062]) 11 | 12 | ## Changed 13 | - Update to `digest` v0.11 ([#1011]) 14 | - Update to `pkcs8` v0.11 ([#1011]) 15 | - Update to `sec1` v0.8 ([#1011]) 16 | - Update to `rand_core` v0.9 ([#1125]) 17 | - Update to `hybrid-array` v0.3 ([#1125]) 18 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1125]) 19 | - Relax MSRV policy and allow MSRV bumps in patch releases 20 | 21 | [#1011]: https://github.com/RustCrypto/elliptic-curves/pull/1011 22 | [#1046]: https://github.com/RustCrypto/elliptic-curves/pull/1046 23 | [#1062]: https://github.com/RustCrypto/elliptic-curves/pull/1062 24 | [#1125]: https://github.com/RustCrypto/elliptic-curves/pull/1125 25 | 26 | ## 0.13.1 (2024-01-05) 27 | ### Added 28 | - Digital signature algorithm ([#935]) 29 | 30 | [#935]: https://github.com/RustCrypto/elliptic-curves/pull/935 31 | 32 | ## 0.13.0 (2023-06-27) 33 | - Initial release 34 | -------------------------------------------------------------------------------- /hash2curve/src/map2curve.rs: -------------------------------------------------------------------------------- 1 | //! Traits for mapping field elements to points on the curve. 2 | 3 | use elliptic_curve::array::typenum::{NonZero, Unsigned}; 4 | use elliptic_curve::array::{Array, ArraySize}; 5 | use elliptic_curve::group::cofactor::CofactorGroup; 6 | use elliptic_curve::ops::Reduce; 7 | use elliptic_curve::{CurveArithmetic, ProjectivePoint}; 8 | 9 | /// Trait for converting field elements into a point via a mapping method like 10 | /// Simplified Shallue-van de Woestijne-Ulas or Elligator. 11 | pub trait MapToCurve: 12 | CurveArithmetic> 13 | { 14 | /// The target security level in bytes: 15 | /// 16 | /// 17 | type SecurityLevel: Unsigned; 18 | /// The field element representation for a group value with multiple elements. 19 | type FieldElement: Reduce> + Default + Copy; 20 | /// The `L` parameter as specified in the [RFC](https://www.rfc-editor.org/rfc/rfc9380.html#section-5-6). 21 | type Length: ArraySize + NonZero; 22 | 23 | /// Map a field element into a curve point. 24 | fn map_to_curve(element: Self::FieldElement) -> ProjectivePoint; 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/hash2curve.yml: -------------------------------------------------------------------------------- 1 | name: hash2curve 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/hash2curve.yml" 7 | - "hash2curve/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | defaults: 13 | run: 14 | working-directory: hash2curve 15 | 16 | env: 17 | CARGO_INCREMENTAL: 0 18 | RUSTFLAGS: "-Dwarnings" 19 | RUSTDOCFLAGS: "-Dwarnings" 20 | 21 | # Cancels CI jobs when new commits are pushed to a PR branch 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 24 | cancel-in-progress: true 25 | 26 | jobs: 27 | build: 28 | runs-on: ubuntu-latest 29 | strategy: 30 | matrix: 31 | rust: 32 | - 1.85.0 # MSRV 33 | - stable 34 | target: 35 | - thumbv7em-none-eabi 36 | - wasm32-unknown-unknown 37 | steps: 38 | - uses: actions/checkout@v6 39 | - uses: dtolnay/rust-toolchain@master 40 | with: 41 | toolchain: ${{ matrix.rust }} 42 | targets: ${{ matrix.target }} 43 | - run: cargo build --target ${{ matrix.target }} --release 44 | 45 | test: 46 | runs-on: ubuntu-latest 47 | strategy: 48 | matrix: 49 | rust: 50 | - 1.85.0 # MSRV 51 | - stable 52 | steps: 53 | - uses: actions/checkout@v6 54 | - uses: dtolnay/rust-toolchain@master 55 | with: 56 | toolchain: ${{ matrix.rust }} 57 | - run: cargo test 58 | -------------------------------------------------------------------------------- /.github/workflows/primefield.yml: -------------------------------------------------------------------------------- 1 | name: primefield 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/primefield.yml" 7 | - "primefield/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | defaults: 13 | run: 14 | working-directory: primefield 15 | 16 | env: 17 | CARGO_INCREMENTAL: 0 18 | RUSTFLAGS: "-Dwarnings" 19 | RUSTDOCFLAGS: "-Dwarnings" 20 | 21 | # Cancels CI jobs when new commits are pushed to a PR branch 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 24 | cancel-in-progress: true 25 | 26 | jobs: 27 | build: 28 | runs-on: ubuntu-latest 29 | strategy: 30 | matrix: 31 | rust: 32 | - 1.85.0 # MSRV 33 | - stable 34 | target: 35 | - thumbv7em-none-eabi 36 | - wasm32-unknown-unknown 37 | steps: 38 | - uses: actions/checkout@v6 39 | - uses: dtolnay/rust-toolchain@master 40 | with: 41 | toolchain: ${{ matrix.rust }} 42 | targets: ${{ matrix.target }} 43 | - run: cargo build --target ${{ matrix.target }} --release 44 | 45 | test: 46 | runs-on: ubuntu-latest 47 | strategy: 48 | matrix: 49 | rust: 50 | - 1.85.0 # MSRV 51 | - stable 52 | steps: 53 | - uses: actions/checkout@v6 54 | - uses: dtolnay/rust-toolchain@master 55 | with: 56 | toolchain: ${{ matrix.rust }} 57 | - run: cargo test 58 | -------------------------------------------------------------------------------- /sm2/src/distid.rs: -------------------------------------------------------------------------------- 1 | //! Distinguished identifier support. 2 | 3 | use crate::{AffinePoint, Hash, Sm2}; 4 | use elliptic_curve::{ 5 | Error, Result, 6 | sec1::{self, ToEncodedPoint}, 7 | }; 8 | use primeorder::PrimeCurveParams; 9 | use sm3::{Digest, Sm3}; 10 | 11 | /// Type which represents distinguishing identifiers. 12 | pub(crate) type DistId = str; 13 | 14 | /// Compute user information hash `Z` according to [draft-shen-sm2-ecdsa § 5.1.4.4]. 15 | /// 16 | /// ```text 17 | /// ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA) 18 | /// ``` 19 | /// 20 | /// [draft-shen-sm2-ecdsa § 5.1.4.4]: https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa-02#section-5.1.4.4 21 | pub(crate) fn hash_z(distid: &DistId, public_key: &impl AsRef) -> Result { 22 | let entla: u16 = distid 23 | .len() 24 | .checked_mul(8) 25 | .and_then(|l| l.try_into().ok()) 26 | .ok_or(Error)?; 27 | 28 | let mut sm3 = Sm3::new(); 29 | sm3.update(entla.to_be_bytes()); 30 | sm3.update(distid); 31 | sm3.update(Sm2::EQUATION_A.to_bytes()); 32 | sm3.update(Sm2::EQUATION_B.to_bytes()); 33 | sm3.update(Sm2::GENERATOR.0.to_bytes()); 34 | sm3.update(Sm2::GENERATOR.1.to_bytes()); 35 | 36 | match public_key.as_ref().to_encoded_point(false).coordinates() { 37 | sec1::Coordinates::Uncompressed { x, y } => { 38 | sm3.update(x); 39 | sm3.update(y); 40 | Ok(sm3.finalize()) 41 | } 42 | _ => Err(Error), 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/workflows/workspace.yml: -------------------------------------------------------------------------------- 1 | name: Workspace 2 | 3 | on: 4 | pull_request: 5 | paths-ignore: 6 | - README.md 7 | push: 8 | branches: master 9 | paths-ignore: 10 | - README.md 11 | 12 | env: 13 | CARGO_INCREMENTAL: 0 14 | RUSTFLAGS: "-Dwarnings" 15 | 16 | # Cancels CI jobs when new commits are pushed to a PR branch 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | clippy: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v6 26 | - uses: dtolnay/rust-toolchain@master 27 | with: 28 | toolchain: 1.89 # pinned to prevent breakages when new stable versions are released 29 | components: clippy 30 | - run: cargo clippy --all --all-features -- -D warnings 31 | 32 | doc: 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v6 36 | - uses: dtolnay/rust-toolchain@master 37 | with: 38 | toolchain: stable 39 | - run: cargo doc --workspace --all-features --no-deps 40 | 41 | rustfmt: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v6 45 | - uses: dtolnay/rust-toolchain@master 46 | with: 47 | toolchain: stable 48 | components: rustfmt 49 | - run: cargo fmt --all -- --check 50 | 51 | typos: 52 | runs-on: ubuntu-latest 53 | steps: 54 | - uses: actions/checkout@v6 55 | - uses: crate-ci/typos@v1.40.0 56 | -------------------------------------------------------------------------------- /sm2/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.14.0 (UNRELEASED) 8 | ## Added 9 | - Signature and key PKCS8 support ([#1127]) 10 | 11 | ## Changed 12 | - Update to `elliptic-curve` v0.14 ([#1011]) 13 | - Update to `secdect` v0.3 ([#1084]) 14 | - Update to `rand_core` v0.9 ([#1125]) 15 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1125]) 16 | - Relax MSRV policy and allow MSRV bumps in patch releases 17 | 18 | [#964]: https://github.com/RustCrypto/elliptic-curves/pull/964 19 | [#1011]: https://github.com/RustCrypto/elliptic-curves/pull/1011 20 | [#1084]: https://github.com/RustCrypto/elliptic-curves/pull/1084 21 | [#1125]: https://github.com/RustCrypto/elliptic-curves/pull/1125 22 | [#1127]: https://github.com/RustCrypto/elliptic-curves/pull/1127 23 | 24 | ## 0.13.3 (2023-11-20) 25 | ### Added 26 | - Impl `Randomized*Signer` for `sm2::dsa::SigningKey` ([#993]) 27 | 28 | [#993]: https://github.com/RustCrypto/elliptic-curves/pull/993 29 | 30 | ## 0.13.2 (2023-04-15) 31 | ### Changed 32 | - Factor out `distid` module ([#865]) 33 | 34 | [#865]: https://github.com/RustCrypto/elliptic-curves/pull/865 35 | 36 | ## 0.13.1 (2023-04-15) [YANKED] 37 | ### Added 38 | - Enable `dsa` feature by default ([#862]) 39 | 40 | [#862]: https://github.com/RustCrypto/elliptic-curves/pull/862 41 | 42 | ## 0.13.0 (2023-04-15) [YANKED] 43 | - Initial RustCrypto release 44 | 45 | ## 0.0.1 (2020-03-02) 46 | -------------------------------------------------------------------------------- /bp256/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | #![doc = include_str!("../README.md")] 4 | #![doc( 5 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", 6 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" 7 | )] 8 | #![forbid(unsafe_code)] 9 | #![warn( 10 | clippy::mod_module_files, 11 | clippy::unwrap_used, 12 | missing_docs, 13 | rust_2018_idioms, 14 | unused_lifetimes, 15 | unused_qualifications 16 | )] 17 | 18 | pub mod r1; 19 | pub mod t1; 20 | 21 | #[cfg(feature = "arithmetic")] 22 | mod arithmetic; 23 | 24 | pub use crate::{r1::BrainpoolP256r1, t1::BrainpoolP256t1}; 25 | pub use elliptic_curve::{self, bigint::U256}; 26 | 27 | #[cfg(feature = "arithmetic")] 28 | pub use crate::arithmetic::scalar::Scalar; 29 | 30 | #[cfg(feature = "pkcs8")] 31 | pub use elliptic_curve::pkcs8; 32 | 33 | #[cfg(feature = "arithmetic")] 34 | pub(crate) use crate::arithmetic::field::FieldElement; 35 | 36 | use elliptic_curve::{ 37 | array::{Array, typenum::U32}, 38 | bigint::{ArrayEncoding, Odd}, 39 | }; 40 | 41 | /// Byte representation of a base/scalar field element of a given curve. 42 | pub type FieldBytes = Array; 43 | 44 | const ORDER_HEX: &str = "a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7"; 45 | const ORDER: Odd = Odd::::from_be_hex(ORDER_HEX); 46 | 47 | fn decode_field_bytes(field_bytes: &FieldBytes) -> U256 { 48 | U256::from_be_byte_array(*field_bytes) 49 | } 50 | 51 | fn encode_field_bytes(uint: &U256) -> FieldBytes { 52 | uint.to_be_byte_array() 53 | } 54 | -------------------------------------------------------------------------------- /bp256/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bp256" 3 | version = "0.14.0-rc.1" 4 | description = "Brainpool P-256 (brainpoolP256r1 and brainpoolP256t1) elliptic curves" 5 | authors = ["RustCrypto Developers"] 6 | license = "Apache-2.0 OR MIT" 7 | documentation = "https://docs.rs/bp256" 8 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/bp256" 9 | repository = "https://github.com/RustCrypto/elliptic-curves" 10 | readme = "README.md" 11 | categories = ["cryptography", "no-std"] 12 | keywords = ["brainpool", "crypto", "ecc"] 13 | edition = "2024" 14 | rust-version = "1.85" 15 | 16 | [dependencies] 17 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["sec1"] } 18 | 19 | # optional dependencies 20 | ecdsa = { version = "0.17.0-rc.9", optional = true, default-features = false, features = ["der"] } 21 | primefield = { version = "0.14.0-rc.1", optional = true } 22 | primeorder = { version = "0.14.0-rc.1", optional = true } 23 | sha2 = { version = "0.11.0-rc.3", optional = true, default-features = false } 24 | 25 | [features] 26 | default = ["pkcs8", "std"] 27 | alloc = ["ecdsa?/alloc", "elliptic-curve/alloc", "primeorder?/alloc"] 28 | std = ["alloc", "ecdsa?/std", "elliptic-curve/std", "getrandom"] 29 | 30 | arithmetic = ["dep:primefield", "dep:primeorder"] 31 | bits = ["arithmetic", "elliptic-curve/bits"] 32 | getrandom = ["ecdsa?/getrandom", "elliptic-curve/getrandom"] 33 | pem = ["elliptic-curve/pem", "pkcs8"] 34 | pkcs8 = ["ecdsa/pkcs8", "elliptic-curve/pkcs8"] 35 | serde = ["ecdsa/serde", "elliptic-curve/serde"] 36 | sha256 = ["ecdsa/digest", "ecdsa/hazmat", "sha2"] 37 | 38 | [package.metadata.docs.rs] 39 | all-features = true 40 | -------------------------------------------------------------------------------- /bp384/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bp384" 3 | version = "0.14.0-rc.1" 4 | description = "Brainpool P-384 (brainpoolP384r1 and brainpoolP384t1) elliptic curves" 5 | authors = ["RustCrypto Developers"] 6 | license = "Apache-2.0 OR MIT" 7 | documentation = "https://docs.rs/bp384" 8 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/bp384" 9 | repository = "https://github.com/RustCrypto/elliptic-curves" 10 | readme = "README.md" 11 | categories = ["cryptography", "no-std"] 12 | keywords = ["brainpool", "crypto", "ecc"] 13 | edition = "2024" 14 | rust-version = "1.85" 15 | 16 | [dependencies] 17 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["sec1"] } 18 | 19 | # optional dependencies 20 | ecdsa = { version = "0.17.0-rc.9", optional = true, default-features = false, features = ["der"] } 21 | primefield = { version = "0.14.0-rc.1", optional = true } 22 | primeorder = { version = "0.14.0-rc.1", optional = true } 23 | sha2 = { version = "0.11.0-rc.3", optional = true, default-features = false } 24 | 25 | [features] 26 | default = ["pkcs8", "std"] 27 | alloc = ["ecdsa?/alloc", "elliptic-curve/alloc", "primeorder?/alloc"] 28 | std = ["alloc", "ecdsa?/std", "elliptic-curve/std", "getrandom"] 29 | 30 | arithmetic = ["dep:primefield", "dep:primeorder"] 31 | bits = ["arithmetic", "elliptic-curve/bits"] 32 | getrandom = ["ecdsa?/getrandom", "elliptic-curve/getrandom"] 33 | pem = ["elliptic-curve/pem", "pkcs8"] 34 | pkcs8 = ["ecdsa/pkcs8", "elliptic-curve/pkcs8"] 35 | serde = ["ecdsa/serde", "elliptic-curve/serde"] 36 | sha384 = ["ecdsa/digest", "ecdsa/hazmat", "sha2"] 37 | 38 | [package.metadata.docs.rs] 39 | all-features = true 40 | -------------------------------------------------------------------------------- /hash2curve/src/hash2field.rs: -------------------------------------------------------------------------------- 1 | //! Traits for hashing to field elements. 2 | //! 3 | //! 4 | 5 | mod expand_msg; 6 | 7 | use core::num::NonZeroU16; 8 | 9 | pub use expand_msg::{xmd::*, xof::*, *}; 10 | 11 | use elliptic_curve::{ 12 | array::{Array, ArraySize, typenum::NonZero}, 13 | ops::Reduce, 14 | }; 15 | 16 | /// Convert an arbitrary byte sequence into a field element. 17 | /// 18 | /// 19 | /// 20 | /// For the `expand_message` call, `len_in_bytes = L * N`. 21 | /// 22 | /// # Errors 23 | /// 24 | /// Returns an error if the [`ExpandMsg`] implementation fails. 25 | #[doc(hidden)] 26 | pub fn hash_to_field( 27 | data: &[&[u8]], 28 | domain: &[&[u8]], 29 | ) -> Result<[T; N], E::Error> 30 | where 31 | E: ExpandMsg, 32 | T: Reduce> + Default, 33 | L: ArraySize + NonZero, 34 | { 35 | // Completely degenerate case; `N` and `L` would need to be extremely large. 36 | let len_in_bytes = const { 37 | assert!( 38 | L::USIZE.saturating_mul(N) <= u16::MAX as usize, 39 | "The product of `L` and `N` must not exceed `u16::MAX`." 40 | ); 41 | NonZeroU16::new(L::U16 * N as u16).expect("N is greater than 0") 42 | }; 43 | let mut tmp = Array::::default(); 44 | let mut expander = E::expand_message(data, domain, len_in_bytes)?; 45 | Ok(core::array::from_fn(|_| { 46 | expander 47 | .fill_bytes(&mut tmp) 48 | .expect("never exceeds `len_in_bytes`"); 49 | T::reduce(&tmp) 50 | })) 51 | } 52 | -------------------------------------------------------------------------------- /k256/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! A pure-Rust implementation of group operations on secp256k1. 2 | 3 | pub(crate) mod affine; 4 | mod field; 5 | #[cfg(feature = "hash2curve")] 6 | mod hash2curve; 7 | mod mul; 8 | pub(crate) mod projective; 9 | pub(crate) mod scalar; 10 | 11 | #[cfg(test)] 12 | mod dev; 13 | 14 | pub use field::FieldElement; 15 | 16 | use self::{affine::AffinePoint, projective::ProjectivePoint, scalar::Scalar}; 17 | use crate::Secp256k1; 18 | use elliptic_curve::CurveArithmetic; 19 | 20 | impl CurveArithmetic for Secp256k1 { 21 | type AffinePoint = AffinePoint; 22 | type ProjectivePoint = ProjectivePoint; 23 | type Scalar = Scalar; 24 | } 25 | 26 | const CURVE_EQUATION_B_SINGLE: u32 = 7u32; 27 | 28 | #[rustfmt::skip] 29 | pub(crate) const CURVE_EQUATION_B: FieldElement = FieldElement::from_bytes_unchecked(&[ 30 | 0, 0, 0, 0, 0, 0, 0, 0, 31 | 0, 0, 0, 0, 0, 0, 0, 0, 32 | 0, 0, 0, 0, 0, 0, 0, 0, 33 | 0, 0, 0, 0, 0, 0, 0, CURVE_EQUATION_B_SINGLE as u8, 34 | ]); 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::CURVE_EQUATION_B; 39 | use hex_literal::hex; 40 | 41 | const CURVE_EQUATION_B_BYTES: [u8; 32] = 42 | hex!("0000000000000000000000000000000000000000000000000000000000000007"); 43 | 44 | #[test] 45 | fn verify_constants() { 46 | assert_eq!(CURVE_EQUATION_B.to_bytes(), CURVE_EQUATION_B_BYTES); 47 | } 48 | 49 | #[test] 50 | fn try_from_rng() { 51 | use crate::SecretKey; 52 | use rand::rngs::OsRng; 53 | let key = SecretKey::try_from_rng(&mut OsRng).unwrap(); 54 | 55 | // Sanity check 56 | assert!(!key.to_bytes().iter().all(|b| *b == 0)) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /bp384/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | #![doc = include_str!("../README.md")] 4 | #![doc( 5 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", 6 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" 7 | )] 8 | #![forbid(unsafe_code)] 9 | #![warn( 10 | clippy::mod_module_files, 11 | clippy::unwrap_used, 12 | missing_docs, 13 | rust_2018_idioms, 14 | unused_lifetimes, 15 | unused_qualifications 16 | )] 17 | 18 | pub mod r1; 19 | pub mod t1; 20 | 21 | #[cfg(feature = "arithmetic")] 22 | mod arithmetic; 23 | 24 | pub use crate::{r1::BrainpoolP384r1, t1::BrainpoolP384t1}; 25 | pub use elliptic_curve::{ 26 | self, 27 | bigint::{ArrayEncoding, U384}, 28 | }; 29 | 30 | #[cfg(feature = "arithmetic")] 31 | pub use crate::arithmetic::scalar::Scalar; 32 | 33 | #[cfg(feature = "pkcs8")] 34 | pub use elliptic_curve::pkcs8; 35 | 36 | #[cfg(feature = "arithmetic")] 37 | pub(crate) use crate::arithmetic::field::FieldElement; 38 | 39 | use elliptic_curve::{ 40 | array::{Array, typenum::U48}, 41 | bigint::Odd, 42 | }; 43 | 44 | /// Byte representation of a base/scalar field element of a given curve. 45 | pub type FieldBytes = Array; 46 | 47 | const ORDER_HEX: &str = "8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046565"; 48 | const ORDER: Odd = Odd::::from_be_hex(ORDER_HEX); 49 | 50 | fn decode_field_bytes(field_bytes: &FieldBytes) -> U384 { 51 | U384::from_be_byte_array(*field_bytes) 52 | } 53 | 54 | fn encode_field_bytes(uint: &U384) -> FieldBytes { 55 | uint.to_be_byte_array() 56 | } 57 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve/scalar_mul/window/wnaf.rs: -------------------------------------------------------------------------------- 1 | use crate::curve::twedwards::extended::ExtendedPoint; 2 | use crate::curve::twedwards::projective::ProjectiveNielsPoint; 3 | use subtle::{ConditionallySelectable, ConstantTimeEq}; 4 | 5 | pub struct LookupTable([ProjectiveNielsPoint; 8]); 6 | 7 | /// Precomputes odd multiples of the point passed in 8 | impl From<&ExtendedPoint> for LookupTable { 9 | fn from(P: &ExtendedPoint) -> LookupTable { 10 | let mut table = [P.to_projective_niels(); 8]; 11 | 12 | for i in 1..8 { 13 | table[i] = P 14 | .add_projective_niels(&table[i - 1]) 15 | .to_extended() 16 | .to_projective_niels(); 17 | } 18 | 19 | LookupTable(table) 20 | } 21 | } 22 | 23 | impl LookupTable { 24 | /// Selects a projective niels point from a lookup table in constant time 25 | pub fn select(&self, index: u32) -> ProjectiveNielsPoint { 26 | let mut result = ProjectiveNielsPoint::IDENTITY; 27 | 28 | for i in 1..9 { 29 | let swap = index.ct_eq(&(i as u32)); 30 | result.conditional_assign(&self.0[i - 1], swap); 31 | } 32 | result 33 | } 34 | } 35 | 36 | // XXX: Add back tests to ensure that select works correctly 37 | 38 | #[test] 39 | fn test_lookup() { 40 | let p = ExtendedPoint::GENERATOR; 41 | let points = LookupTable::from(&p); 42 | 43 | let mut expected_point = ExtendedPoint::IDENTITY; 44 | for i in 0..8 { 45 | let selected_point = points.select(i); 46 | assert_eq!(selected_point.to_extensible(), expected_point); 47 | 48 | expected_point = expected_point.add_extended(&p).to_extended(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /hash2curve/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: hash2curve 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Used by [RustCrypto] to implement hash2curve, [RFC9380], for elliptic curves. 11 | 12 | [Documentation][docs-link] 13 | 14 | ## License 15 | 16 | All crates licensed under either of: 17 | 18 | - [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 19 | - [MIT license](http://opensource.org/licenses/MIT) 20 | 21 | at your option. 22 | 23 | ### Contribution 24 | 25 | Unless you explicitly state otherwise, any contribution intentionally submitted 26 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 27 | dual licensed as above, without any additional terms or conditions. 28 | 29 | [//]: # (badges) 30 | 31 | [crate-image]: https://img.shields.io/crates/v/hash2curve?logo=rust 32 | [crate-link]: https://crates.io/crates/hash2curve 33 | [docs-image]: https://docs.rs/hash2curve/badge.svg 34 | [docs-link]: https://docs.rs/hash2curve/ 35 | [build-image]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/hash2curve.yml/badge.svg 36 | [build-link]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/hash2curve.yml 37 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 38 | [rustc-image]: https://img.shields.io/badge/rustc-1.81+-blue.svg 39 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 40 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260040-elliptic-curves 41 | 42 | [//]: # (links) 43 | 44 | [RFC9380]: https://www.rfc-editor.org/rfc/rfc9380.html 45 | [RustCrypto]: https://github.com/rustcrypto/ 46 | -------------------------------------------------------------------------------- /bignp256/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Pure Rust implementation of group operations on bign-curve256v1. 2 | //! 3 | //! Curve parameters can be found in STB 34.101.45-2013 4 | //! 5 | //! 6 | //! See table B.1: l = 128. 7 | 8 | pub(crate) mod field; 9 | pub(crate) mod scalar; 10 | 11 | pub use self::scalar::Scalar; 12 | 13 | pub use self::field::FieldElement; 14 | use crate::BignP256; 15 | pub use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 16 | pub use primeorder::{PrimeCurveParams, point_arithmetic}; 17 | 18 | /// Elliptic curve point in affine coordinates. 19 | pub type AffinePoint = primeorder::AffinePoint; 20 | 21 | /// Elliptic curve point in projective coordinates. 22 | pub type ProjectivePoint = primeorder::ProjectivePoint; 23 | 24 | impl CurveArithmetic for BignP256 { 25 | type AffinePoint = AffinePoint; 26 | type ProjectivePoint = ProjectivePoint; 27 | type Scalar = Scalar; 28 | } 29 | 30 | impl PrimeCurveArithmetic for BignP256 { 31 | type CurveGroup = ProjectivePoint; 32 | } 33 | 34 | impl PrimeCurveParams for BignP256 { 35 | type FieldElement = FieldElement; 36 | type PointArithmetic = point_arithmetic::EquationAIsGeneric; 37 | const EQUATION_A: Self::FieldElement = FieldElement::from_hex_vartime( 38 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40", 39 | ); 40 | const EQUATION_B: Self::FieldElement = FieldElement::from_hex_vartime( 41 | "77CE6C1515F3A8EDD2C13AABE4D8FBBE4CF55069978B9253B22E7D6BD69C03F1", 42 | ); 43 | const GENERATOR: (Self::FieldElement, Self::FieldElement) = ( 44 | FieldElement::ZERO, 45 | FieldElement::from_hex_vartime( 46 | "6BF7FC3CFB16D69F5CE4C9A351D6835D78913966C408F6521E29CF1804516A93", 47 | ), 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/primeorder.yml: -------------------------------------------------------------------------------- 1 | name: primeorder 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/primeorder.yml" 7 | - "primeorder/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | defaults: 13 | run: 14 | working-directory: primeorder 15 | 16 | env: 17 | CARGO_INCREMENTAL: 0 18 | RUSTFLAGS: "-Dwarnings" 19 | RUSTDOCFLAGS: "-Dwarnings" 20 | 21 | # Cancels CI jobs when new commits are pushed to a PR branch 22 | concurrency: 23 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 24 | cancel-in-progress: true 25 | 26 | jobs: 27 | build: 28 | runs-on: ubuntu-latest 29 | strategy: 30 | matrix: 31 | rust: 32 | - 1.85.0 # MSRV 33 | - stable 34 | target: 35 | - thumbv7em-none-eabi 36 | - wasm32-unknown-unknown 37 | steps: 38 | - uses: actions/checkout@v6 39 | - uses: dtolnay/rust-toolchain@master 40 | with: 41 | toolchain: ${{ matrix.rust }} 42 | targets: ${{ matrix.target }} 43 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features 44 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc 45 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features hash2curve 46 | 47 | test: 48 | runs-on: ubuntu-latest 49 | strategy: 50 | matrix: 51 | rust: 52 | - 1.85.0 # MSRV 53 | - stable 54 | steps: 55 | - uses: actions/checkout@v6 56 | - uses: dtolnay/rust-toolchain@master 57 | with: 58 | toolchain: ${{ matrix.rust }} 59 | - run: cargo check --all-features 60 | - run: cargo test --no-default-features 61 | - run: cargo test 62 | - run: cargo test --all-features 63 | -------------------------------------------------------------------------------- /bp256/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Brainpool P-256 elliptic curves 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Brainpool P-256 (brainpoolP256r1 and brainpoolP256t1) elliptic curve types 11 | implemented in terms of traits from the [`elliptic-curve`] crate. 12 | 13 | [Documentation][docs-link] 14 | 15 | ## License 16 | 17 | All crates licensed under either of 18 | 19 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 20 | * [MIT license](http://opensource.org/licenses/MIT) 21 | 22 | at your option. 23 | 24 | ### Contribution 25 | 26 | Unless you explicitly state otherwise, any contribution intentionally submitted 27 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 28 | dual licensed as above, without any additional terms or conditions. 29 | 30 | [//]: # (badges) 31 | 32 | [crate-image]: https://img.shields.io/crates/v/bp256?logo=rust 33 | [crate-link]: https://crates.io/crates/bp256 34 | [docs-image]: https://docs.rs/bp256/badge.svg 35 | [docs-link]: https://docs.rs/bp256/ 36 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 37 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 38 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 39 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260040-elliptic-curves 40 | [build-image]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/bp256.yml/badge.svg 41 | [build-link]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/bp256.yml 42 | 43 | [//]: # (links) 44 | 45 | [RustCrypto]: https://github.com/rustcrypto/ 46 | [`elliptic-curve`]: https://github.com/RustCrypto/traits/tree/master/elliptic-curve 47 | -------------------------------------------------------------------------------- /bp256/src/r1/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP256r1 curve arithmetic implementation. 2 | 3 | use super::BrainpoolP256r1; 4 | use crate::{FieldElement, Scalar}; 5 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 6 | use primeorder::{PrimeCurveParams, point_arithmetic}; 7 | 8 | /// Elliptic curve point in affine coordinates. 9 | pub type AffinePoint = primeorder::AffinePoint; 10 | 11 | /// Elliptic curve point in projective coordinates. 12 | pub type ProjectivePoint = primeorder::ProjectivePoint; 13 | 14 | /// Primitive scalar type. 15 | pub type ScalarValue = elliptic_curve::ScalarValue; 16 | 17 | /// Non-zero scalar field element. 18 | pub type NonZeroScalar = elliptic_curve::NonZeroScalar; 19 | 20 | impl CurveArithmetic for BrainpoolP256r1 { 21 | type AffinePoint = AffinePoint; 22 | type ProjectivePoint = ProjectivePoint; 23 | type Scalar = Scalar; 24 | } 25 | 26 | impl PrimeCurveArithmetic for BrainpoolP256r1 { 27 | type CurveGroup = ProjectivePoint; 28 | } 29 | 30 | impl PrimeCurveParams for BrainpoolP256r1 { 31 | type FieldElement = FieldElement; 32 | type PointArithmetic = point_arithmetic::EquationAIsGeneric; 33 | 34 | const EQUATION_A: FieldElement = FieldElement::from_hex_vartime( 35 | "7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", 36 | ); 37 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 38 | "26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", 39 | ); 40 | const GENERATOR: (FieldElement, FieldElement) = ( 41 | FieldElement::from_hex_vartime( 42 | "8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262", 43 | ), 44 | FieldElement::from_hex_vartime( 45 | "547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997", 46 | ), 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /bp256/src/t1/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP256t1 curve arithmetic implementation. 2 | 3 | use super::BrainpoolP256t1; 4 | use crate::{FieldElement, Scalar}; 5 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 6 | use primeorder::{PrimeCurveParams, point_arithmetic}; 7 | 8 | /// Elliptic curve point in affine coordinates. 9 | pub type AffinePoint = primeorder::AffinePoint; 10 | 11 | /// Elliptic curve point in projective coordinates. 12 | pub type ProjectivePoint = primeorder::ProjectivePoint; 13 | 14 | /// Primitive scalar type. 15 | pub type ScalarValue = elliptic_curve::ScalarValue; 16 | 17 | /// Non-zero scalar field element. 18 | pub type NonZeroScalar = elliptic_curve::NonZeroScalar; 19 | 20 | impl CurveArithmetic for BrainpoolP256t1 { 21 | type AffinePoint = AffinePoint; 22 | type ProjectivePoint = ProjectivePoint; 23 | type Scalar = Scalar; 24 | } 25 | 26 | impl PrimeCurveArithmetic for BrainpoolP256t1 { 27 | type CurveGroup = ProjectivePoint; 28 | } 29 | 30 | impl PrimeCurveParams for BrainpoolP256t1 { 31 | type FieldElement = FieldElement; 32 | type PointArithmetic = point_arithmetic::EquationAIsGeneric; 33 | 34 | const EQUATION_A: FieldElement = FieldElement::from_hex_vartime( 35 | "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5374", 36 | ); 37 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 38 | "662c61c430d84ea4fe66a7733d0b76b7bf93ebc4af2f49256ae58101fee92b04", 39 | ); 40 | const GENERATOR: (FieldElement, FieldElement) = ( 41 | FieldElement::from_hex_vartime( 42 | "a3e8eb3cc1cfe7b7732213b23a656149afa142c47aafbc2b79a191562e1305f4", 43 | ), 44 | FieldElement::from_hex_vartime( 45 | "2d996c823439c56d7f7b22e14644417e69bcb6de39d027001dabe8f35b25c9be", 46 | ), 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /bp384/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Brainpool P-384 elliptic curves 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Brainpool P-384 (brainpoolP384r1 and brainpoolP384t1) elliptic curve types 11 | implemented in terms of traits from the [`elliptic-curve`] crate. 12 | 13 | [Documentation][docs-link] 14 | 15 | ## License 16 | 17 | All crates licensed under either of 18 | 19 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 20 | * [MIT license](http://opensource.org/licenses/MIT) 21 | 22 | at your option. 23 | 24 | ### Contribution 25 | 26 | Unless you explicitly state otherwise, any contribution intentionally submitted 27 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 28 | dual licensed as above, without any additional terms or conditions. 29 | 30 | [//]: # (badges) 31 | 32 | [crate-image]: https://img.shields.io/crates/v/bp384?logo=rust 33 | [crate-link]: https://crates.io/crates/bp384 34 | [docs-image]: https://docs.rs/bp384/badge.svg 35 | [docs-link]: https://docs.rs/bp384/ 36 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 37 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 38 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 39 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260040-elliptic-curves 40 | [build-image]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/bp384.yml/badge.svg 41 | [build-link]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/bp384.yml 42 | 43 | [//]: # (links) 44 | 45 | [RustCrypto]: https://github.com/rustcrypto/ 46 | [`elliptic-curve`]: https://github.com/RustCrypto/traits/tree/master/elliptic-curve 47 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/sign/error.rs: -------------------------------------------------------------------------------- 1 | use core::{ 2 | error::Error, 3 | fmt::{self, Display, Formatter}, 4 | }; 5 | 6 | /// Signing errors 7 | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] 8 | pub enum SigningError { 9 | /// Prehashed context length is invalid 10 | PrehashedContextLength, 11 | /// Public key bytes are invalid 12 | InvalidPublicKeyBytes, 13 | /// Signature S component is invalid 14 | InvalidSignatureSComponent, 15 | /// Signature R component is invalid 16 | InvalidSignatureRComponent, 17 | /// Signature length is invalid 18 | InvalidSignatureLength, 19 | /// Signature verification failed 20 | Verify, 21 | } 22 | 23 | impl Display for SigningError { 24 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 25 | match self { 26 | SigningError::PrehashedContextLength => { 27 | write!(f, "prehashed context length is invalid") 28 | } 29 | SigningError::InvalidPublicKeyBytes => write!(f, "public key bytes are invalid"), 30 | SigningError::InvalidSignatureSComponent => { 31 | write!(f, "signature S component is invalid") 32 | } 33 | SigningError::InvalidSignatureRComponent => { 34 | write!(f, "signature R component is invalid") 35 | } 36 | SigningError::InvalidSignatureLength => write!(f, "signature length is invalid"), 37 | SigningError::Verify => write!(f, "signature verification failed"), 38 | } 39 | } 40 | } 41 | 42 | impl Error for SigningError {} 43 | 44 | impl From for signature::Error { 45 | #[cfg(feature = "alloc")] 46 | fn from(err: SigningError) -> Self { 47 | signature::Error::from_source(err) 48 | } 49 | 50 | #[cfg(not(feature = "alloc"))] 51 | fn from(_err: SigningError) -> Self { 52 | signature::Error::new() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /primeorder/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", 5 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" 6 | )] 7 | #![forbid(unsafe_code)] 8 | #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] 9 | #![doc = include_str!("../README.md")] 10 | 11 | #[cfg(feature = "alloc")] 12 | #[macro_use] 13 | extern crate alloc; 14 | 15 | #[cfg(feature = "hash2curve")] 16 | pub mod osswu; 17 | pub mod point_arithmetic; 18 | 19 | mod affine; 20 | #[cfg(feature = "dev")] 21 | mod dev; 22 | mod projective; 23 | 24 | pub use crate::{affine::AffinePoint, projective::ProjectivePoint}; 25 | pub use elliptic_curve::{self, Field, FieldBytes, PrimeCurve, PrimeField, array, point::Double}; 26 | 27 | use elliptic_curve::{CurveArithmetic, ops::Invert, subtle::CtOption}; 28 | 29 | /// Parameters for elliptic curves of prime order which can be described by the 30 | /// short Weierstrass equation. 31 | pub trait PrimeCurveParams: 32 | PrimeCurve 33 | + CurveArithmetic 34 | + CurveArithmetic> 35 | + CurveArithmetic> 36 | { 37 | /// Base field element type. 38 | type FieldElement: PrimeField> 39 | + Invert>; 40 | 41 | /// [Point arithmetic](point_arithmetic) implementation, might be optimized for this specific curve 42 | type PointArithmetic: point_arithmetic::PointArithmetic; 43 | 44 | /// Coefficient `a` in the curve equation. 45 | const EQUATION_A: Self::FieldElement; 46 | 47 | /// Coefficient `b` in the curve equation. 48 | const EQUATION_B: Self::FieldElement; 49 | 50 | /// Generator point's affine coordinates: (x, y). 51 | const GENERATOR: (Self::FieldElement, Self::FieldElement); 52 | } 53 | -------------------------------------------------------------------------------- /bignp256/benches/field.rs: -------------------------------------------------------------------------------- 1 | //! bign-curve256v1 field element benchmarks 2 | 3 | use bignp256::arithmetic::FieldElement; 4 | use criterion::{ 5 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 6 | }; 7 | use hex_literal::hex; 8 | 9 | fn test_field_element_x() -> FieldElement { 10 | FieldElement::from_bytes( 11 | &hex!("1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83").into(), 12 | ) 13 | .unwrap() 14 | } 15 | 16 | fn test_field_element_y() -> FieldElement { 17 | FieldElement::from_bytes( 18 | &hex!("ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9").into(), 19 | ) 20 | .unwrap() 21 | } 22 | 23 | fn bench_field_element_mul(group: &mut BenchmarkGroup) { 24 | let x = test_field_element_x(); 25 | let y = test_field_element_y(); 26 | group.bench_function("mul", |b| b.iter(|| x * y)); 27 | } 28 | 29 | fn bench_field_element_square(group: &mut BenchmarkGroup) { 30 | let x = test_field_element_x(); 31 | group.bench_function("square", |b| b.iter(|| x.square())); 32 | } 33 | 34 | fn bench_field_element_sqrt(group: &mut BenchmarkGroup) { 35 | let x = test_field_element_x(); 36 | group.bench_function("sqrt", |b| b.iter(|| x.sqrt())); 37 | } 38 | 39 | fn bench_field_element_invert(group: &mut BenchmarkGroup) { 40 | let x = test_field_element_x(); 41 | group.bench_function("invert", |b| b.iter(|| x.invert())); 42 | } 43 | 44 | fn bench_field_element(c: &mut Criterion) { 45 | let mut group = c.benchmark_group("field element operations"); 46 | bench_field_element_mul(&mut group); 47 | bench_field_element_square(&mut group); 48 | bench_field_element_invert(&mut group); 49 | bench_field_element_sqrt(&mut group); 50 | group.finish(); 51 | } 52 | 53 | criterion_group!(benches, bench_field_element); 54 | criterion_main!(benches); 55 | -------------------------------------------------------------------------------- /p256/benches/field.rs: -------------------------------------------------------------------------------- 1 | //! secp256r1 field element benchmarks 2 | 3 | use criterion::{ 4 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 5 | }; 6 | use elliptic_curve::array::Array; 7 | use hex_literal::hex; 8 | use p256::FieldElement; 9 | 10 | fn test_field_element_x() -> FieldElement { 11 | FieldElement::from_bytes(&Array(hex!( 12 | "1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83" 13 | ))) 14 | .unwrap() 15 | } 16 | 17 | fn test_field_element_y() -> FieldElement { 18 | FieldElement::from_bytes(&Array(hex!( 19 | "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9" 20 | ))) 21 | .unwrap() 22 | } 23 | 24 | fn bench_field_element_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 25 | let x = test_field_element_x(); 26 | let y = test_field_element_y(); 27 | group.bench_function("mul", |b| b.iter(|| &x * &y)); 28 | } 29 | 30 | fn bench_field_element_square<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 31 | let x = test_field_element_x(); 32 | group.bench_function("square", |b| b.iter(|| x.square())); 33 | } 34 | 35 | fn bench_field_element_sqrt<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 36 | let x = test_field_element_x(); 37 | group.bench_function("sqrt", |b| b.iter(|| x.sqrt())); 38 | } 39 | 40 | fn bench_field_element_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 41 | let x = test_field_element_x(); 42 | group.bench_function("invert", |b| b.iter(|| x.invert())); 43 | } 44 | 45 | fn bench_field_element(c: &mut Criterion) { 46 | let mut group = c.benchmark_group("field element operations"); 47 | bench_field_element_mul(&mut group); 48 | bench_field_element_square(&mut group); 49 | bench_field_element_invert(&mut group); 50 | bench_field_element_sqrt(&mut group); 51 | group.finish(); 52 | } 53 | 54 | criterion_group!(benches, bench_field_element); 55 | criterion_main!(benches); 56 | -------------------------------------------------------------------------------- /bp384/src/r1/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP384r1 curve arithmetic implementation. 2 | 3 | use super::BrainpoolP384r1; 4 | use crate::{FieldElement, Scalar}; 5 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 6 | use primeorder::{PrimeCurveParams, point_arithmetic}; 7 | 8 | /// Elliptic curve point in affine coordinates. 9 | pub type AffinePoint = primeorder::AffinePoint; 10 | 11 | /// Elliptic curve point in projective coordinates. 12 | pub type ProjectivePoint = primeorder::ProjectivePoint; 13 | 14 | /// Primitive scalar type. 15 | pub type ScalarValue = elliptic_curve::ScalarValue; 16 | 17 | /// Non-zero scalar field element. 18 | pub type NonZeroScalar = elliptic_curve::NonZeroScalar; 19 | 20 | impl CurveArithmetic for BrainpoolP384r1 { 21 | type AffinePoint = AffinePoint; 22 | type ProjectivePoint = ProjectivePoint; 23 | type Scalar = Scalar; 24 | } 25 | 26 | impl PrimeCurveArithmetic for BrainpoolP384r1 { 27 | type CurveGroup = ProjectivePoint; 28 | } 29 | 30 | impl PrimeCurveParams for BrainpoolP384r1 { 31 | type FieldElement = FieldElement; 32 | type PointArithmetic = point_arithmetic::EquationAIsGeneric; 33 | 34 | const EQUATION_A: FieldElement = FieldElement::from_hex_vartime( 35 | "7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd22ce2826", 36 | ); 37 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 38 | "04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696fa504c11", 39 | ); 40 | const GENERATOR: (FieldElement, FieldElement) = ( 41 | FieldElement::from_hex_vartime( 42 | "1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e247d4af1e", 43 | ), 44 | FieldElement::from_hex_vartime( 45 | "8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341263c5315", 46 | ), 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /bp384/src/t1/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP384t1 curve arithmetic implementation. 2 | 3 | use super::BrainpoolP384t1; 4 | use crate::{FieldElement, Scalar}; 5 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 6 | use primeorder::{PrimeCurveParams, point_arithmetic}; 7 | 8 | /// Elliptic curve point in affine coordinates. 9 | pub type AffinePoint = primeorder::AffinePoint; 10 | 11 | /// Elliptic curve point in projective coordinates. 12 | pub type ProjectivePoint = primeorder::ProjectivePoint; 13 | 14 | /// Primitive scalar type. 15 | pub type ScalarValue = elliptic_curve::ScalarValue; 16 | 17 | /// Non-zero scalar field element. 18 | pub type NonZeroScalar = elliptic_curve::NonZeroScalar; 19 | 20 | impl CurveArithmetic for BrainpoolP384t1 { 21 | type AffinePoint = AffinePoint; 22 | type ProjectivePoint = ProjectivePoint; 23 | type Scalar = Scalar; 24 | } 25 | 26 | impl PrimeCurveArithmetic for BrainpoolP384t1 { 27 | type CurveGroup = ProjectivePoint; 28 | } 29 | 30 | impl PrimeCurveParams for BrainpoolP384t1 { 31 | type FieldElement = FieldElement; 32 | type PointArithmetic = point_arithmetic::EquationAIsGeneric; 33 | 34 | const EQUATION_A: FieldElement = FieldElement::from_hex_vartime( 35 | "8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec50", 36 | ); 37 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 38 | "7f519eada7bda81bd826dba647910f8c4b9346ed8ccdc64e4b1abd11756dce1d2074aa263b88805ced70355a33b471ee", 39 | ); 40 | const GENERATOR: (FieldElement, FieldElement) = ( 41 | FieldElement::from_hex_vartime( 42 | "18de98b02db9a306f2afcd7235f72a819b80ab12ebd653172476fecd462aabffc4ff191b946a5f54d8d0aa2f418808cc", 43 | ), 44 | FieldElement::from_hex_vartime( 45 | "25ab056962d30651a114afd2755ad336747f93475b7a1fca3b88f2b6a208ccfe469408584dc2b2912675bf5b9e582928", 46 | ), 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /k256/benches/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! secp256k1 scalar arithmetic benchmarks 2 | 3 | use criterion::{Criterion, criterion_group, criterion_main}; 4 | use k256::{ 5 | FieldBytes, NonZeroScalar, Scalar, 6 | ecdsa::{ 7 | Signature, SigningKey, 8 | signature::hazmat::{PrehashSigner, PrehashVerifier}, 9 | }, 10 | elliptic_curve::group::ff::PrimeField, 11 | }; 12 | use std::hint::black_box; 13 | 14 | fn test_scalar_d() -> NonZeroScalar { 15 | NonZeroScalar::new( 16 | Scalar::from_repr( 17 | [ 18 | 0xbb, 0x48, 0x8a, 0xef, 0x41, 0x6a, 0x41, 0xd7, 0x68, 0x0d, 0x1c, 0xf0, 0x1d, 0x70, 19 | 0xf5, 0x9b, 0x60, 0xd7, 0xf5, 0xf7, 0x7e, 0x30, 0xe7, 0x8b, 0x8b, 0xf9, 0xd2, 0xd8, 20 | 0x82, 0xf1, 0x56, 0xa6, 21 | ] 22 | .into(), 23 | ) 24 | .unwrap(), 25 | ) 26 | .unwrap() 27 | } 28 | 29 | fn test_scalar_z() -> FieldBytes { 30 | [ 31 | 0xe3, 0x35, 0x80, 0xeb, 0x6e, 0xd0, 0x22, 0xae, 0xd6, 0xaf, 0x20, 0xd9, 0x22, 0x37, 0x63, 32 | 0x5e, 0x7c, 0x20, 0xc5, 0xf1, 0xbc, 0xd6, 0xae, 0xe8, 0x81, 0x82, 0xed, 0x71, 0x80, 0xf6, 33 | 0xe2, 0x67, 34 | ] 35 | .into() 36 | } 37 | 38 | fn bench_ecdsa(c: &mut Criterion) { 39 | let mut group = c.benchmark_group("ecdsa"); 40 | 41 | let d = SigningKey::from(test_scalar_d()); 42 | let z = test_scalar_z(); 43 | 44 | group.bench_function("try_sign_prehashed", |b| { 45 | b.iter(|| { 46 | let _: Signature = black_box(&d).sign_prehash(&black_box(z)).unwrap(); 47 | }) 48 | }); 49 | 50 | let q = d.verifying_key(); 51 | let s: Signature = d.sign_prehash(&z).unwrap(); 52 | 53 | group.bench_function("verify_prehashed", |b| { 54 | b.iter(|| { 55 | black_box(q) 56 | .verify_prehash(&black_box(z), &black_box(s)) 57 | .unwrap() 58 | }) 59 | }); 60 | 61 | group.finish(); 62 | } 63 | 64 | criterion_group!(benches, bench_ecdsa); 65 | criterion_main!(benches); 66 | -------------------------------------------------------------------------------- /p224/src/ecdh.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Diffie-Hellman (Ephemeral) Support. 2 | //! 3 | //! This module contains a high-level interface for performing ephemeral 4 | //! Diffie-Hellman key exchanges using the secp224r1 elliptic curve. 5 | //! 6 | //! # Usage 7 | //! 8 | //! This usage example is from the perspective of two participants in the 9 | //! exchange, nicknamed "Alice" and "Bob". 10 | //! 11 | //! ``` 12 | //! use p224::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; 13 | //! use rand::rngs::OsRng; 14 | //! 15 | //! // Alice 16 | //! let alice_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 17 | //! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); 18 | //! 19 | //! // Bob 20 | //! let bob_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 21 | //! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); 22 | //! 23 | //! // Alice decodes Bob's serialized public key and computes a shared secret from it 24 | //! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref()) 25 | //! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! 26 | //! 27 | //! let alice_shared = alice_secret.diffie_hellman(&bob_public); 28 | //! 29 | //! // Bob decodes Alice's serialized public key and computes the same shared secret 30 | //! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) 31 | //! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! 32 | //! 33 | //! let bob_shared = bob_secret.diffie_hellman(&alice_public); 34 | //! 35 | //! // Both participants arrive on the same shared secret 36 | //! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); 37 | //! ``` 38 | 39 | pub use elliptic_curve::ecdh::diffie_hellman; 40 | 41 | use crate::NistP224; 42 | 43 | /// NIST P-224 Ephemeral Diffie-Hellman Secret. 44 | pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; 45 | 46 | /// Shared secret value computed via ECDH key agreement. 47 | pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; 48 | -------------------------------------------------------------------------------- /p256/src/ecdh.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Diffie-Hellman (Ephemeral) Support. 2 | //! 3 | //! This module contains a high-level interface for performing ephemeral 4 | //! Diffie-Hellman key exchanges using the secp256r1 elliptic curve. 5 | //! 6 | //! # Usage 7 | //! 8 | //! This usage example is from the perspective of two participants in the 9 | //! exchange, nicknamed "Alice" and "Bob". 10 | //! 11 | //! ``` 12 | //! use p256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; 13 | //! use rand::rngs::OsRng; 14 | //! 15 | //! // Alice 16 | //! let alice_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 17 | //! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); 18 | //! 19 | //! // Bob 20 | //! let bob_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 21 | //! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); 22 | //! 23 | //! // Alice decodes Bob's serialized public key and computes a shared secret from it 24 | //! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref()) 25 | //! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! 26 | //! 27 | //! let alice_shared = alice_secret.diffie_hellman(&bob_public); 28 | //! 29 | //! // Bob decodes Alice's serialized public key and computes the same shared secret 30 | //! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) 31 | //! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! 32 | //! 33 | //! let bob_shared = bob_secret.diffie_hellman(&alice_public); 34 | //! 35 | //! // Both participants arrive on the same shared secret 36 | //! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); 37 | //! ``` 38 | 39 | pub use elliptic_curve::ecdh::diffie_hellman; 40 | 41 | use crate::NistP256; 42 | 43 | /// NIST P-256 Ephemeral Diffie-Hellman Secret. 44 | pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; 45 | 46 | /// Shared secret value computed via ECDH key agreement. 47 | pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; 48 | -------------------------------------------------------------------------------- /p384/src/ecdh.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Diffie-Hellman (Ephemeral) Support. 2 | //! 3 | //! This module contains a high-level interface for performing ephemeral 4 | //! Diffie-Hellman key exchanges using the secp384r1 elliptic curve. 5 | //! 6 | //! # Usage 7 | //! 8 | //! This usage example is from the perspective of two participants in the 9 | //! exchange, nicknamed "Alice" and "Bob". 10 | //! 11 | //! ``` 12 | //! use p384::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; 13 | //! use rand::rngs::OsRng; 14 | //! 15 | //! // Alice 16 | //! let alice_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 17 | //! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); 18 | //! 19 | //! // Bob 20 | //! let bob_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 21 | //! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); 22 | //! 23 | //! // Alice decodes Bob's serialized public key and computes a shared secret from it 24 | //! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref()) 25 | //! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! 26 | //! 27 | //! let alice_shared = alice_secret.diffie_hellman(&bob_public); 28 | //! 29 | //! // Bob decodes Alice's serialized public key and computes the same shared secret 30 | //! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) 31 | //! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! 32 | //! 33 | //! let bob_shared = bob_secret.diffie_hellman(&alice_public); 34 | //! 35 | //! // Both participants arrive on the same shared secret 36 | //! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); 37 | //! ``` 38 | 39 | pub use elliptic_curve::ecdh::diffie_hellman; 40 | 41 | use crate::NistP384; 42 | 43 | /// NIST P-384 Ephemeral Diffie-Hellman Secret. 44 | pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; 45 | 46 | /// Shared secret value computed via ECDH key agreement. 47 | pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; 48 | -------------------------------------------------------------------------------- /p521/src/ecdh.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Diffie-Hellman (Ephemeral) Support. 2 | //! 3 | //! This module contains a high-level interface for performing ephemeral 4 | //! Diffie-Hellman key exchanges using the secp521r1 elliptic curve. 5 | //! 6 | //! # Usage 7 | //! 8 | //! This usage example is from the perspective of two participants in the 9 | //! exchange, nicknamed "Alice" and "Bob". 10 | //! 11 | //! ``` 12 | //! use p521::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; 13 | //! use rand::{rngs::OsRng, TryRngCore}; 14 | //! 15 | //! // Alice 16 | //! let alice_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 17 | //! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); 18 | //! 19 | //! // Bob 20 | //! let bob_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 21 | //! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); 22 | //! 23 | //! // Alice decodes Bob's serialized public key and computes a shared secret from it 24 | //! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref()) 25 | //! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! 26 | //! 27 | //! let alice_shared = alice_secret.diffie_hellman(&bob_public); 28 | //! 29 | //! // Bob decodes Alice's serialized public key and computes the same shared secret 30 | //! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) 31 | //! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! 32 | //! 33 | //! let bob_shared = bob_secret.diffie_hellman(&alice_public); 34 | //! 35 | //! // Both participants arrive on the same shared secret 36 | //! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); 37 | //! ``` 38 | 39 | pub use elliptic_curve::ecdh::diffie_hellman; 40 | 41 | use crate::NistP521; 42 | 43 | /// NIST P-521 Ephemeral Diffie-Hellman Secret. 44 | pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; 45 | 46 | /// Shared secret value computed via ECDH key agreement. 47 | pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; 48 | -------------------------------------------------------------------------------- /bignp256/tests/dsa.rs: -------------------------------------------------------------------------------- 1 | //! bignp256 DSA Tests 2 | 3 | #![cfg(feature = "ecdsa")] 4 | 5 | use elliptic_curve::ops::Reduce; 6 | use hex_literal::hex; 7 | use proptest::prelude::*; 8 | 9 | use bignp256::{ 10 | FieldBytes, NonZeroScalar, Scalar, 11 | ecdsa::{ 12 | Signature, SigningKey, VerifyingKey, 13 | signature::{Signer, Verifier}, 14 | }, 15 | }; 16 | 17 | const PUBLIC_KEY: [u8; 64] = hex!( 18 | "BD1A5650 179D79E0 3FCEE49D 4C2BD5DD F54CE46D 0CF11E4F F87BF7A8 90857FD0" 19 | "7AC6A603 61E8C817 3491686D 461B2826 190C2EDA 5909054A 9AB84D2A B9D99A90" 20 | ); 21 | 22 | const MSG: &[u8] = b"testing"; 23 | const SIG: [u8; 48] = hex!( 24 | "63F59C523FF1780851143114FFBC5C13" 25 | "9BE81FF88F9D7F7FE209A6914198044C2A41D37B8439AAB42983FDB04AC2C326" 26 | ); 27 | 28 | #[test] 29 | fn verify_test_vector() { 30 | let vk = VerifyingKey::from_bytes(&PUBLIC_KEY).unwrap(); 31 | let sig = Signature::try_from(&SIG).unwrap(); 32 | assert!(vk.verify(MSG, &sig).is_ok()); 33 | } 34 | 35 | prop_compose! { 36 | fn signing_key()(bytes in any::<[u8; 32]>()) -> SigningKey { 37 | loop { 38 | let scalar = >::reduce(&bytes.into()); 39 | if let Some(scalar) = Option::from(NonZeroScalar::new(scalar)) { 40 | return SigningKey::from_nonzero_scalar(scalar).unwrap(); 41 | } 42 | } 43 | } 44 | } 45 | 46 | proptest! { 47 | #[test] 48 | fn sign_and_verify(sk in signing_key()) { 49 | let signature = sk.sign(MSG); 50 | prop_assert!(sk.verifying_key().verify(MSG, &signature).is_ok()); 51 | } 52 | 53 | #[test] 54 | fn reject_invalid_signature(sk in signing_key(), byte in 0usize..32, bit in 0usize..8) { 55 | let mut signature_bytes = sk.sign(MSG).to_bytes(); 56 | 57 | // tweak signature to make it invalid 58 | signature_bytes[byte] ^= 1 << bit; 59 | 60 | let signature = Signature::from_bytes(&signature_bytes).unwrap(); 61 | prop_assert!(sk.verifying_key().verify(MSG, &signature).is_err()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /p384/benches/field.rs: -------------------------------------------------------------------------------- 1 | //! secp384r1 field element benchmarks 2 | 3 | use core::hint::black_box; 4 | use criterion::{ 5 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 6 | }; 7 | use hex_literal::hex; 8 | use p384::{FieldElement, elliptic_curve::ff::Field}; 9 | 10 | fn test_field_element_x() -> FieldElement { 11 | black_box(FieldElement::from_bytes( 12 | &hex!("c2b47944fb5de342d03285880177ca5f7d0f2fcad7678cce4229d6e1932fcac11bfc3c3e97d942a3c56bf34123013dbf").into() 13 | ) 14 | .unwrap()) 15 | } 16 | 17 | fn test_field_element_y() -> FieldElement { 18 | FieldElement::from_bytes( 19 | &hex!("37257906a8223866eda0743c519616a76a758ae58aee81c5fd35fbf3a855b7754a36d4a0672df95d6c44a81cf7620c2d").into() 20 | ) 21 | .unwrap() 22 | } 23 | 24 | fn bench_field_element_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 25 | let x = test_field_element_x(); 26 | let y = test_field_element_y(); 27 | group.bench_function("mul", |b| b.iter(|| &x * &y)); 28 | } 29 | 30 | fn bench_field_element_square<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 31 | let x = test_field_element_x(); 32 | group.bench_function("square", |b| b.iter(|| x.square())); 33 | } 34 | 35 | fn bench_field_element_sqrt<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 36 | let x = test_field_element_x(); 37 | group.bench_function("sqrt", |b| b.iter(|| x.sqrt())); 38 | } 39 | 40 | fn bench_field_element_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 41 | let x = test_field_element_x(); 42 | group.bench_function("invert", |b| b.iter(|| x.invert())); 43 | } 44 | 45 | fn bench_field_element(c: &mut Criterion) { 46 | let mut group = c.benchmark_group("field element operations"); 47 | bench_field_element_mul(&mut group); 48 | bench_field_element_square(&mut group); 49 | bench_field_element_invert(&mut group); 50 | bench_field_element_sqrt(&mut group); 51 | group.finish(); 52 | } 53 | 54 | criterion_group!(benches, bench_field_element); 55 | criterion_main!(benches); 56 | -------------------------------------------------------------------------------- /x448/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: X448 Diffie-Hellman 2 | 3 | [![Crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | THIS CODE HAS NOT BEEN AUDITED OR REVIEWED. USE AT YOUR OWN RISK. 11 | 12 | ## About 13 | 14 | This crate provides a pure Rust implementation of X448, the Diffie-Hellman 15 | function for the Ed448-Goldilocks elliptic curve, providing public key 16 | cryptography for symmetric key exchange/agreement. 17 | 18 | Companion library to [`ed448-goldilocks`]. 19 | 20 | ## License 21 | 22 | All crates licensed under either of 23 | 24 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 25 | * [MIT license](http://opensource.org/licenses/MIT) 26 | 27 | at your option. 28 | 29 | ### Contribution 30 | 31 | Unless you explicitly state otherwise, any contribution intentionally submitted 32 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 33 | dual licensed as above, without any additional terms or conditions. 34 | 35 | [//]: # (badges) 36 | 37 | [crate-image]: https://img.shields.io/crates/v/ed448-goldilocks?logo=rust 38 | [crate-link]: https://crates.io/crates/ed448-goldilocks 39 | [docs-image]: https://docs.rs/ed448-goldilocks/badge.svg 40 | [docs-link]: https://docs.rs/ed448-goldilocks/ 41 | [build-image]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/ed448-goldilocks.yml/badge.svg 42 | [build-link]: https://github.com/RustCrypto/elliptic-curves/actions/workflows/ed448-goldilocks.yml 43 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 44 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 45 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 46 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260040-elliptic-curves 47 | 48 | [//]: # (links) 49 | 50 | [RustCrypto]: https://github.com/RustCrypto 51 | [`ed448-goldilocks`]: https://docs.rs/ed448-goldilocks/ 52 | -------------------------------------------------------------------------------- /p192/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "p192" 3 | version = "0.14.0-rc.1" 4 | description = """ 5 | Pure Rust implementation of the NIST P-192 (a.k.a. secp192r1) elliptic curve 6 | as defined in SP 800-186 7 | """ 8 | authors = ["RustCrypto Developers"] 9 | license = "Apache-2.0 OR MIT" 10 | documentation = "https://docs.rs/p192" 11 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/p192" 12 | repository = "https://github.com/RustCrypto/elliptic-curves" 13 | readme = "README.md" 14 | categories = ["cryptography", "no-std"] 15 | keywords = ["crypto", "ecc", "nist", "secp192r1"] 16 | edition = "2024" 17 | rust-version = "1.85" 18 | 19 | [dependencies] 20 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["sec1"] } 21 | 22 | # optional dependencies 23 | ecdsa-core = { version = "0.17.0-rc.9", package = "ecdsa", optional = true, default-features = false, features = ["der"] } 24 | hex-literal = { version = "1", optional = true } 25 | primefield = { version = "0.14.0-rc.1", optional = true } 26 | primeorder = { version = "0.14.0-rc.1", optional = true } 27 | serdect = { version = "0.4", optional = true, default-features = false } 28 | 29 | [dev-dependencies] 30 | ecdsa-core = { version = "0.17.0-rc.9", package = "ecdsa", default-features = false, features = ["dev"] } 31 | hex-literal = "1" 32 | primeorder = { version = "0.14.0-rc.1", features = ["dev"] } 33 | 34 | [features] 35 | default = ["arithmetic", "ecdsa", "pem", "std"] 36 | alloc = ["elliptic-curve/alloc", "primeorder?/alloc"] 37 | std = ["alloc", "elliptic-curve/std", "getrandom"] 38 | 39 | arithmetic = ["dep:primefield", "dep:primeorder", "elliptic-curve/arithmetic"] 40 | bits = ["arithmetic", "elliptic-curve/bits"] 41 | digest = ["ecdsa-core/digest", "ecdsa-core/hazmat"] 42 | ecdsa = ["arithmetic", "ecdsa-core/algorithm"] 43 | getrandom = ["ecdsa-core?/getrandom", "elliptic-curve/getrandom"] 44 | pem = ["elliptic-curve/pem", "pkcs8"] 45 | pkcs8 = ["elliptic-curve/pkcs8"] 46 | serde = ["elliptic-curve/serde", "primeorder?/serde", "serdect"] 47 | test-vectors = ["hex-literal"] 48 | 49 | [package.metadata.docs.rs] 50 | all-features = true 51 | -------------------------------------------------------------------------------- /p521/benches/field.rs: -------------------------------------------------------------------------------- 1 | //! secp521r1 field element benchmarks 2 | 3 | use criterion::{ 4 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 5 | }; 6 | use elliptic_curve::array::Array; 7 | use hex_literal::hex; 8 | use p521::FieldElement; 9 | use std::hint::black_box; 10 | 11 | fn test_field_element_x() -> FieldElement { 12 | black_box(FieldElement::from_bytes( 13 | &Array(hex!("01a7596d38aac7868327ddc1ef5e8178cf052b7ebc512828e8a45955d85bef49494d15278198bbcc5454358c12a2af9a3874e7002e1a2f02fcb36ff3e3b4bc0c69e7")) 14 | ) 15 | .unwrap()) 16 | } 17 | 18 | fn test_field_element_y() -> FieldElement { 19 | black_box(FieldElement::from_bytes( 20 | &Array(hex!("0184902e515982bb225b8c84f245e61b327c08e94d41c07d0b4101a963e02fe52f6a9f33e8b1de2394e0cb74c40790b4e489b5500e6804cabed0fe8c192443d4027b")) 21 | ) 22 | .unwrap()) 23 | } 24 | 25 | fn bench_field_element_mul<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 26 | let x = test_field_element_x(); 27 | let y = test_field_element_y(); 28 | group.bench_function("mul", |b| b.iter(|| &x * &y)); 29 | } 30 | 31 | fn bench_field_element_square<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 32 | let x = test_field_element_x(); 33 | group.bench_function("square", |b| b.iter(|| x.square())); 34 | } 35 | 36 | fn bench_field_element_sqrt<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 37 | let x = test_field_element_x(); 38 | group.bench_function("sqrt", |b| b.iter(|| x.sqrt())); 39 | } 40 | 41 | fn bench_field_element_invert<'a, M: Measurement>(group: &mut BenchmarkGroup<'a, M>) { 42 | let x = test_field_element_x(); 43 | group.bench_function("invert", |b| b.iter(|| x.invert())); 44 | } 45 | 46 | fn bench_field_element(c: &mut Criterion) { 47 | let mut group = c.benchmark_group("field element operations"); 48 | bench_field_element_mul(&mut group); 49 | bench_field_element_square(&mut group); 50 | bench_field_element_invert(&mut group); 51 | bench_field_element_sqrt(&mut group); 52 | group.finish(); 53 | } 54 | 55 | criterion_group!(benches, bench_field_element); 56 | criterion_main!(benches); 57 | -------------------------------------------------------------------------------- /ed448-goldilocks/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ed448-goldilocks" 3 | version = "0.14.0-pre.4" 4 | authors = ["RustCrypto Developers"] 5 | categories = ["cryptography"] 6 | keywords = ["cryptography", "decaf", "ed448", "ed448-goldilocks"] 7 | homepage = "https://docs.rs/ed448-goldilocks/" 8 | repository = "https://github.com/RustCrypto/elliptic-curves/tree/master/ed448-goldilocks" 9 | documentation = "https://docs.rs/ed448-goldilocks" 10 | license = "Apache-2.0 OR MIT" 11 | edition = "2024" 12 | rust-version = "1.85" 13 | readme = "README.md" 14 | description = """A pure-Rust implementation of Ed448 and Curve448 and Decaf. 15 | This crate also includes signing and verifying of Ed448 signatures. 16 | """ 17 | 18 | [dependencies] 19 | elliptic-curve = { version = "0.14.0-rc.17", features = ["arithmetic", "pkcs8"] } 20 | hash2curve = "0.14.0-rc.4" 21 | rand_core = { version = "0.10.0-rc-2", default-features = false } 22 | sha3 = { version = "0.11.0-rc.3", default-features = false } 23 | subtle = { version = "2.6", default-features = false } 24 | 25 | # optional dependencies 26 | ed448 = { version = "0.5.0-rc.2", optional = true, default-features = false } 27 | serdect = { version = "0.4", optional = true } 28 | signature = { version = "3.0.0-rc.5", optional = true, default-features = false, features = ["digest", "rand_core"] } 29 | 30 | [dev-dependencies] 31 | criterion = { version = "0.7", default-features = false, features = ["cargo_bench_support"] } 32 | hex-literal = "1" 33 | hex = "0.4" 34 | proptest = { version = "1", features = ["attr-macro"] } 35 | rand = "0.10.0-rc.1" 36 | chacha20 = "0.10.0-rc.3" 37 | serde_bare = "0.5" 38 | serde_json = "1.0" 39 | 40 | [features] 41 | default = ["std", "signing", "pkcs8"] 42 | alloc = ["ed448?/alloc", "elliptic-curve/alloc", "serdect?/alloc", "signature?/alloc"] 43 | std = ["alloc", "getrandom"] 44 | 45 | bits = ["elliptic-curve/bits"] 46 | getrandom = ["elliptic-curve/getrandom"] 47 | pkcs8 = ["ed448?/pkcs8", "elliptic-curve/pkcs8"] 48 | signing = ["dep:ed448", "dep:signature"] 49 | serde = ["dep:serdect", "ed448?/serde_bytes"] 50 | 51 | [[bench]] 52 | harness = false 53 | name = "bench" 54 | 55 | [package.metadata.docs.rs] 56 | all-features = true 57 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/field.rs: -------------------------------------------------------------------------------- 1 | mod element; 2 | mod scalar; 3 | 4 | pub(crate) use element::*; 5 | pub(crate) use scalar::CurveWithScalar; 6 | pub use scalar::{MODULUS_LIMBS, ORDER, Scalar, ScalarBytes, WIDE_ORDER, WideScalarBytes}; 7 | 8 | use crate::curve::twedwards::extended::ExtendedPoint as TwExtendedPoint; 9 | use crate::edwards::EdwardsPoint; 10 | 11 | use elliptic_curve::bigint::{ 12 | U448, const_monty_params, 13 | modular::{ConstMontyForm, ConstMontyParams}, 14 | }; 15 | 16 | const_monty_params!( 17 | MODULUS, 18 | U448, 19 | "fffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff" 20 | ); 21 | pub(crate) type ConstMontyType = ConstMontyForm; 22 | 23 | pub const GOLDILOCKS_BASE_POINT: EdwardsPoint = EdwardsPoint { 24 | X: FieldElement(ConstMontyType::new(&U448::from_be_hex( 25 | "4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e", 26 | ))), 27 | Y: FieldElement(ConstMontyType::new(&U448::from_be_hex( 28 | "693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14", 29 | ))), 30 | Z: FieldElement::ONE, 31 | T: FieldElement(ConstMontyType::new(&U448::from_be_hex( 32 | "c75eb58aee221c6ccec39d2d508d91c9c5056a183f8451d260d71667e2356d58f179de90b5b27da1f78fa07d85662d1deb06624e82af95f3", 33 | ))), 34 | }; 35 | 36 | pub const TWISTED_EDWARDS_BASE_POINT: TwExtendedPoint = TwExtendedPoint { 37 | X: FieldElement(ConstMontyType::new(&U448::from_be_hex( 38 | "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffe80000000000000000000000000000000000000000000000000000000", 39 | ))), 40 | Y: FieldElement(ConstMontyType::new(&U448::from_be_hex( 41 | "8508de14f04286d48d06c13078ca240805264370504c74c393d5242c5045271414181844d73f48e5199b0c1e3ab470a1c86079b4dfdd4a64", 42 | ))), 43 | Z: FieldElement::ONE, 44 | T: FieldElement(ConstMontyType::new(&U448::from_be_hex( 45 | "6d3669e173c6a450e23d5682a9ffe1ddc2b86da60f794be956382384a319b57519c9854dde98e342140362071833f4e093e3c816dc198105", 46 | ))), 47 | }; 48 | -------------------------------------------------------------------------------- /bignp256/src/ecdh.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Diffie-Hellman (Ephemeral) Support. 2 | //! 3 | //! This module contains a high-level interface for performing ephemeral 4 | //! Diffie-Hellman key exchanges using the bign-curve256v1 elliptic curve. 5 | //! 6 | //! # Usage 7 | //! 8 | //! This usage example is from the perspective of two participants in the 9 | //! exchange, nicknamed "Alice" and "Bob". 10 | //! 11 | #![cfg_attr(feature = "getrandom", doc = "```")] 12 | #![cfg_attr(not(feature = "getrandom"), doc = "```ignore")] 13 | //! // NOTE: requires 'getrandom' feature is enabled 14 | //! 15 | //! use bignp256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; 16 | //! 17 | //! // Alice 18 | //! let alice_secret = EphemeralSecret::generate(); 19 | //! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); 20 | //! 21 | //! // Bob 22 | //! let bob_secret = EphemeralSecret::generate(); 23 | //! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); 24 | //! 25 | //! // Alice decodes Bob's serialized public key and computes a shared secret from it 26 | //! let bob_public = 27 | //! PublicKey::from_encoded_point(bob_pk_bytes).expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! 28 | //! 29 | //! let alice_shared = alice_secret.diffie_hellman(&bob_public.into()); 30 | //! 31 | //! // Bob decodes Alice's serialized public key and computes the same shared secret 32 | //! let alice_public = 33 | //! PublicKey::from_encoded_point(alice_pk_bytes).expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! 34 | //! 35 | //! let bob_shared = bob_secret.diffie_hellman(&alice_public.into()); 36 | //! 37 | //! // Both participants arrive on the same shared secret 38 | //! assert_eq!( 39 | //! alice_shared.raw_secret_bytes(), 40 | //! bob_shared.raw_secret_bytes() 41 | //! ); 42 | //! ``` 43 | 44 | pub use elliptic_curve::ecdh::diffie_hellman; 45 | 46 | use crate::BignP256; 47 | 48 | /// NIST P-256 Ephemeral Diffie-Hellman Secret. 49 | pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; 50 | 51 | /// Shared secret value computed via ECDH key agreement. 52 | pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; 53 | -------------------------------------------------------------------------------- /p192/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Pure Rust implementation of group operations on secp192r1. 2 | //! 3 | //! Curve parameters can be found in [FIPS 186-4] § D.1.2.1: Curve P-192. 4 | //! 5 | //! [FIPS 186-4]: https://csrc.nist.gov/publications/detail/fips/186/4/final 6 | 7 | pub(crate) mod field; 8 | pub(crate) mod scalar; 9 | 10 | use self::{field::FieldElement, scalar::Scalar}; 11 | use crate::NistP192; 12 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 13 | use primeorder::{PrimeCurveParams, point_arithmetic}; 14 | 15 | /// Elliptic curve point in affine coordinates. 16 | pub type AffinePoint = primeorder::AffinePoint; 17 | 18 | /// Elliptic curve point in projective coordinates. 19 | pub type ProjectivePoint = primeorder::ProjectivePoint; 20 | 21 | impl CurveArithmetic for NistP192 { 22 | type AffinePoint = AffinePoint; 23 | type ProjectivePoint = ProjectivePoint; 24 | type Scalar = Scalar; 25 | } 26 | 27 | impl PrimeCurveArithmetic for NistP192 { 28 | type CurveGroup = ProjectivePoint; 29 | } 30 | 31 | /// Adapted from [FIPS 186-4] § D.1.2.1: Curve P-192. 32 | /// 33 | /// [FIPS 186-4]: https://csrc.nist.gov/publications/detail/fips/186/4/final 34 | impl PrimeCurveParams for NistP192 { 35 | type FieldElement = FieldElement; 36 | type PointArithmetic = point_arithmetic::EquationAIsMinusThree; 37 | 38 | /// a = -3 (=0xffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe) 39 | const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); 40 | 41 | /// b = 0x64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1 42 | const EQUATION_B: FieldElement = 43 | FieldElement::from_hex_vartime("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"); 44 | 45 | /// Base point of P-192. 46 | /// 47 | /// ```text 48 | /// Gₓ = 0x188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012 49 | /// Gᵧ = 0x07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811 50 | /// ``` 51 | const GENERATOR: (FieldElement, FieldElement) = ( 52 | FieldElement::from_hex_vartime("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"), 53 | FieldElement::from_hex_vartime("07192b95ffc8da78631011ed6b24cdd573f977a11e794811"), 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /k256/src/ecdh.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Diffie-Hellman (Ephemeral) Support. 2 | //! 3 | //! This module contains a high-level interface for performing ephemeral 4 | //! Diffie-Hellman key exchanges using the secp256k1 elliptic curve. 5 | //! 6 | //! # Usage 7 | //! 8 | //! This usage example is from the perspective of two participants in the 9 | //! exchange, nicknamed "Alice" and "Bob". 10 | //! 11 | //! ``` 12 | //! use k256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; 13 | //! use rand::{rngs::OsRng, TryRngCore}; 14 | //! 15 | //! // Alice 16 | //! let alice_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 17 | //! let alice_pk_bytes = EncodedPoint::from(alice_secret.public_key()); 18 | //! 19 | //! // Bob 20 | //! let bob_secret = EphemeralSecret::try_from_rng(&mut OsRng).unwrap(); 21 | //! let bob_pk_bytes = EncodedPoint::from(bob_secret.public_key()); 22 | //! 23 | //! // Alice decodes Bob's serialized public key and computes a shared secret from it 24 | //! let bob_public = PublicKey::from_sec1_bytes(bob_pk_bytes.as_ref()) 25 | //! .expect("bob's public key is invalid!"); // In real usage, don't panic, handle this! 26 | //! 27 | //! let alice_shared = alice_secret.diffie_hellman(&bob_public); 28 | //! 29 | //! // Bob decodes Alice's serialized public key and computes the same shared secret 30 | //! let alice_public = PublicKey::from_sec1_bytes(alice_pk_bytes.as_ref()) 31 | //! .expect("alice's public key is invalid!"); // In real usage, don't panic, handle this! 32 | //! 33 | //! let bob_shared = bob_secret.diffie_hellman(&alice_public); 34 | //! 35 | //! // Both participants arrive on the same shared secret 36 | //! assert_eq!(alice_shared.raw_secret_bytes(), bob_shared.raw_secret_bytes()); 37 | //! ``` 38 | 39 | pub use elliptic_curve::ecdh::diffie_hellman; 40 | 41 | use crate::{AffinePoint, Secp256k1}; 42 | 43 | /// secp256k1 Ephemeral Diffie-Hellman Secret. 44 | pub type EphemeralSecret = elliptic_curve::ecdh::EphemeralSecret; 45 | 46 | /// Shared secret value computed via ECDH key agreement. 47 | pub type SharedSecret = elliptic_curve::ecdh::SharedSecret; 48 | 49 | impl From<&AffinePoint> for SharedSecret { 50 | fn from(affine: &AffinePoint) -> SharedSecret { 51 | affine.x.to_bytes().into() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /sm2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sm2" 3 | version = "0.14.0-rc.1" 4 | description = """ 5 | Pure Rust implementation of the SM2 elliptic curve as defined in the Chinese 6 | national standard GM/T 0003-2012 as well as ISO/IEC 14888. Includes support for 7 | the SM2DSA Digital Signature Algorithm. 8 | """ 9 | authors = ["RustCrypto Developers"] 10 | license = "Apache-2.0 OR MIT" 11 | documentation = "https://docs.rs/sm2" 12 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/sm2" 13 | repository = "https://github.com/RustCrypto/elliptic-curves" 14 | readme = "README.md" 15 | categories = ["cryptography", "no-std"] 16 | keywords = ["crypto", "ecc", "shangmi", "signature", "encryption"] 17 | edition = "2024" 18 | rust-version = "1.85" 19 | 20 | [dependencies] 21 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["sec1"] } 22 | fiat-crypto = { version = "0.3", default-features = false } 23 | rand_core = { version = "0.10.0-rc-2", default-features = false } 24 | 25 | # optional dependencies 26 | primefield = { version = "0.14.0-rc.1", optional = true } 27 | primeorder = { version = "0.14.0-rc.1", optional = true } 28 | rfc6979 = { version = "0.5.0-rc.3", optional = true } 29 | serdect = { version = "0.4", optional = true, default-features = false } 30 | signature = { version = "3.0.0-rc.5", optional = true, features = ["rand_core"] } 31 | sm3 = { version = "0.5.0-rc.3", optional = true, default-features = false } 32 | der = { version = "0.8.0-rc.10", optional = true } 33 | 34 | [dev-dependencies] 35 | hex-literal = "1" 36 | proptest = "1" 37 | rand = "0.10.0-rc.1" 38 | 39 | [features] 40 | default = ["arithmetic", "dsa", "getrandom", "pke", "pem", "std"] 41 | alloc = ["elliptic-curve/alloc"] 42 | std = ["alloc", "elliptic-curve/std"] 43 | 44 | arithmetic = ["dep:primefield", "dep:primeorder", "elliptic-curve/arithmetic"] 45 | bits = ["arithmetic", "elliptic-curve/bits"] 46 | dsa = ["arithmetic", "dep:rfc6979", "dep:signature", "dep:sm3"] 47 | getrandom = ["elliptic-curve/getrandom"] 48 | pke = ["arithmetic", "dep:sm3"] 49 | pem = ["elliptic-curve/pem", "pkcs8"] 50 | pkcs8 = ["elliptic-curve/pkcs8", "der"] 51 | serde = ["elliptic-curve/serde", "primeorder?/serde", "serdect"] 52 | 53 | [package.metadata.docs.rs] 54 | all-features = true 55 | -------------------------------------------------------------------------------- /bp384/src/t1.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP384t1 elliptic curve: twisted variant 2 | 3 | #[cfg(feature = "ecdsa")] 4 | pub mod ecdsa; 5 | 6 | #[cfg(feature = "arithmetic")] 7 | mod arithmetic; 8 | 9 | #[cfg(feature = "arithmetic")] 10 | pub use { 11 | self::arithmetic::{AffinePoint, NonZeroScalar, ProjectivePoint, ScalarValue}, 12 | crate::Scalar, 13 | }; 14 | 15 | use crate::ORDER; 16 | use elliptic_curve::{ 17 | FieldBytesEncoding, 18 | bigint::{Odd, U384}, 19 | consts::U48, 20 | }; 21 | 22 | #[cfg(feature = "pkcs8")] 23 | use crate::pkcs8; 24 | 25 | /// brainpoolP384t1 elliptic curve: twisted variant 26 | #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] 27 | pub struct BrainpoolP384t1; 28 | 29 | impl elliptic_curve::Curve for BrainpoolP384t1 { 30 | /// 48-byte serialized field elements. 31 | type FieldBytesSize = U48; 32 | 33 | /// 384-bit field modulus. 34 | type Uint = U384; 35 | 36 | /// Curve order. 37 | const ORDER: Odd = ORDER; 38 | } 39 | 40 | impl elliptic_curve::PrimeCurve for BrainpoolP384t1 {} 41 | 42 | impl elliptic_curve::point::PointCompression for BrainpoolP384t1 { 43 | const COMPRESS_POINTS: bool = false; 44 | } 45 | 46 | #[cfg(feature = "pkcs8")] 47 | impl pkcs8::AssociatedOid for BrainpoolP384t1 { 48 | const OID: pkcs8::ObjectIdentifier = 49 | pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.12"); 50 | } 51 | 52 | /// brainpoolP384t1 SEC1 encoded point. 53 | pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; 54 | 55 | /// brainpoolP384t1 field element serialized as bytes. 56 | /// 57 | /// Byte array containing a serialized field element value (base field or scalar). 58 | pub type FieldBytes = elliptic_curve::FieldBytes; 59 | 60 | impl FieldBytesEncoding for U384 { 61 | fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { 62 | crate::decode_field_bytes(field_bytes) 63 | } 64 | 65 | fn encode_field_bytes(&self) -> FieldBytes { 66 | crate::encode_field_bytes(self) 67 | } 68 | } 69 | 70 | /// brainpoolP384t1 secret key. 71 | pub type SecretKey = elliptic_curve::SecretKey; 72 | 73 | #[cfg(not(feature = "arithmetic"))] 74 | impl elliptic_curve::sec1::ValidatePublicKey for BrainpoolP384t1 {} 75 | -------------------------------------------------------------------------------- /p224/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Pure Rust implementation of group operations on secp224r1. 2 | //! 3 | //! Curve parameters can be found in [NIST SP 800-186] § 3.2.1.2: P-224. 4 | //! 5 | //! [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final 6 | 7 | pub(crate) mod field; 8 | pub(crate) mod scalar; 9 | 10 | pub use self::scalar::Scalar; 11 | 12 | use self::field::FieldElement; 13 | use crate::NistP224; 14 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 15 | use primeorder::{PrimeCurveParams, point_arithmetic}; 16 | 17 | /// Elliptic curve point in affine coordinates. 18 | pub type AffinePoint = primeorder::AffinePoint; 19 | 20 | /// Elliptic curve point in projective coordinates. 21 | pub type ProjectivePoint = primeorder::ProjectivePoint; 22 | 23 | impl CurveArithmetic for NistP224 { 24 | type AffinePoint = AffinePoint; 25 | type ProjectivePoint = ProjectivePoint; 26 | type Scalar = Scalar; 27 | } 28 | 29 | impl PrimeCurveArithmetic for NistP224 { 30 | type CurveGroup = ProjectivePoint; 31 | } 32 | 33 | /// Adapted from [NIST SP 800-186] § 3.2.1.2: P-224. 34 | /// 35 | /// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final 36 | impl PrimeCurveParams for NistP224 { 37 | type FieldElement = FieldElement; 38 | type PointArithmetic = point_arithmetic::EquationAIsMinusThree; 39 | 40 | /// a = -3 (=0xffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe) 41 | const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); 42 | 43 | /// b = 0xb4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4 44 | const EQUATION_B: FieldElement = 45 | FieldElement::from_hex_vartime("b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"); 46 | 47 | /// Base point of P-224. 48 | /// 49 | /// ```text 50 | /// Gₓ = 0xb70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21 51 | /// Gᵧ = 0xbd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34 52 | /// ``` 53 | const GENERATOR: (FieldElement, FieldElement) = ( 54 | FieldElement::from_hex_vartime("b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"), 55 | FieldElement::from_hex_vartime("bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"), 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /bp256/src/t1.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP256t1 elliptic curve: twisted variant 2 | 3 | #[cfg(feature = "ecdsa")] 4 | pub mod ecdsa; 5 | 6 | #[cfg(feature = "arithmetic")] 7 | mod arithmetic; 8 | 9 | #[cfg(feature = "arithmetic")] 10 | pub use { 11 | self::arithmetic::{AffinePoint, NonZeroScalar, ProjectivePoint, ScalarValue}, 12 | crate::Scalar, 13 | }; 14 | 15 | use crate::ORDER; 16 | use elliptic_curve::{ 17 | FieldBytesEncoding, 18 | bigint::{Odd, U256}, 19 | consts::U32, 20 | }; 21 | 22 | #[cfg(feature = "pkcs8")] 23 | use crate::pkcs8; 24 | 25 | /// brainpoolP256t1 elliptic curve: twisted variant 26 | #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] 27 | pub struct BrainpoolP256t1; 28 | 29 | impl elliptic_curve::Curve for BrainpoolP256t1 { 30 | /// 32-byte serialized field elements. 31 | type FieldBytesSize = U32; 32 | 33 | /// 256-bit field modulus. 34 | type Uint = U256; 35 | 36 | /// Curve order 37 | const ORDER: Odd = ORDER; 38 | } 39 | 40 | impl elliptic_curve::PrimeCurve for BrainpoolP256t1 {} 41 | 42 | impl elliptic_curve::point::PointCompression for BrainpoolP256t1 { 43 | const COMPRESS_POINTS: bool = false; 44 | } 45 | 46 | #[cfg(feature = "pkcs8")] 47 | impl pkcs8::AssociatedOid for BrainpoolP256t1 { 48 | const OID: pkcs8::ObjectIdentifier = 49 | pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.8"); 50 | } 51 | 52 | /// brainpoolP256t1 SEC1 encoded point. 53 | pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; 54 | 55 | /// brainpoolP256t1 field element serialized as bytes. 56 | /// 57 | /// Byte array containing a serialized field element value (base field or scalar). 58 | pub type FieldBytes = elliptic_curve::FieldBytes; 59 | 60 | impl FieldBytesEncoding for U256 { 61 | fn decode_field_bytes(field_bytes: &crate::r1::FieldBytes) -> Self { 62 | crate::decode_field_bytes(field_bytes) 63 | } 64 | 65 | fn encode_field_bytes(&self) -> crate::r1::FieldBytes { 66 | crate::encode_field_bytes(self) 67 | } 68 | } 69 | 70 | /// brainpoolP256t1 secret key. 71 | pub type SecretKey = elliptic_curve::SecretKey; 72 | 73 | #[cfg(not(feature = "arithmetic"))] 74 | impl elliptic_curve::sec1::ValidatePublicKey for BrainpoolP256t1 {} 75 | -------------------------------------------------------------------------------- /bp256/src/r1.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP256r1 elliptic curve: verifiably pseudo-random variant 2 | 3 | #[cfg(feature = "ecdsa")] 4 | pub mod ecdsa; 5 | 6 | #[cfg(feature = "arithmetic")] 7 | mod arithmetic; 8 | 9 | #[cfg(feature = "arithmetic")] 10 | pub use { 11 | self::arithmetic::{AffinePoint, NonZeroScalar, ProjectivePoint, ScalarValue}, 12 | crate::Scalar, 13 | }; 14 | 15 | use crate::ORDER; 16 | use elliptic_curve::{ 17 | FieldBytesEncoding, 18 | bigint::{Odd, U256}, 19 | consts::U32, 20 | }; 21 | 22 | #[cfg(feature = "pkcs8")] 23 | use crate::pkcs8; 24 | 25 | /// brainpoolP256r1 elliptic curve: verifiably pseudo-random variant 26 | #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] 27 | pub struct BrainpoolP256r1; 28 | 29 | impl elliptic_curve::Curve for BrainpoolP256r1 { 30 | /// 32-byte serialized field elements. 31 | type FieldBytesSize = U32; 32 | 33 | /// 256-bit field modulus. 34 | type Uint = U256; 35 | 36 | /// Curve order 37 | const ORDER: Odd = ORDER; 38 | } 39 | 40 | impl elliptic_curve::PrimeCurve for BrainpoolP256r1 {} 41 | 42 | impl elliptic_curve::point::PointCompression for BrainpoolP256r1 { 43 | const COMPRESS_POINTS: bool = false; 44 | } 45 | 46 | #[cfg(feature = "pkcs8")] 47 | impl pkcs8::AssociatedOid for BrainpoolP256r1 { 48 | const OID: pkcs8::ObjectIdentifier = 49 | pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.7"); 50 | } 51 | 52 | /// brainpoolP256r1 SEC1 encoded point. 53 | pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; 54 | 55 | /// brainpoolP256r1 field element serialized as bytes. 56 | /// 57 | /// Byte array containing a serialized field element value (base field or scalar). 58 | pub type FieldBytes = elliptic_curve::FieldBytes; 59 | 60 | impl FieldBytesEncoding for U256 { 61 | fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { 62 | crate::decode_field_bytes(field_bytes) 63 | } 64 | 65 | fn encode_field_bytes(&self) -> FieldBytes { 66 | crate::encode_field_bytes(self) 67 | } 68 | } 69 | 70 | /// brainpoolP256r1 secret key. 71 | pub type SecretKey = elliptic_curve::SecretKey; 72 | 73 | #[cfg(not(feature = "arithmetic"))] 74 | impl elliptic_curve::sec1::ValidatePublicKey for BrainpoolP256r1 {} 75 | -------------------------------------------------------------------------------- /sm2/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff 2 | //! 3 | //! Arithmetic implementations have been synthesized using fiat-crypto. 4 | //! 5 | //! # License 6 | //! 7 | //! Copyright (c) 2015-2020 the fiat-crypto authors 8 | //! 9 | //! fiat-crypto is distributed under the terms of the MIT License, the 10 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 11 | //! users may pick which license to apply. 12 | 13 | #[cfg(target_pointer_width = "32")] 14 | use fiat_crypto::sm2_32::*; 15 | #[cfg(target_pointer_width = "64")] 16 | use fiat_crypto::sm2_64::*; 17 | 18 | use crate::U256; 19 | use elliptic_curve::{ 20 | ff::PrimeField, 21 | subtle::{Choice, ConstantTimeEq, CtOption}, 22 | }; 23 | 24 | /// Constant representing the modulus serialized as hex. 25 | const MODULUS_HEX: &str = "fffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff"; 26 | 27 | primefield::monty_field_params! { 28 | name: FieldParams, 29 | modulus: MODULUS_HEX, 30 | uint: U256, 31 | byte_order: primefield::ByteOrder::BigEndian, 32 | multiplicative_generator: 13, 33 | doc: "Montgomery parameters for SM2's field modulus `p = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff`" 34 | } 35 | 36 | primefield::monty_field_element! { 37 | name: FieldElement, 38 | params: FieldParams, 39 | uint: U256, 40 | doc: "Element in the SM2 finite field modulo `p = 0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff`" 41 | } 42 | 43 | primefield::monty_field_fiat_arithmetic! { 44 | name: FieldElement, 45 | params: FieldParams, 46 | uint: U256, 47 | non_mont: fiat_sm2_non_montgomery_domain_field_element, 48 | mont: fiat_sm2_montgomery_domain_field_element, 49 | from_mont: fiat_sm2_from_montgomery, 50 | to_mont: fiat_sm2_to_montgomery, 51 | add: fiat_sm2_add, 52 | sub: fiat_sm2_sub, 53 | mul: fiat_sm2_mul, 54 | neg: fiat_sm2_opp, 55 | square: fiat_sm2_square, 56 | divstep_precomp: fiat_sm2_divstep_precomp, 57 | divstep: fiat_sm2_divstep, 58 | msat: fiat_sm2_msat, 59 | selectnz: fiat_sm2_selectznz 60 | } 61 | 62 | #[cfg(test)] 63 | mod tests { 64 | use super::{FieldElement, U256}; 65 | primefield::test_primefield!(FieldElement, U256); 66 | } 67 | -------------------------------------------------------------------------------- /bp384/src/r1.rs: -------------------------------------------------------------------------------- 1 | //! brainpoolP384r1 elliptic curve: verifiably pseudo-random variant 2 | 3 | #[cfg(feature = "ecdsa")] 4 | pub mod ecdsa; 5 | 6 | #[cfg(feature = "arithmetic")] 7 | mod arithmetic; 8 | 9 | #[cfg(feature = "arithmetic")] 10 | pub use { 11 | self::arithmetic::{AffinePoint, NonZeroScalar, ProjectivePoint, ScalarValue}, 12 | crate::Scalar, 13 | }; 14 | 15 | use crate::ORDER; 16 | use elliptic_curve::{ 17 | FieldBytesEncoding, 18 | bigint::{Odd, U384}, 19 | consts::U48, 20 | }; 21 | 22 | #[cfg(feature = "pkcs8")] 23 | use crate::pkcs8; 24 | 25 | /// brainpoolP384r1 elliptic curve: verifiably pseudo-random variant 26 | #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] 27 | pub struct BrainpoolP384r1; 28 | 29 | impl elliptic_curve::Curve for BrainpoolP384r1 { 30 | /// 48-byte serialized field elements. 31 | type FieldBytesSize = U48; 32 | 33 | /// 384-bit field modulus. 34 | type Uint = U384; 35 | 36 | /// Curve order. 37 | const ORDER: Odd = ORDER; 38 | } 39 | 40 | impl elliptic_curve::PrimeCurve for BrainpoolP384r1 {} 41 | 42 | impl elliptic_curve::point::PointCompression for BrainpoolP384r1 { 43 | const COMPRESS_POINTS: bool = false; 44 | } 45 | 46 | #[cfg(feature = "pkcs8")] 47 | impl pkcs8::AssociatedOid for BrainpoolP384r1 { 48 | const OID: pkcs8::ObjectIdentifier = 49 | pkcs8::ObjectIdentifier::new_unwrap("1.3.36.3.3.2.8.1.1.11"); 50 | } 51 | 52 | /// brainpoolP384r1 SEC1 encoded point. 53 | pub type EncodedPoint = elliptic_curve::sec1::EncodedPoint; 54 | 55 | /// brainpoolP384r1 field element serialized as bytes. 56 | /// 57 | /// Byte array containing a serialized field element value (base field or scalar). 58 | pub type FieldBytes = elliptic_curve::FieldBytes; 59 | 60 | impl FieldBytesEncoding for U384 { 61 | fn decode_field_bytes(field_bytes: &FieldBytes) -> Self { 62 | crate::decode_field_bytes(field_bytes) 63 | } 64 | 65 | fn encode_field_bytes(&self) -> FieldBytes { 66 | crate::encode_field_bytes(self) 67 | } 68 | } 69 | 70 | /// brainpoolP384r1 secret key. 71 | pub type SecretKey = elliptic_curve::SecretKey; 72 | 73 | #[cfg(not(feature = "arithmetic"))] 74 | impl elliptic_curve::sec1::ValidatePublicKey for BrainpoolP384r1 {} 75 | -------------------------------------------------------------------------------- /p256/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Pure Rust implementation of group operations on secp256r1. 2 | //! 3 | //! Curve parameters can be found in [NIST SP 800-186] § G.1.2: Curve P-256. 4 | //! 5 | //! [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final 6 | 7 | pub(crate) mod field; 8 | #[cfg(feature = "hash2curve")] 9 | mod hash2curve; 10 | pub(crate) mod scalar; 11 | 12 | use self::{field::FieldElement, scalar::Scalar}; 13 | use crate::NistP256; 14 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 15 | use primeorder::{PrimeCurveParams, point_arithmetic}; 16 | 17 | /// Elliptic curve point in affine coordinates. 18 | pub type AffinePoint = primeorder::AffinePoint; 19 | 20 | /// Elliptic curve point in projective coordinates. 21 | pub type ProjectivePoint = primeorder::ProjectivePoint; 22 | 23 | impl CurveArithmetic for NistP256 { 24 | type AffinePoint = AffinePoint; 25 | type ProjectivePoint = ProjectivePoint; 26 | type Scalar = Scalar; 27 | } 28 | 29 | impl PrimeCurveArithmetic for NistP256 { 30 | type CurveGroup = ProjectivePoint; 31 | } 32 | 33 | /// Adapted from [NIST SP 800-186] § G.1.2: Curve P-256. 34 | /// 35 | /// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final 36 | impl PrimeCurveParams for NistP256 { 37 | type FieldElement = FieldElement; 38 | type PointArithmetic = point_arithmetic::EquationAIsMinusThree; 39 | 40 | /// a = -3 41 | const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); 42 | 43 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 44 | "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 45 | ); 46 | 47 | /// Base point of P-256. 48 | /// 49 | /// Defined in NIST SP 800-186 § G.1.2: 50 | /// 51 | /// ```text 52 | /// Gₓ = 6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296 53 | /// Gᵧ = 4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5 54 | /// ``` 55 | const GENERATOR: (FieldElement, FieldElement) = ( 56 | FieldElement::from_hex_vartime( 57 | "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 58 | ), 59 | FieldElement::from_hex_vartime( 60 | "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 61 | ), 62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /p224/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "p224" 3 | version = "0.14.0-rc.1" 4 | description = """ 5 | Pure Rust implementation of the NIST P-224 (a.k.a. secp224r1) elliptic curve 6 | as defined in SP 800-186 7 | """ 8 | authors = ["RustCrypto Developers"] 9 | license = "Apache-2.0 OR MIT" 10 | documentation = "https://docs.rs/p224" 11 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/p224" 12 | repository = "https://github.com/RustCrypto/elliptic-curves" 13 | readme = "README.md" 14 | categories = ["cryptography", "no-std"] 15 | keywords = ["crypto", "ecc", "nist", "secp224r1"] 16 | edition = "2024" 17 | rust-version = "1.85" 18 | 19 | [dependencies] 20 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["sec1"] } 21 | 22 | # optional dependencies 23 | ecdsa-core = { version = "0.17.0-rc.9", package = "ecdsa", optional = true, default-features = false, features = ["der"] } 24 | hex-literal = { version = "1", optional = true } 25 | primefield = { version = "0.14.0-rc.1", optional = true } 26 | primeorder = { version = "0.14.0-rc.1", optional = true } 27 | serdect = { version = "0.4", optional = true, default-features = false } 28 | sha2 = { version = "0.11.0-rc.3", optional = true, default-features = false } 29 | 30 | [dev-dependencies] 31 | ecdsa-core = { version = "0.17.0-rc.9", package = "ecdsa", default-features = false, features = ["dev"] } 32 | hex-literal = "1" 33 | primeorder = { version = "0.14.0-rc.1", features = ["dev"] } 34 | rand = "0.10.0-rc.1" 35 | 36 | [features] 37 | default = ["arithmetic", "ecdsa", "pem", "std"] 38 | alloc = ["elliptic-curve/alloc", "primeorder?/alloc"] 39 | std = ["alloc", "elliptic-curve/std", "getrandom"] 40 | 41 | arithmetic = ["dep:primefield", "dep:primeorder", "elliptic-curve/arithmetic"] 42 | bits = ["arithmetic", "elliptic-curve/bits"] 43 | digest = ["ecdsa-core/digest", "ecdsa-core/hazmat"] 44 | ecdh = ["arithmetic", "elliptic-curve/ecdh"] 45 | ecdsa = ["arithmetic", "ecdsa-core/algorithm", "sha224"] 46 | getrandom = ["ecdsa-core?/getrandom", "elliptic-curve/getrandom"] 47 | pem = ["elliptic-curve/pem", "pkcs8"] 48 | pkcs8 = ["ecdsa-core?/pkcs8", "elliptic-curve/pkcs8"] 49 | serde = ["ecdsa-core?/serde", "elliptic-curve/serde", "primeorder?/serde", "serdect"] 50 | sha224 = ["digest", "sha2"] 51 | test-vectors = ["dep:hex-literal"] 52 | 53 | [package.metadata.docs.rs] 54 | all-features = true 55 | -------------------------------------------------------------------------------- /ed448-goldilocks/src/curve/twedwards.rs: -------------------------------------------------------------------------------- 1 | /// This module will contain the EC arithmetic for the Twisted Edwards form of Goldilocks. 2 | /// with the following affine equation : -x^2 + y^2 = 1 - 39082x^2y^2 3 | /// This curve will be used as a backend for the Goldilocks and Decaf through the use of isogenies. 4 | /// It will not be exposed in the public API. 5 | pub(crate) mod affine; 6 | pub(crate) mod extended; 7 | pub(crate) mod extensible; 8 | pub(crate) mod projective; 9 | 10 | use crate::field::FieldElement; 11 | 12 | pub(crate) struct IsogenyMap { 13 | pub(crate) X: FieldElement, 14 | pub(crate) Y: FieldElement, 15 | pub(crate) Z: FieldElement, 16 | pub(crate) T: FieldElement, 17 | } 18 | 19 | pub(crate) struct IsogenyMapResult { 20 | pub(crate) X: FieldElement, 21 | pub(crate) Y: FieldElement, 22 | pub(crate) Z: FieldElement, 23 | pub(crate) T1: FieldElement, 24 | pub(crate) T2: FieldElement, 25 | } 26 | 27 | impl IsogenyMap { 28 | // (1.) https://eprint.iacr.org/2014/027.pdf 29 | pub(crate) fn map(&self, scale: impl FnOnce(FieldElement) -> FieldElement) -> IsogenyMapResult { 30 | // x = 2xy / (y^2 - a*x^2) 31 | // y = (y^2 + a*x^2) / (2 - y^2 - a*x^2) 32 | 33 | // Derive algorithm for projective form: 34 | 35 | // x = X / Z 36 | // y = Y / Z 37 | // xy = T / Z 38 | // x^2 = X^2 / Z^2 39 | // y^2 = y^2 / Z^2 40 | 41 | // x = 2xy / (y^2 - a*x^2) 42 | // x = (2T/Z) / (Y^2/Z^2 + a*X^2/Z^2) 43 | // x = 2TZ / (Y^2 - a*X^2) 44 | 45 | // y = (y^2 + a*x^2) / (2 - y^2 - a*x^2) 46 | // y = (Y^2/Z^2 + a*X^2/Z^2) / (2 - Y^2/Z^2 - a*X^2/Z^2) 47 | // y = (Y^2 + a*X^2) / (2*Z^2 - Y^2 - a*X^2) 48 | 49 | let xx = self.X.square(); 50 | let yy = self.Y.square(); 51 | let axx = scale(xx); 52 | let yy_plus_axx = yy + axx; 53 | 54 | // Compute x 55 | let x_numerator = (self.T * self.Z).double(); 56 | let x_denom = yy - axx; 57 | 58 | // Compute y 59 | let y_numerator = yy_plus_axx; 60 | let y_denom = self.Z.square().double() - yy_plus_axx; 61 | 62 | let X = x_numerator * y_denom; 63 | let Y = y_numerator * x_denom; 64 | let Z = x_denom * y_denom; 65 | let T1 = x_numerator; 66 | let T2 = y_numerator; 67 | 68 | IsogenyMapResult { X, Y, Z, T1, T2 } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /p192/src/ecdsa.rs: -------------------------------------------------------------------------------- 1 | //! Elliptic Curve Digital Signature Algorithm (ECDSA) 2 | //! 3 | //! This module contains support for computing and verifying ECDSA signatures. 4 | //! To use it, you will need to enable one of the two following Cargo features: 5 | //! 6 | //! - `ecdsa-core`: provides only the [`Signature`] type (which represents an 7 | //! ECDSA/P-192 signature). Does not require the `arithmetic` feature. This is 8 | //! useful for 3rd-party crates which wish to use the `Signature` type for 9 | //! interoperability purposes. Example use cases for this include other 10 | //! software implementations of ECDSA/P-192 and wrappers for cloud KMS 11 | //! services or hardware devices (HSM or crypto hardware wallet). 12 | //! - `ecdsa`: provides `ecdsa-core` features plus [`VerifyingKey`] types 13 | //! which natively implement ECDSA/P-192 verification. 14 | //! 15 | //! ## Verification only 16 | //! 17 | //! Following guidance from [NIST Special Publication 800-131A Revision 2]: 18 | //! "Transitioning the Use of Cryptographic Algorithms and Key Lengths", this 19 | //! crate only supports ECDSA verification, not signing. 20 | //! 21 | //! From Section 3: Digital Signatures: 22 | //! 23 | //! > <112 bits of security strength: ECDSA: len(n) < 224 24 | //! > 25 | //! > [...] 26 | //! > 27 | //! > Digital signature generation: 28 | //! > 29 | //! > Private-key lengths providing less than 112 bits of security **shall not** be used to 30 | //! > generate digital signatures. 31 | //! 32 | //! [NIST Special Publication 800-131A Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf 33 | 34 | pub use ecdsa_core::signature::{self, Error}; 35 | 36 | use super::NistP192; 37 | use ecdsa_core::EcdsaCurve; 38 | 39 | /// ECDSA/P-192 signature (fixed-size) 40 | pub type Signature = ecdsa_core::Signature; 41 | 42 | /// ECDSA/P-192 signature (ASN.1 DER encoded) 43 | pub type DerSignature = ecdsa_core::der::Signature; 44 | 45 | impl EcdsaCurve for NistP192 { 46 | const NORMALIZE_S: bool = false; 47 | } 48 | 49 | /// ECDSA/P-192 verification key (i.e. public key) 50 | #[cfg(feature = "ecdsa")] 51 | pub type VerifyingKey = ecdsa_core::VerifyingKey; 52 | 53 | #[cfg(all(test, feature = "ecdsa"))] 54 | mod tests { 55 | mod verify { 56 | use crate::{NistP192, test_vectors::ecdsa::ECDSA_TEST_VECTORS}; 57 | ecdsa_core::new_verification_test!(NistP192, ECDSA_TEST_VECTORS); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /sm2/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Pure Rust implementation of group operations on the SM2 elliptic curve. 2 | //! 3 | //! Curve parameters can be found in [draft-shen-sm2-ecdsa Appendix D]: 4 | //! Recommended Parameters. 5 | //! 6 | //! [draft-shen-sm2-ecdsa Appendix D]: https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa-02#appendix-D 7 | 8 | pub(crate) mod field; 9 | pub(crate) mod scalar; 10 | 11 | pub use self::scalar::Scalar; 12 | 13 | use self::field::FieldElement; 14 | use crate::Sm2; 15 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 16 | use primeorder::{PrimeCurveParams, point_arithmetic}; 17 | 18 | /// Elliptic curve point in affine coordinates. 19 | pub type AffinePoint = primeorder::AffinePoint; 20 | 21 | /// Elliptic curve point in projective coordinates. 22 | pub type ProjectivePoint = primeorder::ProjectivePoint; 23 | 24 | impl CurveArithmetic for Sm2 { 25 | type AffinePoint = AffinePoint; 26 | type ProjectivePoint = ProjectivePoint; 27 | type Scalar = Scalar; 28 | } 29 | 30 | impl PrimeCurveArithmetic for Sm2 { 31 | type CurveGroup = ProjectivePoint; 32 | } 33 | 34 | /// Adapted from [draft-shen-sm2-ecdsa Appendix D]: Recommended Parameters. 35 | /// 36 | /// [draft-shen-sm2-ecdsa Appendix D]: https://datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa-02#appendix-D 37 | impl PrimeCurveParams for Sm2 { 38 | type FieldElement = FieldElement; 39 | type PointArithmetic = point_arithmetic::EquationAIsMinusThree; 40 | 41 | /// a = -3 (0xFFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC) 42 | const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); 43 | 44 | /// b = 0x28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93 45 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 46 | "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 47 | ); 48 | 49 | /// Base point of SM2. 50 | /// 51 | /// ```text 52 | /// Gₓ = 0x32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 53 | /// Gᵧ = 0xBC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 54 | /// ``` 55 | const GENERATOR: (FieldElement, FieldElement) = ( 56 | FieldElement::from_hex_vartime( 57 | "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 58 | ), 59 | FieldElement::from_hex_vartime( 60 | "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 61 | ), 62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /p192/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 2^{192} − 2^{64} - 1 2 | //! 3 | //! Arithmetic implementations have been synthesized using fiat-crypto. 4 | //! 5 | //! # License 6 | //! 7 | //! Copyright (c) 2015-2020 the fiat-crypto authors 8 | //! 9 | //! fiat-crypto is distributed under the terms of the MIT License, the 10 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 11 | //! users may pick which license to apply. 12 | 13 | #[cfg_attr(target_pointer_width = "32", path = "field/p192_32.rs")] 14 | #[cfg_attr(target_pointer_width = "64", path = "field/p192_64.rs")] 15 | #[allow( 16 | clippy::identity_op, 17 | clippy::needless_lifetimes, 18 | clippy::unnecessary_cast, 19 | clippy::too_many_arguments 20 | )] 21 | #[allow(dead_code)] // TODO(tarcieri): remove this when we can use `const _` to silence warnings 22 | mod field_impl; 23 | 24 | use self::field_impl::*; 25 | use crate::U192; 26 | use elliptic_curve::{ 27 | ff::PrimeField, 28 | subtle::{Choice, ConstantTimeEq, CtOption}, 29 | }; 30 | 31 | /// Constant representing the modulus serialized as hex. 32 | /// p = 2^{192} − 2^{64} - 1 33 | const MODULUS_HEX: &str = "fffffffffffffffffffffffffffffffeffffffffffffffff"; 34 | 35 | primefield::monty_field_params! { 36 | name: FieldParams, 37 | modulus: MODULUS_HEX, 38 | uint: U192, 39 | byte_order: primefield::ByteOrder::BigEndian, 40 | multiplicative_generator: 11, 41 | doc: "Montgomery parameters for the NIST P-192 field modulus: `p = 2^{192} − 2^{64} - 1`." 42 | } 43 | 44 | primefield::monty_field_element! { 45 | name: FieldElement, 46 | params: FieldParams, 47 | uint: U192, 48 | doc: "Element in the finite field modulo `p = 2^{192} − 2^{64} - 1`." 49 | } 50 | 51 | primefield::monty_field_fiat_arithmetic! { 52 | name: FieldElement, 53 | params: FieldParams, 54 | uint: U192, 55 | non_mont: fiat_p192_non_montgomery_domain_field_element, 56 | mont: fiat_p192_montgomery_domain_field_element, 57 | from_mont: fiat_p192_from_montgomery, 58 | to_mont: fiat_p192_to_montgomery, 59 | add: fiat_p192_add, 60 | sub: fiat_p192_sub, 61 | mul: fiat_p192_mul, 62 | neg: fiat_p192_opp, 63 | square: fiat_p192_square, 64 | divstep_precomp: fiat_p192_divstep_precomp, 65 | divstep: fiat_p192_divstep, 66 | msat: fiat_p192_msat, 67 | selectnz: fiat_p192_selectznz 68 | } 69 | 70 | #[cfg(test)] 71 | mod tests { 72 | use super::{FieldElement, U192}; 73 | primefield::test_primefield!(FieldElement, U192); 74 | } 75 | -------------------------------------------------------------------------------- /bp256/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377 2 | //! 3 | //! Arithmetic implementations have been synthesized using fiat-crypto. 4 | //! 5 | //! # License 6 | //! 7 | //! Copyright (c) 2015-2020 the fiat-crypto authors 8 | //! 9 | //! fiat-crypto is distributed under the terms of the MIT License, the 10 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 11 | //! users may pick which license to apply. 12 | 13 | #[cfg_attr(target_pointer_width = "32", path = "field/bp256_32.rs")] 14 | #[cfg_attr(target_pointer_width = "64", path = "field/bp256_64.rs")] 15 | #[allow( 16 | clippy::identity_op, 17 | clippy::needless_lifetimes, 18 | clippy::unnecessary_cast, 19 | clippy::too_many_arguments 20 | )] 21 | #[allow(dead_code)] // TODO(tarcieri): remove this when we can use `const _` to silence warnings 22 | mod field_impl; 23 | 24 | use self::field_impl::*; 25 | use crate::U256; 26 | use elliptic_curve::{ 27 | ff::PrimeField, 28 | subtle::{Choice, ConstantTimeEq, CtOption}, 29 | }; 30 | 31 | /// Constant representing the modulus serialized as hex. 32 | const MODULUS_HEX: &str = "a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377"; 33 | 34 | primefield::monty_field_params! { 35 | name: FieldParams, 36 | modulus: MODULUS_HEX, 37 | uint: U256, 38 | byte_order: primefield::ByteOrder::BigEndian, 39 | multiplicative_generator: 11, 40 | doc: "Montgomery parameters for brainpoolP256's field modulus" 41 | } 42 | 43 | primefield::monty_field_element! { 44 | name: FieldElement, 45 | params: FieldParams, 46 | uint: U256, 47 | doc: "Element in the brainpoolP256 finite field modulo p" 48 | } 49 | 50 | primefield::monty_field_fiat_arithmetic! { 51 | name: FieldElement, 52 | params: FieldParams, 53 | uint: U256, 54 | non_mont: fiat_bp256_non_montgomery_domain_field_element, 55 | mont: fiat_bp256_montgomery_domain_field_element, 56 | from_mont: fiat_bp256_from_montgomery, 57 | to_mont: fiat_bp256_to_montgomery, 58 | add: fiat_bp256_add, 59 | sub: fiat_bp256_sub, 60 | mul: fiat_bp256_mul, 61 | neg: fiat_bp256_opp, 62 | square: fiat_bp256_square, 63 | divstep_precomp: fiat_bp256_divstep_precomp, 64 | divstep: fiat_bp256_divstep, 65 | msat: fiat_bp256_msat, 66 | selectnz: fiat_bp256_selectznz 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use super::{FieldElement, U256}; 72 | primefield::test_primefield!(FieldElement, U256); 73 | } 74 | -------------------------------------------------------------------------------- /.github/workflows/bp256.yml: -------------------------------------------------------------------------------- 1 | name: bp256 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/bp256.yml" 7 | - "bp256/**" 8 | - "primefield/**" 9 | - "primeorder/**" 10 | - "Cargo.*" 11 | push: 12 | branches: master 13 | 14 | defaults: 15 | run: 16 | working-directory: bp256 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | RUSTDOCFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | rust: 34 | - 1.85.0 # MSRV 35 | - stable 36 | target: 37 | - thumbv7em-none-eabi 38 | - wasm32-unknown-unknown 39 | steps: 40 | - uses: actions/checkout@v6 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features 46 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc 47 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features arithmetic 48 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features ecdsa 49 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pem 50 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pkcs8 51 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features serde 52 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features sha256 53 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features ecdsa,pem,pkcs8,serde,sha256 54 | 55 | test: 56 | runs-on: ubuntu-latest 57 | strategy: 58 | matrix: 59 | rust: 60 | - 1.85.0 # MSRV 61 | - stable 62 | steps: 63 | - uses: actions/checkout@v6 64 | - uses: dtolnay/rust-toolchain@master 65 | with: 66 | toolchain: ${{ matrix.rust }} 67 | - run: cargo check --all-features 68 | - run: cargo test --no-default-features 69 | - run: cargo test 70 | - run: cargo test --all-features 71 | -------------------------------------------------------------------------------- /.github/workflows/bp384.yml: -------------------------------------------------------------------------------- 1 | name: bp384 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/bp384.yml" 7 | - "bp384/**" 8 | - "primefield/**" 9 | - "primeorder/**" 10 | - "Cargo.*" 11 | push: 12 | branches: master 13 | 14 | defaults: 15 | run: 16 | working-directory: bp384 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | RUSTDOCFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | rust: 34 | - 1.85.0 # MSRV 35 | - stable 36 | target: 37 | - thumbv7em-none-eabi 38 | - wasm32-unknown-unknown 39 | steps: 40 | - uses: actions/checkout@v6 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features 46 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc 47 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features arithmetic 48 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features ecdsa 49 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pem 50 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pkcs8 51 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features serde 52 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features sha384 53 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features ecdsa,pem,pkcs8,serde,sha384 54 | 55 | test: 56 | runs-on: ubuntu-latest 57 | strategy: 58 | matrix: 59 | rust: 60 | - 1.85.0 # MSRV 61 | - stable 62 | steps: 63 | - uses: actions/checkout@v6 64 | - uses: dtolnay/rust-toolchain@master 65 | with: 66 | toolchain: ${{ matrix.rust }} 67 | - run: cargo check --all-features 68 | - run: cargo test --no-default-features 69 | - run: cargo test 70 | - run: cargo test --all-features 71 | -------------------------------------------------------------------------------- /bignp256/benches/scalar.rs: -------------------------------------------------------------------------------- 1 | //! bign-curve256v1 scalar arithmetic benchmarks 2 | 3 | use bignp256::{ProjectivePoint, Scalar, elliptic_curve::group::ff::PrimeField}; 4 | use criterion::{ 5 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 6 | }; 7 | use hex_literal::hex; 8 | 9 | fn test_scalar_x() -> Scalar { 10 | Scalar::from_repr( 11 | hex!("519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464").into(), 12 | ) 13 | .unwrap() 14 | } 15 | 16 | fn test_scalar_y() -> Scalar { 17 | Scalar::from_repr( 18 | hex!("0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813").into(), 19 | ) 20 | .unwrap() 21 | } 22 | 23 | fn bench_point_mul(group: &mut BenchmarkGroup) { 24 | let p = ProjectivePoint::GENERATOR; 25 | let m = test_scalar_x(); 26 | let s = Scalar::from_repr(m.into()).unwrap(); 27 | group.bench_function("point-scalar mul", |b| b.iter(|| p * s)); 28 | } 29 | 30 | fn bench_scalar_sub(group: &mut BenchmarkGroup) { 31 | let x = test_scalar_x(); 32 | let y = test_scalar_y(); 33 | group.bench_function("sub", |b| b.iter(|| x - y)); 34 | } 35 | 36 | fn bench_scalar_add(group: &mut BenchmarkGroup) { 37 | let x = test_scalar_x(); 38 | let y = test_scalar_y(); 39 | group.bench_function("add", |b| b.iter(|| x + y)); 40 | } 41 | 42 | fn bench_scalar_mul(group: &mut BenchmarkGroup) { 43 | let x = test_scalar_x(); 44 | let y = test_scalar_y(); 45 | group.bench_function("mul", |b| b.iter(|| x * y)); 46 | } 47 | 48 | fn bench_scalar_negate(group: &mut BenchmarkGroup) { 49 | let x = test_scalar_x(); 50 | group.bench_function("negate", |b| b.iter(|| -x)); 51 | } 52 | 53 | fn bench_scalar_invert(group: &mut BenchmarkGroup) { 54 | let x = test_scalar_x(); 55 | group.bench_function("invert", |b| b.iter(|| x.invert())); 56 | } 57 | 58 | fn bench_point(c: &mut Criterion) { 59 | let mut group = c.benchmark_group("point operations"); 60 | bench_point_mul(&mut group); 61 | group.finish(); 62 | } 63 | 64 | fn bench_scalar(c: &mut Criterion) { 65 | let mut group = c.benchmark_group("scalar operations"); 66 | bench_scalar_sub(&mut group); 67 | bench_scalar_add(&mut group); 68 | bench_scalar_mul(&mut group); 69 | bench_scalar_negate(&mut group); 70 | bench_scalar_invert(&mut group); 71 | group.finish(); 72 | } 73 | 74 | criterion_group!(benches, bench_point, bench_scalar); 75 | criterion_main!(benches); 76 | -------------------------------------------------------------------------------- /p256/benches/scalar.rs: -------------------------------------------------------------------------------- 1 | //! secp256r1 scalar arithmetic benchmarks 2 | 3 | use criterion::{ 4 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 5 | }; 6 | use hex_literal::hex; 7 | use p256::{ProjectivePoint, Scalar, elliptic_curve::group::ff::PrimeField}; 8 | 9 | fn test_scalar_x() -> Scalar { 10 | Scalar::from_repr( 11 | hex!("519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464").into(), 12 | ) 13 | .unwrap() 14 | } 15 | 16 | fn test_scalar_y() -> Scalar { 17 | Scalar::from_repr( 18 | hex!("0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813").into(), 19 | ) 20 | .unwrap() 21 | } 22 | 23 | fn bench_point_mul(group: &mut BenchmarkGroup<'_, M>) { 24 | let p = ProjectivePoint::GENERATOR; 25 | let m = test_scalar_x(); 26 | let s = Scalar::from_repr(m.into()).unwrap(); 27 | group.bench_function("point-scalar mul", |b| b.iter(|| p * s)); 28 | } 29 | 30 | fn bench_scalar_sub(group: &mut BenchmarkGroup<'_, M>) { 31 | let x = test_scalar_x(); 32 | let y = test_scalar_y(); 33 | group.bench_function("sub", |b| b.iter(|| x - y)); 34 | } 35 | 36 | fn bench_scalar_add(group: &mut BenchmarkGroup<'_, M>) { 37 | let x = test_scalar_x(); 38 | let y = test_scalar_y(); 39 | group.bench_function("add", |b| b.iter(|| x + y)); 40 | } 41 | 42 | fn bench_scalar_mul(group: &mut BenchmarkGroup<'_, M>) { 43 | let x = test_scalar_x(); 44 | let y = test_scalar_y(); 45 | group.bench_function("mul", |b| b.iter(|| x * y)); 46 | } 47 | 48 | fn bench_scalar_negate(group: &mut BenchmarkGroup<'_, M>) { 49 | let x = test_scalar_x(); 50 | group.bench_function("negate", |b| b.iter(|| -x)); 51 | } 52 | 53 | fn bench_scalar_invert(group: &mut BenchmarkGroup<'_, M>) { 54 | let x = test_scalar_x(); 55 | group.bench_function("invert", |b| b.iter(|| x.invert())); 56 | } 57 | 58 | fn bench_point(c: &mut Criterion) { 59 | let mut group = c.benchmark_group("point operations"); 60 | bench_point_mul(&mut group); 61 | group.finish(); 62 | } 63 | 64 | fn bench_scalar(c: &mut Criterion) { 65 | let mut group = c.benchmark_group("scalar operations"); 66 | bench_scalar_sub(&mut group); 67 | bench_scalar_add(&mut group); 68 | bench_scalar_mul(&mut group); 69 | bench_scalar_negate(&mut group); 70 | bench_scalar_invert(&mut group); 71 | group.finish(); 72 | } 73 | 74 | criterion_group!(benches, bench_point, bench_scalar); 75 | criterion_main!(benches); 76 | -------------------------------------------------------------------------------- /bp384/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53 2 | //! 3 | //! Arithmetic implementations have been synthesized using fiat-crypto. 4 | //! 5 | //! # License 6 | //! 7 | //! Copyright (c) 2015-2020 the fiat-crypto authors 8 | //! 9 | //! fiat-crypto is distributed under the terms of the MIT License, the 10 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 11 | //! users may pick which license to apply. 12 | 13 | #[cfg_attr(target_pointer_width = "32", path = "field/bp384_32.rs")] 14 | #[cfg_attr(target_pointer_width = "64", path = "field/bp384_64.rs")] 15 | #[allow( 16 | clippy::identity_op, 17 | clippy::needless_lifetimes, 18 | clippy::unnecessary_cast, 19 | clippy::too_many_arguments 20 | )] 21 | #[allow(dead_code)] // TODO(tarcieri): remove this when we can use `const _` to silence warnings 22 | mod field_impl; 23 | 24 | use self::field_impl::*; 25 | use crate::U384; 26 | use elliptic_curve::{ 27 | ff::PrimeField, 28 | subtle::{Choice, ConstantTimeEq, CtOption}, 29 | }; 30 | 31 | /// Constant representing the modulus serialized as hex. 32 | const MODULUS_HEX: &str = "8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53"; 33 | 34 | primefield::monty_field_params! { 35 | name: FieldParams, 36 | modulus: MODULUS_HEX, 37 | uint: U384, 38 | byte_order: primefield::ByteOrder::BigEndian, 39 | multiplicative_generator: 3, 40 | doc: "Montgomery parameters for brainpoolP384's field modulus" 41 | } 42 | 43 | primefield::monty_field_element! { 44 | name: FieldElement, 45 | params: FieldParams, 46 | uint: U384, 47 | doc: "Element in the brainpoolP256 finite field modulo p" 48 | } 49 | 50 | primefield::monty_field_fiat_arithmetic! { 51 | name: FieldElement, 52 | params: FieldParams, 53 | uint: U384, 54 | non_mont: fiat_bp384_non_montgomery_domain_field_element, 55 | mont: fiat_bp384_montgomery_domain_field_element, 56 | from_mont: fiat_bp384_from_montgomery, 57 | to_mont: fiat_bp384_to_montgomery, 58 | add: fiat_bp384_add, 59 | sub: fiat_bp384_sub, 60 | mul: fiat_bp384_mul, 61 | neg: fiat_bp384_opp, 62 | square: fiat_bp384_square, 63 | divstep_precomp: fiat_bp384_divstep_precomp, 64 | divstep: fiat_bp384_divstep, 65 | msat: fiat_bp384_msat, 66 | selectnz: fiat_bp384_selectznz 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use super::{FieldElement, U384}; 72 | primefield::test_primefield!(FieldElement, U384); 73 | } 74 | -------------------------------------------------------------------------------- /p384/benches/scalar.rs: -------------------------------------------------------------------------------- 1 | //! secp384r1 scalar arithmetic benchmarks 2 | 3 | use criterion::{ 4 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 5 | }; 6 | use hex_literal::hex; 7 | use p384::{ProjectivePoint, Scalar, elliptic_curve::group::ff::PrimeField}; 8 | 9 | fn test_scalar_x() -> Scalar { 10 | Scalar::from_repr( 11 | hex!("201b432d8df14324182d6261db3e4b3f46a8284482d52e370da41e6cbdf45ec2952f5db7ccbce3bc29449f4fb080ac97").into() 12 | ).unwrap() 13 | } 14 | 15 | fn test_scalar_y() -> Scalar { 16 | Scalar::from_repr( 17 | hex!("23d9f4ea6d87b7d6163d64256e3449255db14786401a51daa7847161bf56d494325ad2ac8ba928394e01061d882c3528").into() 18 | ).unwrap() 19 | } 20 | 21 | fn bench_point_mul(group: &mut BenchmarkGroup<'_, M>) { 22 | let p = ProjectivePoint::GENERATOR; 23 | let m = test_scalar_x(); 24 | let s = Scalar::from_repr(m.into()).unwrap(); 25 | group.bench_function("point-scalar mul", |b| b.iter(|| p * s)); 26 | } 27 | 28 | fn bench_scalar_sub(group: &mut BenchmarkGroup<'_, M>) { 29 | let x = test_scalar_x(); 30 | let y = test_scalar_y(); 31 | group.bench_function("sub", |b| b.iter(|| x - y)); 32 | } 33 | 34 | fn bench_scalar_add(group: &mut BenchmarkGroup<'_, M>) { 35 | let x = test_scalar_x(); 36 | let y = test_scalar_y(); 37 | group.bench_function("add", |b| b.iter(|| x + y)); 38 | } 39 | 40 | fn bench_scalar_mul(group: &mut BenchmarkGroup<'_, M>) { 41 | let x = test_scalar_x(); 42 | let y = test_scalar_y(); 43 | group.bench_function("mul", |b| b.iter(|| x * y)); 44 | } 45 | 46 | fn bench_scalar_negate(group: &mut BenchmarkGroup<'_, M>) { 47 | let x = test_scalar_x(); 48 | group.bench_function("negate", |b| b.iter(|| -x)); 49 | } 50 | 51 | fn bench_scalar_invert(group: &mut BenchmarkGroup<'_, M>) { 52 | let x = test_scalar_x(); 53 | group.bench_function("invert", |b| b.iter(|| x.invert())); 54 | } 55 | 56 | fn bench_point(c: &mut Criterion) { 57 | let mut group = c.benchmark_group("point operations"); 58 | bench_point_mul(&mut group); 59 | group.finish(); 60 | } 61 | 62 | fn bench_scalar(c: &mut Criterion) { 63 | let mut group = c.benchmark_group("scalar operations"); 64 | bench_scalar_sub(&mut group); 65 | bench_scalar_add(&mut group); 66 | bench_scalar_mul(&mut group); 67 | bench_scalar_negate(&mut group); 68 | bench_scalar_invert(&mut group); 69 | group.finish(); 70 | } 71 | 72 | criterion_group!(benches, bench_point, bench_scalar); 73 | criterion_main!(benches); 74 | -------------------------------------------------------------------------------- /p384/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 2^{384} − 2^{128} − 2^{96} + 2^{32} − 1 2 | //! 3 | //! Arithmetic implementations have been synthesized using fiat-crypto. 4 | //! 5 | //! # License 6 | //! 7 | //! Copyright (c) 2015-2020 the fiat-crypto authors 8 | //! 9 | //! fiat-crypto is distributed under the terms of the MIT License, the 10 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 11 | //! users may pick which license to apply. 12 | 13 | // Default backend: fiat-crypto 14 | #[cfg(all(not(p384_backend = "bignum"), target_pointer_width = "32"))] 15 | use fiat_crypto::p384_32::*; 16 | #[cfg(all(not(p384_backend = "bignum"), target_pointer_width = "64"))] 17 | use fiat_crypto::p384_64::*; 18 | 19 | use elliptic_curve::{ 20 | bigint::U384, 21 | ff::PrimeField, 22 | subtle::{Choice, ConstantTimeEq, CtOption}, 23 | }; 24 | 25 | /// Constant representing the modulus 26 | /// p = 2^{384} − 2^{128} − 2^{96} + 2^{32} − 1 27 | const MODULUS_HEX: &str = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff"; 28 | 29 | primefield::monty_field_params! { 30 | name: FieldParams, 31 | modulus: MODULUS_HEX, 32 | uint: U384, 33 | byte_order: primefield::ByteOrder::BigEndian, 34 | multiplicative_generator: 19, 35 | doc: "Montgomery parameters for the NIST P-384 field modulus: `p = 2^{384} − 2^{128} − 2^{96} + 2^{32} − 1`." 36 | } 37 | 38 | primefield::monty_field_element! { 39 | name: FieldElement, 40 | params: FieldParams, 41 | uint: U384, 42 | doc: "Element in the finite field modulo `p = 2^{384} − 2^{128} − 2^{96} + 2^{32} − 1`." 43 | } 44 | 45 | #[cfg(p384_backend = "bignum")] 46 | primefield::monty_field_arithmetic! { 47 | name: FieldElement, 48 | params: FieldParams, 49 | uint: U384 50 | } 51 | 52 | #[cfg(not(p384_backend = "bignum"))] 53 | primefield::monty_field_fiat_arithmetic! { 54 | name: FieldElement, 55 | params: FieldParams, 56 | uint: U384, 57 | non_mont: fiat_p384_non_montgomery_domain_field_element, 58 | mont: fiat_p384_montgomery_domain_field_element, 59 | from_mont: fiat_p384_from_montgomery, 60 | to_mont: fiat_p384_to_montgomery, 61 | add: fiat_p384_add, 62 | sub: fiat_p384_sub, 63 | mul: fiat_p384_mul, 64 | neg: fiat_p384_opp, 65 | square: fiat_p384_square, 66 | divstep_precomp: fiat_p384_divstep_precomp, 67 | divstep: fiat_p384_divstep, 68 | msat: fiat_p384_msat, 69 | selectnz: fiat_p384_selectznz 70 | } 71 | 72 | #[cfg(test)] 73 | mod tests { 74 | use super::{FieldElement, U384}; 75 | primefield::test_primefield!(FieldElement, U384); 76 | } 77 | -------------------------------------------------------------------------------- /p521/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.14.0 (UNRELEASED) 8 | ### Added 9 | - `elliptic_curve::ops::Invert` implementation ([#971]) 10 | - make `LooseFieldElement` pub ([#978]) 11 | 12 | ### Changed 13 | - merge `u576_to_le_bytes` into `FieldBytes::from_uint_unchecked` ([#969]) 14 | - switch to upstream RFC6979-based ECDSA ([#1016]) 15 | - Update to `elliptic-curve` v0.14 ([#1011]) 16 | - Update to `ecdsa` v0.17 ([#1011]) 17 | - Update to `sec1` v0.8 ([#1011]) 18 | - Update to `secdect` v0.3 ([#1084]) 19 | - Update to `rand_core` v0.9 ([#1125]) 20 | - Update to `hybrid-array` v0.3 ([#1125]) 21 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1125]) 22 | - Relax MSRV policy and allow MSRV bumps in patch releases 23 | 24 | [#969]: https://github.com/RustCrypto/elliptic-curves/pull/969 25 | [#971]: https://github.com/RustCrypto/elliptic-curves/pull/971 26 | [#978]: https://github.com/RustCrypto/elliptic-curves/pull/978 27 | [#1011]: https://github.com/RustCrypto/elliptic-curves/pull/1011 28 | [#1016]: https://github.com/RustCrypto/elliptic-curves/pull/1016 29 | [#1084]: https://github.com/RustCrypto/elliptic-curves/pull/1084 30 | [#1125]: https://github.com/RustCrypto/elliptic-curves/pull/1125 31 | 32 | ## 0.13.3 (2023-11-11) 33 | ### Added 34 | - Implement hash2curve ([#964]) 35 | 36 | ### Fixed 37 | - Panics when decoding `FieldElement`s ([#967]) 38 | 39 | [#964]: https://github.com/RustCrypto/elliptic-curves/pull/964 40 | [#967]: https://github.com/RustCrypto/elliptic-curves/pull/967 41 | 42 | ## 0.13.2 (2023-11-09) 43 | ### Added 44 | - `serde` feature ([#962]) 45 | 46 | ### Changed 47 | - Remove `pub` from `arithmetic` module ([#961]) 48 | 49 | [#961]: https://github.com/RustCrypto/elliptic-curves/pull/961 50 | [#962]: https://github.com/RustCrypto/elliptic-curves/pull/962 51 | 52 | ## 0.13.1 (2023-11-09) [YANKED] 53 | ### Added 54 | - Bernstein-Yang scalar inversions ([#786]) 55 | - VOPRF support ([#924]) 56 | - `arithmetic` feature ([#953]) 57 | - `ecdh` feature ([#954]) 58 | - `ecdsa` feature ([#956]) 59 | 60 | [#786]: https://github.com/RustCrypto/elliptic-curves/pull/786 61 | [#924]: https://github.com/RustCrypto/elliptic-curves/pull/924 62 | [#953]: https://github.com/RustCrypto/elliptic-curves/pull/953 63 | [#954]: https://github.com/RustCrypto/elliptic-curves/pull/954 64 | [#956]: https://github.com/RustCrypto/elliptic-curves/pull/956 65 | 66 | ## 0.13.0 (2023-03-03) [YANKED] 67 | - Initial release 68 | -------------------------------------------------------------------------------- /bignp256/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bignp256" 3 | version = "0.14.0-rc.1" 4 | description = """ 5 | Pure Rust implementation of the Bign P-256 (a.k.a. bign-curve256v1) 6 | elliptic curve as defined in STB 34.101.45-2013, with 7 | general purpose curve arithmetic 8 | """ 9 | authors = ["RustCrypto Developers"] 10 | license = "Apache-2.0 OR MIT" 11 | documentation = "https://docs.rs/bignp256" 12 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/bignp256" 13 | repository = "https://github.com/RustCrypto/elliptic-curves" 14 | readme = "README.md" 15 | categories = ["cryptography", "no-std"] 16 | keywords = ["crypto", "ecc", "stb", "bign-curve256v1", "bignp256"] 17 | edition = "2024" 18 | rust-version = "1.85" 19 | 20 | [dependencies] 21 | elliptic-curve = { version = "0.14.0-rc.17", features = ["sec1"] } 22 | 23 | # optional dependencies 24 | belt-hash = { version = "0.2.0-rc.0", optional = true, default-features = false } 25 | der = { version = "0.8.0-rc.10" } 26 | digest = { version = "0.11.0-rc.4", optional = true } 27 | hex-literal = { version = "1", optional = true } 28 | hkdf = { version = "0.13.0-rc.3", optional = true } 29 | hmac = { version = "0.13.0-rc.3", optional = true } 30 | rand_core = "0.10.0-rc-2" 31 | rfc6979 = { version = "0.5.0-rc.3", optional = true } 32 | pkcs8 = { version = "0.11.0-rc.8", optional = true } 33 | primefield = { version = "0.14.0-rc.1", optional = true } 34 | primeorder = { version = "0.14.0-rc.1", optional = true } 35 | sec1 = { version = "0.8.0-rc.10", optional = true } 36 | signature = { version = "3.0.0-rc.5", optional = true } 37 | 38 | [dev-dependencies] 39 | criterion = "0.7" 40 | hex-literal = "1" 41 | primeorder = { version = "0.14.0-rc.1", features = ["dev"] } 42 | proptest = "1" 43 | rand = "0.10.0-rc.1" 44 | hex = { version = "0.4" } 45 | 46 | [features] 47 | default = ["ecdh", "ecdsa", "pem", "std"] 48 | alloc = ["elliptic-curve/alloc", "primeorder?/alloc"] 49 | std = ["alloc", "elliptic-curve/std", "getrandom"] 50 | 51 | arithmetic = ["dep:primefield", "dep:primeorder", "elliptic-curve/arithmetic"] 52 | bits = ["arithmetic", "elliptic-curve/bits"] 53 | ecdsa = ["arithmetic", "dep:rfc6979", "dep:signature", "dep:belt-hash"] 54 | getrandom = ["elliptic-curve/getrandom"] 55 | pem = ["pkcs8/pem", "sec1/pem"] 56 | pkcs8 = ["dep:pkcs8"] 57 | ecdh = ["arithmetic", "elliptic-curve/ecdh", "dep:digest", "dep:hkdf", "dep:hmac", "dep:belt-hash", "alloc"] 58 | serde = ["elliptic-curve/serde", "primeorder?/serde"] 59 | test-vectors = ["dep:hex-literal"] 60 | 61 | [[bench]] 62 | name = "field" 63 | harness = false 64 | 65 | [[bench]] 66 | name = "scalar" 67 | harness = false 68 | 69 | [package.metadata.docs.rs] 70 | all-features = true 71 | -------------------------------------------------------------------------------- /p224/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.14.0 (UNRELEASED) 8 | ### Added 9 | - `bits` feature ([#868]) 10 | - `Scalar::sqrt` implementation ([#904]) 11 | - `elliptic_curve::ops::Invert` implementation ([#971]) 12 | 13 | ## Changed 14 | - Update to `elliptic-curve` v0.14 ([#1011]) 15 | - Update to `ecdsa` v0.17 ([#1011]) 16 | - Update to `sec1` v0.8 ([#1011]) 17 | - Update to `secdect` v0.3 ([#1084]) 18 | - Update to `rand_core` v0.9 ([#1125]) 19 | - Update to `hybrid-array` v0.3 ([#1125]) 20 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1125]) 21 | - Relax MSRV policy and allow MSRV bumps in patch releases 22 | 23 | [#868]: https://github.com/RustCrypto/elliptic-curves/pull/868 24 | [#904]: https://github.com/RustCrypto/elliptic-curves/pull/904 25 | [#971]: https://github.com/RustCrypto/elliptic-curves/pull/971 26 | [#1011]: https://github.com/RustCrypto/elliptic-curves/pull/1011 27 | [#1084]: https://github.com/RustCrypto/elliptic-curves/pull/1084 28 | [#1125]: https://github.com/RustCrypto/elliptic-curves/pull/1125 29 | 30 | ## 0.13.2 (2023-04-15) 31 | ### Changed 32 | - Enable `arithmetic` and `ecdsa` by default ([#833]) 33 | 34 | ### Fixed 35 | - Have `serde` feature enable `primeorder/serde` ([#851]) 36 | 37 | [#833]: https://github.com/RustCrypto/elliptic-curves/pull/833 38 | [#851]: https://github.com/RustCrypto/elliptic-curves/pull/851 39 | 40 | ## 0.13.1 (2023-04-09) 41 | ### Added 42 | - Projective arithmetic tests ([#813]) 43 | - `ecdh` feature ([#814]) 44 | - `arithmetic` feature ([#815]) 45 | - `ecdsa` feature ([#816]) 46 | - FIPS 186-4 ECDSA test vectors ([#817]) 47 | - Wycheproof test vectors ([#818]) 48 | - Bump `primeorder` to v0.13.1 ([#819]) 49 | 50 | ### Changed 51 | - Better `Debug` for field elements ([#798]) 52 | - Make `primeorder` dependency optional ([#799]) 53 | 54 | [#798]: https://github.com/RustCrypto/elliptic-curves/pull/798 55 | [#799]: https://github.com/RustCrypto/elliptic-curves/pull/799 56 | [#813]: https://github.com/RustCrypto/elliptic-curves/pull/813 57 | [#814]: https://github.com/RustCrypto/elliptic-curves/pull/814 58 | [#815]: https://github.com/RustCrypto/elliptic-curves/pull/815 59 | [#816]: https://github.com/RustCrypto/elliptic-curves/pull/816 60 | [#817]: https://github.com/RustCrypto/elliptic-curves/pull/817 61 | [#818]: https://github.com/RustCrypto/elliptic-curves/pull/818 62 | [#819]: https://github.com/RustCrypto/elliptic-curves/pull/819 63 | 64 | ## 0.13.0 (2023-03-03) 65 | - Initial release 66 | -------------------------------------------------------------------------------- /p224/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 2^{224} − 2^{96} + 1 2 | //! 3 | //! Arithmetic implementations have been synthesized using fiat-crypto. 4 | //! 5 | //! # License 6 | //! 7 | //! Copyright (c) 2015-2020 the fiat-crypto authors 8 | //! 9 | //! fiat-crypto is distributed under the terms of the MIT License, the 10 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 11 | //! users may pick which license to apply. 12 | 13 | #[cfg_attr(target_pointer_width = "32", path = "field/p224_32.rs")] 14 | #[cfg_attr(target_pointer_width = "64", path = "field/p224_64.rs")] 15 | #[allow( 16 | clippy::identity_op, 17 | clippy::needless_lifetimes, 18 | clippy::unnecessary_cast, 19 | clippy::too_many_arguments 20 | )] 21 | #[allow(dead_code)] // TODO(tarcieri): remove this when we can use `const _` to silence warnings 22 | mod field_impl; 23 | 24 | use self::field_impl::*; 25 | use crate::Uint; 26 | use elliptic_curve::{ 27 | ff::PrimeField, 28 | subtle::{Choice, ConstantTimeEq, CtOption}, 29 | }; 30 | 31 | /// Constant representing the modulus serialized as hex. 32 | /// p = 2^{224} − 2^{96} + 1 33 | #[cfg(target_pointer_width = "32")] 34 | const MODULUS_HEX: &str = "ffffffffffffffffffffffffffffffff000000000000000000000001"; 35 | #[cfg(target_pointer_width = "64")] 36 | const MODULUS_HEX: &str = "00000000ffffffffffffffffffffffffffffffff000000000000000000000001"; 37 | 38 | primefield::monty_field_params! { 39 | name: FieldParams, 40 | modulus: MODULUS_HEX, 41 | uint: Uint, 42 | byte_order: primefield::ByteOrder::BigEndian, 43 | multiplicative_generator: 22, 44 | doc: "Montgomery parameters for the NIST P-224 field modulus: `p = 2^{224} − 2^{96} + 1`." 45 | } 46 | 47 | primefield::monty_field_element! { 48 | name: FieldElement, 49 | params: FieldParams, 50 | uint: Uint, 51 | doc: "Element in the finite field modulo `p = 2^{224} − 2^{96} + 1`." 52 | } 53 | 54 | primefield::monty_field_fiat_arithmetic! { 55 | name: FieldElement, 56 | params: FieldParams, 57 | uint: Uint, 58 | non_mont: fiat_p224_non_montgomery_domain_field_element, 59 | mont: fiat_p224_montgomery_domain_field_element, 60 | from_mont: fiat_p224_from_montgomery, 61 | to_mont: fiat_p224_to_montgomery, 62 | add: fiat_p224_add, 63 | sub: fiat_p224_sub, 64 | mul: fiat_p224_mul, 65 | neg: fiat_p224_opp, 66 | square: fiat_p224_square, 67 | divstep_precomp: fiat_p224_divstep_precomp, 68 | divstep: fiat_p224_divstep, 69 | msat: fiat_p224_msat, 70 | selectnz: fiat_p224_selectznz 71 | } 72 | 73 | #[cfg(test)] 74 | mod tests { 75 | use super::{FieldElement, Uint}; 76 | primefield::test_primefield!(FieldElement, Uint); 77 | } 78 | -------------------------------------------------------------------------------- /p521/benches/scalar.rs: -------------------------------------------------------------------------------- 1 | //! secp521r1 scalar arithmetic benchmarks 2 | 3 | use criterion::{ 4 | BenchmarkGroup, Criterion, criterion_group, criterion_main, measurement::Measurement, 5 | }; 6 | use hex_literal::hex; 7 | use p521::{ProjectivePoint, Scalar, elliptic_curve::group::ff::PrimeField}; 8 | use std::hint::black_box; 9 | 10 | fn test_scalar_x() -> Scalar { 11 | black_box(Scalar::from_repr( 12 | hex!("01d7bb864c5b5ecae019296cf9b5c63a166f5f1113942819b1933d889a96d12245777a99428f93de4fc9a18d709bf91889d7f8dddd522b4c364aeae13c983e9fae46").into() 13 | ).unwrap()) 14 | } 15 | 16 | fn test_scalar_y() -> Scalar { 17 | black_box(Scalar::from_repr( 18 | hex!("017e49b8ea8f9d1b7c0378e378a7a42e68e12cf78779ed41dcd29a090ae7e0f883b0d0f2cbc8f0473c0ad6732bea40d371a7f363bc6537d075bd1a4c23e558b0bc73").into() 19 | ).unwrap()) 20 | } 21 | 22 | fn bench_point_mul(group: &mut BenchmarkGroup<'_, M>) { 23 | let p = ProjectivePoint::GENERATOR; 24 | let m = test_scalar_x(); 25 | let s = Scalar::from_repr(m.into()).unwrap(); 26 | group.bench_function("point-scalar mul", |b| b.iter(|| p * s)); 27 | } 28 | 29 | fn bench_scalar_sub(group: &mut BenchmarkGroup<'_, M>) { 30 | let x = test_scalar_x(); 31 | let y = test_scalar_y(); 32 | group.bench_function("sub", |b| b.iter(|| x - y)); 33 | } 34 | 35 | fn bench_scalar_add(group: &mut BenchmarkGroup<'_, M>) { 36 | let x = test_scalar_x(); 37 | let y = test_scalar_y(); 38 | group.bench_function("add", |b| b.iter(|| x + y)); 39 | } 40 | 41 | fn bench_scalar_mul(group: &mut BenchmarkGroup<'_, M>) { 42 | let x = test_scalar_x(); 43 | let y = test_scalar_y(); 44 | group.bench_function("mul", |b| b.iter(|| x * y)); 45 | } 46 | 47 | fn bench_scalar_negate(group: &mut BenchmarkGroup<'_, M>) { 48 | let x = test_scalar_x(); 49 | group.bench_function("negate", |b| b.iter(|| -x)); 50 | } 51 | 52 | fn bench_scalar_invert(group: &mut BenchmarkGroup<'_, M>) { 53 | let x = test_scalar_x(); 54 | group.bench_function("invert", |b| b.iter(|| x.invert())); 55 | } 56 | 57 | fn bench_point(c: &mut Criterion) { 58 | let mut group = c.benchmark_group("point operations"); 59 | bench_point_mul(&mut group); 60 | group.finish(); 61 | } 62 | 63 | fn bench_scalar(c: &mut Criterion) { 64 | let mut group = c.benchmark_group("scalar operations"); 65 | bench_scalar_sub(&mut group); 66 | bench_scalar_add(&mut group); 67 | bench_scalar_mul(&mut group); 68 | bench_scalar_negate(&mut group); 69 | bench_scalar_invert(&mut group); 70 | group.finish(); 71 | } 72 | 73 | criterion_group!(benches, bench_point, bench_scalar); 74 | criterion_main!(benches); 75 | -------------------------------------------------------------------------------- /bignp256/src/arithmetic/field.rs: -------------------------------------------------------------------------------- 1 | //! Field arithmetic modulo p = 2^{256} − 189 2 | //! 3 | //! Arithmetic implementations are extracted Rust code from the Coq fiat-crypto 4 | //! libraries. 5 | //! 6 | //! # License 7 | //! 8 | //! Copyright (c) 2015-2020 the fiat-crypto authors 9 | //! 10 | //! fiat-crypto is distributed under the terms of the MIT License, the 11 | //! Apache License (Version 2.0), and the BSD 1-Clause License; 12 | //! users may pick which license to apply. 13 | 14 | #![allow(clippy::arithmetic_side_effects)] 15 | 16 | #[cfg_attr(target_pointer_width = "32", path = "field/bignp256_32.rs")] 17 | #[cfg_attr(target_pointer_width = "64", path = "field/bignp256_64.rs")] 18 | #[allow( 19 | clippy::cast_possible_truncation, 20 | clippy::cast_possible_wrap, 21 | clippy::cast_sign_loss, 22 | clippy::identity_op, 23 | clippy::needless_lifetimes, 24 | clippy::unnecessary_cast, 25 | clippy::too_many_arguments 26 | )] 27 | #[allow(dead_code)] // TODO(tarcieri): remove this when we can use `const _` to silence warnings 28 | mod field_impl; 29 | 30 | use self::field_impl::*; 31 | use crate::U256; 32 | use elliptic_curve::{ 33 | ff::PrimeField, 34 | subtle::{Choice, ConstantTimeEq, CtOption}, 35 | }; 36 | 37 | /// Constant representing the modulus: p = 2^{256} − 189 38 | const MODULUS_HEX: &str = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43"; 39 | 40 | primefield::monty_field_params! { 41 | name: FieldParams, 42 | modulus: MODULUS_HEX, 43 | uint: U256, 44 | byte_order: primefield::ByteOrder::BigEndian, 45 | multiplicative_generator: 2, 46 | doc: "Montgomery parameters for the bign-curve256v1 field modulus p = 2^{256} − 189" 47 | } 48 | 49 | primefield::monty_field_element! { 50 | name: FieldElement, 51 | params: FieldParams, 52 | uint: U256, 53 | doc: "Element in the bign-curve256v1 finite field modulo p = 2^{256} − 189" 54 | } 55 | 56 | primefield::monty_field_fiat_arithmetic! { 57 | name: FieldElement, 58 | params: FieldParams, 59 | uint: U256, 60 | non_mont: fiat_bignp256_non_montgomery_domain_field_element, 61 | mont: fiat_bignp256_montgomery_domain_field_element, 62 | from_mont: fiat_bignp256_from_montgomery, 63 | to_mont: fiat_bignp256_to_montgomery, 64 | add: fiat_bignp256_add, 65 | sub: fiat_bignp256_sub, 66 | mul: fiat_bignp256_mul, 67 | neg: fiat_bignp256_opp, 68 | square: fiat_bignp256_square, 69 | divstep_precomp: fiat_bignp256_divstep_precomp, 70 | divstep: fiat_bignp256_divstep, 71 | msat: fiat_bignp256_msat, 72 | selectnz: fiat_bignp256_selectznz 73 | } 74 | 75 | #[cfg(test)] 76 | mod tests { 77 | use super::{FieldElement, U256}; 78 | primefield::test_primefield!(FieldElement, U256); 79 | } 80 | -------------------------------------------------------------------------------- /p384/tests/affine.rs: -------------------------------------------------------------------------------- 1 | //! Affine arithmetic tests. 2 | 3 | // TODO(tarcieri): point compaction support 4 | 5 | #![cfg(all(feature = "arithmetic", feature = "test-vectors"))] 6 | 7 | use elliptic_curve::{ 8 | group::{GroupEncoding, prime::PrimeCurveAffine}, 9 | sec1::{FromEncodedPoint, ToEncodedPoint}, 10 | }; 11 | use hex_literal::hex; 12 | 13 | use p384::{AffinePoint, EncodedPoint}; 14 | 15 | const UNCOMPRESSED_BASEPOINT: &[u8] = &hex!( 16 | "04 aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 17 | 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7 18 | 3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c 19 | e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f" 20 | ); 21 | 22 | const COMPRESSED_BASEPOINT: &[u8] = &hex!( 23 | "03 aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 24 | 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7" 25 | ); 26 | 27 | #[test] 28 | fn uncompressed_round_trip() { 29 | let pubkey = EncodedPoint::from_bytes(UNCOMPRESSED_BASEPOINT).unwrap(); 30 | let point = AffinePoint::from_encoded_point(&pubkey).unwrap(); 31 | assert_eq!(point, AffinePoint::generator()); 32 | 33 | let res: EncodedPoint = point.into(); 34 | assert_eq!(res, pubkey); 35 | } 36 | 37 | #[test] 38 | fn compressed_round_trip() { 39 | let pubkey = EncodedPoint::from_bytes(COMPRESSED_BASEPOINT).unwrap(); 40 | let point = AffinePoint::from_encoded_point(&pubkey).unwrap(); 41 | assert_eq!(point, AffinePoint::generator()); 42 | 43 | let res: EncodedPoint = point.to_encoded_point(true); 44 | assert_eq!(res, pubkey); 45 | } 46 | 47 | #[test] 48 | fn uncompressed_to_compressed() { 49 | let encoded = EncodedPoint::from_bytes(UNCOMPRESSED_BASEPOINT).unwrap(); 50 | 51 | let res = AffinePoint::from_encoded_point(&encoded) 52 | .unwrap() 53 | .to_encoded_point(true); 54 | 55 | assert_eq!(res.as_bytes(), COMPRESSED_BASEPOINT); 56 | } 57 | 58 | #[test] 59 | fn compressed_to_uncompressed() { 60 | let encoded = EncodedPoint::from_bytes(COMPRESSED_BASEPOINT).unwrap(); 61 | 62 | let res = AffinePoint::from_encoded_point(&encoded) 63 | .unwrap() 64 | .to_encoded_point(false); 65 | 66 | assert_eq!(res.as_bytes(), UNCOMPRESSED_BASEPOINT); 67 | } 68 | 69 | #[test] 70 | fn affine_negation() { 71 | let basepoint = AffinePoint::generator(); 72 | assert_eq!(-(-basepoint), basepoint); 73 | } 74 | 75 | #[test] 76 | fn identity_encoding() { 77 | // This is technically an invalid SEC1 encoding, but is preferable to panicking. 78 | assert_eq!([0; 49], AffinePoint::IDENTITY.to_bytes().as_slice()); 79 | assert!(bool::from( 80 | AffinePoint::from_bytes(&AffinePoint::IDENTITY.to_bytes()) 81 | .unwrap() 82 | .is_identity() 83 | )) 84 | } 85 | -------------------------------------------------------------------------------- /p384/src/arithmetic.rs: -------------------------------------------------------------------------------- 1 | //! Pure Rust implementation of group operations on secp384r1. 2 | //! 3 | //! Curve parameters can be found in [NIST SP 800-186] § G.1.3: Curve P-384. 4 | //! 5 | //! [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final 6 | 7 | pub(crate) mod field; 8 | #[cfg(feature = "hash2curve")] 9 | mod hash2curve; 10 | pub(crate) mod scalar; 11 | 12 | use self::{field::FieldElement, scalar::Scalar}; 13 | use crate::NistP384; 14 | use elliptic_curve::{CurveArithmetic, PrimeCurveArithmetic}; 15 | use primeorder::{PrimeCurveParams, point_arithmetic}; 16 | 17 | /// Elliptic curve point in affine coordinates. 18 | pub type AffinePoint = primeorder::AffinePoint; 19 | 20 | /// Elliptic curve point in projective coordinates. 21 | pub type ProjectivePoint = primeorder::ProjectivePoint; 22 | 23 | impl CurveArithmetic for NistP384 { 24 | type AffinePoint = AffinePoint; 25 | type ProjectivePoint = ProjectivePoint; 26 | type Scalar = Scalar; 27 | } 28 | 29 | impl PrimeCurveArithmetic for NistP384 { 30 | type CurveGroup = ProjectivePoint; 31 | } 32 | 33 | /// Adapted from [NIST SP 800-186] § G.1.3: Curve P-384. 34 | /// 35 | /// [NIST SP 800-186]: https://csrc.nist.gov/publications/detail/sp/800-186/final 36 | impl PrimeCurveParams for NistP384 { 37 | type FieldElement = FieldElement; 38 | type PointArithmetic = point_arithmetic::EquationAIsMinusThree; 39 | 40 | /// a = -3 (0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc) 41 | const EQUATION_A: FieldElement = FieldElement::from_u64(3).neg(); 42 | 43 | /// b = b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 44 | /// 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef 45 | const EQUATION_B: FieldElement = FieldElement::from_hex_vartime( 46 | "b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 47 | ); 48 | 49 | /// Base point of P-384. 50 | /// 51 | /// Defined in NIST SP 800-186 § G.1.3: Curve P-384. 52 | /// 53 | /// ```text 54 | /// Gₓ = aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 55 | /// 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7 56 | /// Gᵧ = 3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c 57 | /// e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f 58 | /// ``` 59 | const GENERATOR: (FieldElement, FieldElement) = ( 60 | FieldElement::from_hex_vartime( 61 | "aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 62 | ), 63 | FieldElement::from_hex_vartime( 64 | "3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 65 | ), 66 | ); 67 | } 68 | -------------------------------------------------------------------------------- /.github/workflows/sm2.yml: -------------------------------------------------------------------------------- 1 | name: sm2 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/sm2.yml" 7 | - "primefield/**" 8 | - "primeorder/**" 9 | - "sm2/**" 10 | - "Cargo.*" 11 | push: 12 | branches: master 13 | 14 | defaults: 15 | run: 16 | working-directory: sm2 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | RUSTDOCFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | rust: 34 | - 1.85.0 # MSRV 35 | - stable 36 | target: 37 | - thumbv7em-none-eabi 38 | - wasm32-unknown-unknown 39 | steps: 40 | - uses: actions/checkout@v6 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features 46 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc 47 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features arithmetic 48 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features pkcs8 49 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,arithmetic,pkcs8 50 | 51 | test: 52 | runs-on: ubuntu-latest 53 | strategy: 54 | matrix: 55 | include: 56 | # 32-bit Linux 57 | - target: i686-unknown-linux-gnu 58 | rust: 1.85.0 # MSRV 59 | deps: sudo apt update && sudo apt install gcc-multilib 60 | - target: i686-unknown-linux-gnu 61 | rust: stable 62 | deps: sudo apt update && sudo apt install gcc-multilib 63 | 64 | # 64-bit Linux 65 | - target: x86_64-unknown-linux-gnu 66 | rust: 1.85.0 # MSRV 67 | - target: x86_64-unknown-linux-gnu 68 | rust: stable 69 | 70 | steps: 71 | - uses: actions/checkout@v6 72 | - uses: dtolnay/rust-toolchain@master 73 | with: 74 | toolchain: ${{ matrix.rust }} 75 | targets: ${{ matrix.target }} 76 | - run: ${{ matrix.deps }} 77 | - run: cargo check --target ${{ matrix.target }} --all-features 78 | - run: cargo test --release --target ${{ matrix.target }} --no-default-features 79 | - run: cargo test --release --target ${{ matrix.target }} 80 | - run: cargo test --release --target ${{ matrix.target }} --all-features 81 | -------------------------------------------------------------------------------- /.github/workflows/p521.yml: -------------------------------------------------------------------------------- 1 | name: p521 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/p521.yml" 7 | - "p521/**" 8 | - "hash2curve/**" 9 | - "primefield/**" 10 | - "primeorder/**" 11 | - "Cargo.*" 12 | push: 13 | branches: master 14 | 15 | defaults: 16 | run: 17 | working-directory: p521 18 | 19 | env: 20 | CARGO_INCREMENTAL: 0 21 | RUSTFLAGS: "-Dwarnings" 22 | RUSTDOCFLAGS: "-Dwarnings" 23 | 24 | # Cancels CI jobs when new commits are pushed to a PR branch 25 | concurrency: 26 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | build: 31 | runs-on: ubuntu-latest 32 | strategy: 33 | matrix: 34 | rust: 35 | - 1.85.0 # MSRV 36 | - stable 37 | target: 38 | - thumbv7em-none-eabi 39 | - wasm32-unknown-unknown 40 | steps: 41 | - uses: actions/checkout@v6 42 | - uses: dtolnay/rust-toolchain@master 43 | with: 44 | toolchain: ${{ matrix.rust }} 45 | targets: ${{ matrix.target }} 46 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features 47 | - run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc 48 | 49 | benches: 50 | runs-on: ubuntu-latest 51 | strategy: 52 | matrix: 53 | rust: 54 | - stable 55 | steps: 56 | - uses: actions/checkout@v6 57 | - uses: dtolnay/rust-toolchain@master 58 | with: 59 | toolchain: ${{ matrix.rust }} 60 | - run: cargo build --all-features --benches 61 | 62 | test: 63 | runs-on: ubuntu-latest 64 | strategy: 65 | matrix: 66 | include: 67 | # 32-bit Linux 68 | - target: i686-unknown-linux-gnu 69 | rust: 1.85.0 # MSRV 70 | deps: sudo apt update && sudo apt install gcc-multilib 71 | - target: i686-unknown-linux-gnu 72 | rust: stable 73 | deps: sudo apt update && sudo apt install gcc-multilib 74 | 75 | # 64-bit Linux 76 | - target: x86_64-unknown-linux-gnu 77 | rust: 1.85.0 # MSRV 78 | - target: x86_64-unknown-linux-gnu 79 | rust: stable 80 | 81 | steps: 82 | - uses: actions/checkout@v6 83 | - uses: dtolnay/rust-toolchain@master 84 | with: 85 | toolchain: ${{ matrix.rust }} 86 | targets: ${{ matrix.target }} 87 | - run: ${{ matrix.deps }} 88 | - run: cargo check --target ${{ matrix.target }} --all-features 89 | - run: cargo test --release --target ${{ matrix.target }} --no-default-features 90 | - run: cargo test --release --target ${{ matrix.target }} 91 | - run: cargo test --release --target ${{ matrix.target }} --all-features 92 | -------------------------------------------------------------------------------- /p521/src/arithmetic/field/loose.rs: -------------------------------------------------------------------------------- 1 | use super::{FieldElement, field_impl::*}; 2 | use core::ops::Mul; 3 | 4 | /// "Loose" field element: unreduced and intended to be followed by an 5 | /// additional operation which will perform a reduction. 6 | pub struct LooseFieldElement(pub(super) fiat_p521_loose_field_element); 7 | 8 | impl LooseFieldElement { 9 | #[cfg(target_pointer_width = "32")] 10 | const LIMBS: usize = 19; 11 | #[cfg(target_pointer_width = "64")] 12 | const LIMBS: usize = 9; 13 | 14 | /// Reduce field element. 15 | #[inline] 16 | pub const fn carry(&self) -> FieldElement { 17 | let mut out = fiat_p521_tight_field_element([0; Self::LIMBS]); 18 | fiat_p521_carry(&mut out, &self.0); 19 | FieldElement(out) 20 | } 21 | 22 | /// Multiplies two field elements and reduces the result. 23 | #[inline] 24 | pub const fn multiply(&self, rhs: &Self) -> FieldElement { 25 | let mut out = fiat_p521_tight_field_element([0; Self::LIMBS]); 26 | fiat_p521_carry_mul(&mut out, &self.0, &rhs.0); 27 | FieldElement(out) 28 | } 29 | 30 | /// Squares a field element and reduces the result. 31 | #[inline] 32 | pub const fn square(&self) -> FieldElement { 33 | let mut out = fiat_p521_tight_field_element([0; Self::LIMBS]); 34 | fiat_p521_carry_square(&mut out, &self.0); 35 | FieldElement(out) 36 | } 37 | } 38 | 39 | impl From for LooseFieldElement { 40 | #[inline] 41 | fn from(tight: FieldElement) -> LooseFieldElement { 42 | LooseFieldElement::from(&tight) 43 | } 44 | } 45 | 46 | impl From<&FieldElement> for LooseFieldElement { 47 | #[inline] 48 | fn from(tight: &FieldElement) -> LooseFieldElement { 49 | tight.relax() 50 | } 51 | } 52 | 53 | impl From for FieldElement { 54 | #[inline] 55 | fn from(loose: LooseFieldElement) -> FieldElement { 56 | FieldElement::from(&loose) 57 | } 58 | } 59 | 60 | impl From<&LooseFieldElement> for FieldElement { 61 | #[inline] 62 | fn from(loose: &LooseFieldElement) -> FieldElement { 63 | loose.carry() 64 | } 65 | } 66 | 67 | impl Mul for LooseFieldElement { 68 | type Output = FieldElement; 69 | 70 | #[inline] 71 | fn mul(self, rhs: LooseFieldElement) -> FieldElement { 72 | Self::multiply(&self, &rhs) 73 | } 74 | } 75 | 76 | impl Mul<&LooseFieldElement> for LooseFieldElement { 77 | type Output = FieldElement; 78 | 79 | #[inline] 80 | fn mul(self, rhs: &LooseFieldElement) -> FieldElement { 81 | Self::multiply(&self, rhs) 82 | } 83 | } 84 | 85 | impl Mul<&LooseFieldElement> for &LooseFieldElement { 86 | type Output = FieldElement; 87 | 88 | #[inline] 89 | fn mul(self, rhs: &LooseFieldElement) -> FieldElement { 90 | LooseFieldElement::multiply(self, rhs) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /p521/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "p521" 3 | version = "0.14.0-rc.1" 4 | description = """ 5 | Pure Rust implementation of the NIST P-521 (a.k.a. secp521r1) elliptic curve 6 | as defined in SP 800-186 7 | """ 8 | authors = ["RustCrypto Developers"] 9 | license = "Apache-2.0 OR MIT" 10 | documentation = "https://docs.rs/p521" 11 | homepage = "https://github.com/RustCrypto/elliptic-curves/tree/master/p521" 12 | repository = "https://github.com/RustCrypto/elliptic-curves" 13 | readme = "README.md" 14 | categories = ["cryptography", "no-std"] 15 | keywords = ["crypto", "ecc", "nist", "secp521r1"] 16 | edition = "2024" 17 | rust-version = "1.85" 18 | 19 | [dependencies] 20 | base16ct = "0.3" 21 | elliptic-curve = { version = "0.14.0-rc.17", default-features = false, features = ["sec1"] } 22 | 23 | # optional dependencies 24 | ecdsa-core = { version = "0.17.0-rc.9", package = "ecdsa", optional = true, default-features = false, features = ["der"] } 25 | hash2curve = { version = "0.14.0-rc.4", optional = true } 26 | hex-literal = { version = "1", optional = true } 27 | primefield = { version = "0.14.0-rc.1", optional = true } 28 | primeorder = { version = "0.14.0-rc.1", optional = true } 29 | rand_core = { version = "0.10.0-rc-2", optional = true, default-features = false } 30 | serdect = { version = "0.4", optional = true, default-features = false } 31 | sha2 = { version = "0.11.0-rc.3", optional = true, default-features = false } 32 | 33 | [dev-dependencies] 34 | criterion = "0.7" 35 | ecdsa-core = { version = "0.17.0-rc.9", package = "ecdsa", default-features = false, features = ["dev"] } 36 | hex-literal = "1" 37 | primeorder = { version = "0.14.0-rc.1", features = ["dev"] } 38 | proptest = "1.9" 39 | rand = "0.10.0-rc.1" 40 | 41 | [features] 42 | default = ["arithmetic", "ecdsa", "pem", "std"] 43 | alloc = ["ecdsa-core?/alloc", "elliptic-curve/alloc", "primeorder?/alloc"] 44 | std = ["alloc", "ecdsa-core?/std", "elliptic-curve/std", "getrandom"] 45 | 46 | arithmetic = ["dep:primefield", "dep:primeorder"] 47 | digest = ["ecdsa-core/digest", "ecdsa-core/hazmat"] 48 | ecdh = ["arithmetic", "elliptic-curve/ecdh"] 49 | ecdsa = ["arithmetic", "ecdsa-core/algorithm", "sha512"] 50 | expose-field = ["arithmetic"] 51 | hash2curve = ["arithmetic", "dep:hash2curve", "primeorder/hash2curve"] 52 | getrandom = ["ecdsa-core?/getrandom", "elliptic-curve/getrandom"] 53 | group-digest = ["hash2curve", "dep:sha2"] 54 | oprf = ["group-digest"] 55 | pem = ["elliptic-curve/pem", "pkcs8"] 56 | pkcs8 = ["ecdsa-core?/pkcs8", "elliptic-curve/pkcs8"] 57 | serde = ["ecdsa-core?/serde", "elliptic-curve/serde", "primeorder?/serde", "serdect"] 58 | sha512 = ["digest", "dep:sha2"] 59 | test-vectors = ["dep:hex-literal"] 60 | 61 | [package.metadata.docs.rs] 62 | all-features = true 63 | 64 | [[bench]] 65 | name = "field" 66 | harness = false 67 | required-features = ["expose-field"] 68 | 69 | [[bench]] 70 | name = "scalar" 71 | harness = false 72 | --------------------------------------------------------------------------------