From c157a1ed6defda81c8113531c9db6d7a85ff7f5a Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Tue, 12 Sep 2023 09:41:15 -0400 Subject: [PATCH 01/32] Add group to documented features (#578) --- curve25519-dalek/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml index 3b77aa33..73d034f5 100644 --- a/curve25519-dalek/Cargo.toml +++ b/curve25519-dalek/Cargo.toml @@ -27,7 +27,7 @@ rustdoc-args = [ "--html-in-header", "docs/assets/rustdoc-include-katex-header.html", "--cfg", "docsrs", ] -features = ["serde", "rand_core", "digest", "legacy_compatibility"] +features = ["serde", "rand_core", "digest", "legacy_compatibility", "group"] [dev-dependencies] sha2 = { version = "0.10", default-features = false } From 533b53a0ec3177496c8757e3da851229ae5cf28b Mon Sep 17 00:00:00 2001 From: "pinkforest(she/her)" <36498018+pinkforest@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:59:05 +1000 Subject: [PATCH 02/32] Deprecate `BASEPOINT_ORDER` from pub API consts (#581) * Mark constants::BASEPOINT_ORDER_PRIVATE deprecated from pub API * Move all BASEPOINT_ORDER use private internally Co-authored-by: Tony Arcieri * Fix CHANGELOG for 4.1.1 --------- Co-authored-by: Tony Arcieri --- curve25519-dalek/CHANGELOG.md | 4 ++++ curve25519-dalek/src/constants.rs | 22 ++++------------------ curve25519-dalek/src/edwards.rs | 6 +++--- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index 0b5c3ab9..df02ffb6 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -5,6 +5,10 @@ major series. ## 4.x series +### 4.1.1 + +* Mark `constants::BASEPOINT_ORDER` deprecated from pub API + ### 4.1.0 * Add arbitrary integer multiplication with `MontgomeryPoint::mul_bits_be` diff --git a/curve25519-dalek/src/constants.rs b/curve25519-dalek/src/constants.rs index caef33a9..34285461 100644 --- a/curve25519-dalek/src/constants.rs +++ b/curve25519-dalek/src/constants.rs @@ -8,24 +8,7 @@ // Authors: // - isis agora lovecruft // - Henry de Valence - //! Various constants, such as the Ristretto and Ed25519 basepoints. -//! -//! Most of the constants are given with -//! `LONG_DESCRIPTIVE_UPPER_CASE_NAMES`, but they can be brought into -//! scope using a `let` binding: -//! -#![cfg_attr(feature = "precomputed-tables", doc = "```")] -#![cfg_attr(not(feature = "precomputed-tables"), doc = "```ignore")] -//! use curve25519_dalek::constants; -//! use curve25519_dalek::traits::IsIdentity; -//! -//! let B = constants::RISTRETTO_BASEPOINT_TABLE; -//! let l = &constants::BASEPOINT_ORDER; -//! -//! let A = l * B; -//! assert!(A.is_identity()); -//! ``` #![allow(non_snake_case)] @@ -86,7 +69,10 @@ pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BAS /// $$ /// \ell = 2^\{252\} + 27742317777372353535851937790883648493. /// $$ -pub const BASEPOINT_ORDER: Scalar = Scalar { +#[deprecated(since = "4.1.1", note = "Should not have been in public API")] +pub const BASEPOINT_ORDER: Scalar = BASEPOINT_ORDER_PRIVATE; + +pub(crate) const BASEPOINT_ORDER_PRIVATE: Scalar = Scalar { bytes: [ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/curve25519-dalek/src/edwards.rs b/curve25519-dalek/src/edwards.rs index e7f6d4b5..accf2277 100644 --- a/curve25519-dalek/src/edwards.rs +++ b/curve25519-dalek/src/edwards.rs @@ -1254,7 +1254,7 @@ impl EdwardsPoint { /// assert_eq!((P+Q).is_torsion_free(), false); /// ``` pub fn is_torsion_free(&self) -> bool { - (self * constants::BASEPOINT_ORDER).is_identity() + (self * constants::BASEPOINT_ORDER_PRIVATE).is_identity() } } @@ -1580,7 +1580,7 @@ impl CofactorGroup for EdwardsPoint { } fn is_torsion_free(&self) -> Choice { - (self * constants::BASEPOINT_ORDER).ct_eq(&Self::identity()) + (self * constants::BASEPOINT_ORDER_PRIVATE).ct_eq(&Self::identity()) } } @@ -1769,7 +1769,7 @@ mod test { /// Test that multiplication by the basepoint order kills the basepoint #[test] fn basepoint_mult_by_basepoint_order() { - let should_be_id = EdwardsPoint::mul_base(&constants::BASEPOINT_ORDER); + let should_be_id = EdwardsPoint::mul_base(&constants::BASEPOINT_ORDER_PRIVATE); assert!(should_be_id.is_identity()); } From 76a8b2a081050bf7142ec0baa15bc4560fc51557 Mon Sep 17 00:00:00 2001 From: Luke Parker Date: Tue, 19 Sep 2023 23:21:43 -0400 Subject: [PATCH 03/32] Add PrimeFieldBits support to Scalar (#579) Co-authored-by: Michael Rosenberg Co-authored-by: pinkforest(she/her) <36498018+pinkforest@users.noreply.github.com> --- curve25519-dalek/CHANGELOG.md | 4 ++++ curve25519-dalek/Cargo.toml | 4 +++- curve25519-dalek/src/scalar.rs | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index df02ffb6..503bbed9 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -5,6 +5,10 @@ major series. ## 4.x series +### Unreleased + +* Add implementation for `PrimeFieldBits`, behind the `group-bits` feature flag. + ### 4.1.1 * Mark `constants::BASEPOINT_ORDER` deprecated from pub API diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml index 73d034f5..15e273ae 100644 --- a/curve25519-dalek/Cargo.toml +++ b/curve25519-dalek/Cargo.toml @@ -27,7 +27,7 @@ rustdoc-args = [ "--html-in-header", "docs/assets/rustdoc-include-katex-header.html", "--cfg", "docsrs", ] -features = ["serde", "rand_core", "digest", "legacy_compatibility", "group"] +features = ["serde", "rand_core", "digest", "legacy_compatibility", "group-bits"] [dev-dependencies] sha2 = { version = "0.10", default-features = false } @@ -48,6 +48,7 @@ required-features = ["alloc", "rand_core"] [dependencies] cfg-if = "1" +ff = { version = "0.13", default-features = false, optional = true } group = { version = "0.13", default-features = false, optional = true } rand_core = { version = "0.6.4", default-features = false, optional = true } digest = { version = "0.10", default-features = false, optional = true } @@ -67,6 +68,7 @@ alloc = ["zeroize?/alloc"] precomputed-tables = [] legacy_compatibility = [] group = ["dep:group", "rand_core"] +group-bits = ["group", "ff/bits"] [target.'cfg(all(not(curve25519_dalek_backend = "fiat"), not(curve25519_dalek_backend = "serial"), target_arch = "x86_64"))'.dependencies] curve25519-dalek-derive = { version = "0.1", path = "../curve25519-dalek-derive" } diff --git a/curve25519-dalek/src/scalar.rs b/curve25519-dalek/src/scalar.rs index 17b0f5e0..5b9eca1d 100644 --- a/curve25519-dalek/src/scalar.rs +++ b/curve25519-dalek/src/scalar.rs @@ -124,6 +124,8 @@ use core::ops::{Sub, SubAssign}; use cfg_if::cfg_if; +#[cfg(feature = "group-bits")] +use group::ff::{FieldBits, PrimeFieldBits}; #[cfg(feature = "group")] use { group::ff::{Field, FromUniformBytes, PrimeField}, @@ -1321,6 +1323,19 @@ impl PrimeField for Scalar { }; } +#[cfg(feature = "group-bits")] +impl PrimeFieldBits for Scalar { + type ReprBits = [u8; 32]; + + fn to_le_bits(&self) -> FieldBits { + self.to_repr().into() + } + + fn char_le_bits() -> FieldBits { + constants::BASEPOINT_ORDER_PRIVATE.to_bytes().into() + } +} + #[cfg(feature = "group")] impl FromUniformBytes<64> for Scalar { fn from_uniform_bytes(bytes: &[u8; 64]) -> Self { From 0cd099a9fb8ff9f6fedc8723d44dbb1c743e9d35 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Wed, 20 Sep 2023 17:42:22 -0500 Subject: [PATCH 04/32] curve: Bump version to 4.1.1 (#584) --- curve25519-dalek/CHANGELOG.md | 5 +---- curve25519-dalek/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index 503bbed9..1715e3bf 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -5,13 +5,10 @@ major series. ## 4.x series -### Unreleased - -* Add implementation for `PrimeFieldBits`, behind the `group-bits` feature flag. - ### 4.1.1 * Mark `constants::BASEPOINT_ORDER` deprecated from pub API +* Add implementation for `PrimeFieldBits`, behind the `group-bits` feature flag. ### 4.1.0 diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml index 15e273ae..b6157955 100644 --- a/curve25519-dalek/Cargo.toml +++ b/curve25519-dalek/Cargo.toml @@ -4,7 +4,7 @@ name = "curve25519-dalek" # - update CHANGELOG # - update README if required by semver # - if README was updated, also update module documentation in src/lib.rs -version = "4.1.0" +version = "4.1.1" edition = "2021" rust-version = "1.60.0" authors = ["Isis Lovecruft ", From e6675c67ceadecc3e22b561296490f4b7de9ff39 Mon Sep 17 00:00:00 2001 From: Victor Graf Date: Tue, 3 Oct 2023 11:51:05 -0700 Subject: [PATCH 05/32] add cfg statements to only build doctest on x86 (#585) --- curve25519-dalek-derive/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/curve25519-dalek-derive/README.md b/curve25519-dalek-derive/README.md index 7f52d440..713207a6 100644 --- a/curve25519-dalek-derive/README.md +++ b/curve25519-dalek-derive/README.md @@ -44,6 +44,7 @@ to build out more elaborate abstractions it starts to become painful to use. } struct AVX; + # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] impl Backend for AVX { #[target_feature(enable = "avx")] unsafe fn sum(xs: &[u32]) -> u32 { @@ -53,6 +54,7 @@ to build out more elaborate abstractions it starts to become painful to use. } struct AVX2; + # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] impl Backend for AVX2 { #[target_feature(enable = "avx2")] unsafe fn sum(xs: &[u32]) -> u32 { @@ -87,6 +89,7 @@ fn func() {} ```rust // It works, but must be `unsafe` +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[target_feature(enable = "avx2")] unsafe fn func() {} ``` @@ -95,6 +98,7 @@ unsafe fn func() {} use curve25519_dalek_derive::unsafe_target_feature; // No `unsafe` on the function itself! +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[unsafe_target_feature("avx2")] fn func() {} ``` @@ -119,6 +123,7 @@ use curve25519_dalek_derive::unsafe_target_feature; struct S; +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[unsafe_target_feature("avx2")] impl core::ops::Add for S { type Output = S; @@ -135,6 +140,7 @@ impl core::ops::Add for S { ```rust use curve25519_dalek_derive::unsafe_target_feature_specialize; +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[unsafe_target_feature_specialize("sse2", "avx2", conditional("avx512ifma", nightly))] mod simd { #[for_target_feature("sse2")] @@ -149,6 +155,7 @@ mod simd { pub fn func() { /* ... */ } } +# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn entry_point() { #[cfg(nightly)] if std::is_x86_feature_detected!("avx512ifma") { From 598695c4007d7ee3f48760668c47cf89b9aefb67 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 26 Oct 2023 22:29:56 -0600 Subject: [PATCH 06/32] ed25519: loosen `signature` crate dependency (#582) The `signature` crate contains unstable, minor version-gated functionality. The v2.1 release did not change any of that, and only added new functionality. So it's safe to relax the requirement for `signature` to `>=2.0, <2.2`. --- ed25519-dalek/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ed25519-dalek/Cargo.toml b/ed25519-dalek/Cargo.toml index 89399e9c..1f9446d9 100644 --- a/ed25519-dalek/Cargo.toml +++ b/ed25519-dalek/Cargo.toml @@ -28,7 +28,7 @@ features = ["batch", "digest", "hazmat", "pem", "serde"] [dependencies] curve25519-dalek = { version = "4", path = "../curve25519-dalek", default-features = false, features = ["digest"] } ed25519 = { version = ">=2.2, <2.3", default-features = false } -signature = { version = ">=2.0, <2.1", optional = true, default-features = false } +signature = { version = ">=2.0, <2.2", optional = true, default-features = false } sha2 = { version = "0.10", default-features = false } subtle = { version = "2.3.0", default-features = false } From b92421916d3b80d2b14e8944fcff39407738ec97 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Sun, 29 Oct 2023 10:47:45 -0400 Subject: [PATCH 07/32] Copy licensing from previous repo --- curve25519-dalek-derive/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/curve25519-dalek-derive/README.md b/curve25519-dalek-derive/README.md index 713207a6..69bde71c 100644 --- a/curve25519-dalek-derive/README.md +++ b/curve25519-dalek-derive/README.md @@ -186,8 +186,8 @@ fn entry_point() { Licensed under either of - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or ) + * Apache License, Version 2.0, [LICENSE-APACHE](LICENSE-APACHE) + * MIT license ([LICENSE-MIT](LICENSE-MIT)) at your option. From 8a41a2993990e89cd95ee1089e734fb28d0acc10 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Sun, 29 Oct 2023 10:50:17 -0400 Subject: [PATCH 08/32] Forgot the license files --- curve25519-dalek-derive/LICENSE-APACHE | 201 +++++++++++++++++++++++++ curve25519-dalek-derive/LICENSE-MIT | 23 +++ 2 files changed, 224 insertions(+) create mode 100644 curve25519-dalek-derive/LICENSE-APACHE create mode 100644 curve25519-dalek-derive/LICENSE-MIT diff --git a/curve25519-dalek-derive/LICENSE-APACHE b/curve25519-dalek-derive/LICENSE-APACHE new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/curve25519-dalek-derive/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/curve25519-dalek-derive/LICENSE-MIT b/curve25519-dalek-derive/LICENSE-MIT new file mode 100644 index 00000000..31aa7938 --- /dev/null +++ b/curve25519-dalek-derive/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. From cd9378e6fd10d57b9d48039f410df90eaf68ab4a Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Sun, 29 Oct 2023 21:53:08 -0400 Subject: [PATCH 09/32] Removed unnecessary 'pub use' --- curve25519-dalek/src/field.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/curve25519-dalek/src/field.rs b/curve25519-dalek/src/field.rs index 545099d1..4767c991 100644 --- a/curve25519-dalek/src/field.rs +++ b/curve25519-dalek/src/field.rs @@ -39,11 +39,6 @@ use crate::constants; cfg_if! { if #[cfg(curve25519_dalek_backend = "fiat")] { - #[cfg(curve25519_dalek_bits = "32")] - pub use backend::serial::fiat_u32::field::*; - #[cfg(curve25519_dalek_bits = "64")] - pub use backend::serial::fiat_u64::field::*; - /// A `FieldElement` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// @@ -64,8 +59,6 @@ cfg_if! { #[cfg(curve25519_dalek_bits = "64")] pub type FieldElement = backend::serial::fiat_u64::field::FieldElement51; } else if #[cfg(curve25519_dalek_bits = "64")] { - pub use crate::backend::serial::u64::field::*; - /// A `FieldElement` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// @@ -73,14 +66,12 @@ cfg_if! { /// implementations. pub type FieldElement = backend::serial::u64::field::FieldElement51; } else { - pub use backend::serial::u32::field::*; - /// A `FieldElement` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// /// The `FieldElement` type is an alias for one of the platform-specific /// implementations. - pub type FieldElement = backend::serial::u32::field::FieldElement2625; + type FieldElement = backend::serial::u32::field::FieldElement2625; } } From 81d0756bdc4a3eab4055294d0a78015ba885fb38 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Sun, 29 Oct 2023 22:06:47 -0400 Subject: [PATCH 10/32] Made unnecessarily pub contents of field.rs pub(crate) --- .github/workflows/curve25519-dalek.yml | 2 +- curve25519-dalek/src/field.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/curve25519-dalek.yml b/.github/workflows/curve25519-dalek.yml index 04ec5423..27df26cd 100644 --- a/.github/workflows/curve25519-dalek.yml +++ b/.github/workflows/curve25519-dalek.yml @@ -127,7 +127,7 @@ jobs: # This should automatically pick up the simd backend in a x86_64 runner # It should pick AVX2 due to stable toolchain used since AVX512 requires nigthly RUSTFLAGS: '-C target_feature=+avx2' - run: cargo test --no-default-features --features alloc,precomputed-tables,zeroize --target x86_64-unknown-linux-gnu + run: cargo test --no-default-features --features alloc,precomputed-tables,zeroize,group-bits --target x86_64-unknown-linux-gnu msrv: name: Current MSRV is 1.60.0 diff --git a/curve25519-dalek/src/field.rs b/curve25519-dalek/src/field.rs index 4767c991..87058941 100644 --- a/curve25519-dalek/src/field.rs +++ b/curve25519-dalek/src/field.rs @@ -47,7 +47,7 @@ cfg_if! { /// /// Using formally-verified field arithmetic from fiat-crypto. #[cfg(curve25519_dalek_bits = "32")] - pub type FieldElement = backend::serial::fiat_u32::field::FieldElement2625; + pub(crate) type FieldElement = backend::serial::fiat_u32::field::FieldElement2625; /// A `FieldElement` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). @@ -57,21 +57,21 @@ cfg_if! { /// /// Using formally-verified field arithmetic from fiat-crypto. #[cfg(curve25519_dalek_bits = "64")] - pub type FieldElement = backend::serial::fiat_u64::field::FieldElement51; + pub(crate) type FieldElement = backend::serial::fiat_u64::field::FieldElement51; } else if #[cfg(curve25519_dalek_bits = "64")] { /// A `FieldElement` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// /// The `FieldElement` type is an alias for one of the platform-specific /// implementations. - pub type FieldElement = backend::serial::u64::field::FieldElement51; + pub(crate) type FieldElement = backend::serial::u64::field::FieldElement51; } else { /// A `FieldElement` represents an element of the field /// \\( \mathbb Z / (2\^{255} - 19)\\). /// /// The `FieldElement` type is an alias for one of the platform-specific /// implementations. - type FieldElement = backend::serial::u32::field::FieldElement2625; + pub(crate) type FieldElement = backend::serial::u32::field::FieldElement2625; } } @@ -100,7 +100,7 @@ impl FieldElement { /// # Return /// /// If negative, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_negative(&self) -> Choice { + pub(crate) fn is_negative(&self) -> Choice { let bytes = self.as_bytes(); (bytes[0] & 1).into() } @@ -110,7 +110,7 @@ impl FieldElement { /// # Return /// /// If zero, return `Choice(1)`. Otherwise, return `Choice(0)`. - pub fn is_zero(&self) -> Choice { + pub(crate) fn is_zero(&self) -> Choice { let zero = [0u8; 32]; let bytes = self.as_bytes(); @@ -156,11 +156,11 @@ impl FieldElement { (t19, t3) } - /// Given a slice of public `FieldElements`, replace each with its inverse. + /// Given a slice of pub(crate)lic `FieldElements`, replace each with its inverse. /// /// When an input `FieldElement` is zero, its value is unchanged. #[cfg(feature = "alloc")] - pub fn batch_invert(inputs: &mut [FieldElement]) { + pub(crate) fn batch_invert(inputs: &mut [FieldElement]) { // Montgomery’s Trick and Fast Implementation of Masked AES // Genelle, Prouff and Quisquater // Section 3.2 @@ -205,7 +205,7 @@ impl FieldElement { /// This function returns zero on input zero. #[rustfmt::skip] // keep alignment of explanatory comments #[allow(clippy::let_and_return)] - pub fn invert(&self) -> FieldElement { + pub(crate) fn invert(&self) -> FieldElement { // The bits of p-2 = 2^255 -19 -2 are 11010111111...11. // // nonzero bits of exponent @@ -242,7 +242,7 @@ impl FieldElement { /// - `(Choice(0), zero) ` if `v` is zero and `u` is nonzero; /// - `(Choice(0), +sqrt(i*u/v))` if `u/v` is nonsquare (so `i*u/v` is square). /// - pub fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) { + pub(crate) fn sqrt_ratio_i(u: &FieldElement, v: &FieldElement) -> (Choice, FieldElement) { // Using the same trick as in ed25519 decoding, we merge the // inversion, the square root, and the square test as follows. // @@ -302,7 +302,7 @@ impl FieldElement { /// - `(Choice(0), zero) ` if `self` is zero; /// - `(Choice(0), +sqrt(i/self)) ` if `self` is a nonzero nonsquare; /// - pub fn invsqrt(&self) -> (Choice, FieldElement) { + pub(crate) fn invsqrt(&self) -> (Choice, FieldElement) { FieldElement::sqrt_ratio_i(&FieldElement::ONE, self) } } From 78a86f1c4988ce12cde848d8fcac97a7e3541ef5 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 31 Oct 2023 10:01:09 -0600 Subject: [PATCH 11/32] ed25519-dalek: hide secret in `SigningKey`'s `Debug` impl (#592) Uses `finish_non_exhaustive` in lieu of printing the `secret_key` component of a `SigningKey`, only showing the corresponding `verifying_key` field which can be used to identify the public key. Closes #591 --- ed25519-dalek/src/signing.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ed25519-dalek/src/signing.rs b/ed25519-dalek/src/signing.rs index fad45f70..ec866d96 100644 --- a/ed25519-dalek/src/signing.rs +++ b/ed25519-dalek/src/signing.rs @@ -9,6 +9,8 @@ //! ed25519 signing keys. +use core::fmt::Debug; + #[cfg(feature = "pkcs8")] use ed25519::pkcs8; @@ -58,7 +60,7 @@ pub type SecretKey = [u8; SECRET_KEY_LENGTH]; // Invariant: `verifying_key` is always the public key of // `secret_key`. This prevents the signing function oracle attack // described in https://github.com/MystenLabs/ed25519-unsafe-libs -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct SigningKey { /// The secret half of this signing key. pub(crate) secret_key: SecretKey, @@ -507,6 +509,14 @@ impl AsRef for SigningKey { } } +impl Debug for SigningKey { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct("SigningKey") + .field("verifying_key", &self.verifying_key) + .finish_non_exhaustive() // avoids printing `secret_key` + } +} + impl KeypairRef for SigningKey { type VerifyingKey = VerifyingKey; } From 3c85f778b37097c25da006ae965ede7a672f2af3 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 31 Oct 2023 10:04:34 -0600 Subject: [PATCH 12/32] CI: fix minimal-versions resolution (#593) To avoid nightly regressions breaking the build, the CI configuration has been updated to *only* use nightly for resolving Cargo.lock by using `cargo update -Z minimal-versions`. Previously, it was running `cargo check` which would attempt to compile all of the dependencies and the code, which is why the diagnostic bug was triggered. By avoiding any kind of code compilation using nightly we can avoid such regressions in the future. Additionally, the clippy job has been changed to run on the latest stable release (1.73.0) rather than nightly, which will prevent future clippy lints from breaking the build. Instead, they can be addressed when clippy is updated. --- .github/workflows/curve25519-dalek.yml | 5 ++--- .github/workflows/ed25519-dalek.yml | 5 ++--- .github/workflows/workspace.yml | 2 +- .github/workflows/x25519-dalek.yml | 5 ++--- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/curve25519-dalek.yml b/.github/workflows/curve25519-dalek.yml index 27df26cd..1fb13aa3 100644 --- a/.github/workflows/curve25519-dalek.yml +++ b/.github/workflows/curve25519-dalek.yml @@ -134,10 +134,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - # First run `cargo +nightly -Z minimal-verisons check` in order to get a - # Cargo.lock with the oldest possible deps + # Re-resolve Cargo.lock with minimal versions - uses: dtolnay/rust-toolchain@nightly - - run: cargo -Z minimal-versions check --no-default-features --features serde + - run: cargo update -Z minimal-versions # Now check that `cargo build` works with respect to the oldest possible # deps and the stated MSRV - uses: dtolnay/rust-toolchain@1.60.0 diff --git a/.github/workflows/ed25519-dalek.yml b/.github/workflows/ed25519-dalek.yml index 4fb4c15b..a49d8345 100644 --- a/.github/workflows/ed25519-dalek.yml +++ b/.github/workflows/ed25519-dalek.yml @@ -24,10 +24,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - # Now run `cargo +nightly -Z minimal-verisons check` in order to get a - # Cargo.lock with the oldest possible deps + # Re-resolve Cargo.lock with minimal versions - uses: dtolnay/rust-toolchain@nightly - - run: cargo -Z minimal-versions check --no-default-features --features serde + - run: cargo update -Z minimal-versions # Now check that `cargo build` works with respect to the oldest possible # deps and the stated MSRV - uses: dtolnay/rust-toolchain@1.60.0 diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 09d1cfa0..b8e44dc5 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -85,7 +85,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly + - uses: dtolnay/rust-toolchain@1.73.0 with: components: clippy - run: cargo clippy --target x86_64-unknown-linux-gnu --all-features diff --git a/.github/workflows/x25519-dalek.yml b/.github/workflows/x25519-dalek.yml index 838b0d06..0ece0dcd 100644 --- a/.github/workflows/x25519-dalek.yml +++ b/.github/workflows/x25519-dalek.yml @@ -24,10 +24,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - # Now run `cargo +nightly -Z minimal-verisons check` in order to get a - # Cargo.lock with the oldest possible deps + # Re-resolve Cargo.lock with minimal versions - uses: dtolnay/rust-toolchain@nightly - - run: cargo -Z minimal-versions check --no-default-features --features serde + - run: cargo update -Z minimal-versions # Now check that `cargo build` works with respect to the oldest possible # deps and the stated MSRV - uses: dtolnay/rust-toolchain@1.60.0 From 72761ca6b4772af985f969db53faf7accbad9b36 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Tue, 31 Oct 2023 13:40:12 -0400 Subject: [PATCH 13/32] derive: Bump version to 0.1.1 (#594) * derive: Bump version to 0.1.1 * Added changelog --- curve25519-dalek-derive/CHANGELOG.md | 8 ++++++++ curve25519-dalek-derive/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 curve25519-dalek-derive/CHANGELOG.md diff --git a/curve25519-dalek-derive/CHANGELOG.md b/curve25519-dalek-derive/CHANGELOG.md new file mode 100644 index 00000000..8a0915b8 --- /dev/null +++ b/curve25519-dalek-derive/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +Entries are listed in reverse chronological order per undeprecated +major series. + +### 0.1.1 + +* Copied over license files from [original](https://github.com/koute/unsafe_target_feature/tree/389ae00d34cf0ff589cb8d9b38a85ae1b05ebfdc) repo diff --git a/curve25519-dalek-derive/Cargo.toml b/curve25519-dalek-derive/Cargo.toml index 17e6d0f5..938144a0 100644 --- a/curve25519-dalek-derive/Cargo.toml +++ b/curve25519-dalek-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "curve25519-dalek-derive" -version = "0.1.0" +version = "0.1.1" edition = "2021" repository = "https://github.com/dalek-cryptography/curve25519-dalek" From 89aabac235ecb2fee2e1f482a17d9312a2616c5a Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 1 Nov 2023 11:33:43 -0600 Subject: [PATCH 14/32] README.md: remove broken image (#595) This image duplicates the `curve25519-dalek` table entry below. It also doesn't actually link to anything, making README.md look broken. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index bbc51d51..aced3739 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ # Dalek elliptic curve cryptography This repo contains pure-Rust crates for elliptic curve cryptography: -[![curve25519 Rust]()](https://github.com/dalek-cryptography/curve25519-dalek/actions/workflows/curve25519-dalek.yml) | Crate | Description | Crates.io | Docs | CI | -------------------------------------------|----------------|-----------|------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- From ac51ef6ecf90ae21f0880d22fe875b3a7eaee884 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 13 Nov 2023 22:09:16 -0700 Subject: [PATCH 15/32] ed25519: loosen `signature` crate dependency again (#598) Like #582, there is a new release of `signature` (v2.2.0) which contains no breaking changes from ed25519-dalek's perspective. The main notable one is it bumps MSRV to 1.60, which so also happens to also be ed25519-dalek's MSRV. This commit loosens the version requirement to allow `>=2.0, <2.3` to allow the `signature` 2.2 series. --- ed25519-dalek/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ed25519-dalek/Cargo.toml b/ed25519-dalek/Cargo.toml index 1f9446d9..8fd4ecc8 100644 --- a/ed25519-dalek/Cargo.toml +++ b/ed25519-dalek/Cargo.toml @@ -28,7 +28,7 @@ features = ["batch", "digest", "hazmat", "pem", "serde"] [dependencies] curve25519-dalek = { version = "4", path = "../curve25519-dalek", default-features = false, features = ["digest"] } ed25519 = { version = ">=2.2, <2.3", default-features = false } -signature = { version = ">=2.0, <2.2", optional = true, default-features = false } +signature = { version = ">=2.0, <2.3", optional = true, default-features = false } sha2 = { version = "0.10", default-features = false } subtle = { version = "2.3.0", default-features = false } From 04f811ad2185f36f58ee4dd293af512ec63bee16 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Tue, 14 Nov 2023 13:23:48 -0500 Subject: [PATCH 16/32] ed: Add back `SigningKey::to_scalar_bytes` (#599) * Brought back SigningKey::to_scalar_bytes; added regression test * Updated SigningKey::to_scalar docs and tests --- ed25519-dalek/CHANGELOG.md | 4 ++ ed25519-dalek/Cargo.toml | 1 + ed25519-dalek/src/signing.rs | 41 ++++++++++++++++++-- ed25519-dalek/tests/x25519.rs | 72 +++++++++++++++++++++-------------- 4 files changed, 85 insertions(+), 33 deletions(-) diff --git a/ed25519-dalek/CHANGELOG.md b/ed25519-dalek/CHANGELOG.md index c3fc94a5..1561d055 100644 --- a/ed25519-dalek/CHANGELOG.md +++ b/ed25519-dalek/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Entries are listed in reverse chronological order per undeprecated major series. +# Unreleased + +* Add `SigningKey::to_scalar_bytes` for getting the unclamped scalar from signing key + # 2.x series ## 2.0.0 diff --git a/ed25519-dalek/Cargo.toml b/ed25519-dalek/Cargo.toml index 8fd4ecc8..447976ad 100644 --- a/ed25519-dalek/Cargo.toml +++ b/ed25519-dalek/Cargo.toml @@ -40,6 +40,7 @@ zeroize = { version = "1.5", default-features = false, optional = true } [dev-dependencies] curve25519-dalek = { version = "4", path = "../curve25519-dalek", default-features = false, features = ["digest", "rand_core"] } +x25519-dalek = { version = "2", path = "../x25519-dalek", default-features = false, features = ["static_secrets"] } blake2 = "0.10" sha3 = "0.10" hex = "0.4" diff --git a/ed25519-dalek/src/signing.rs b/ed25519-dalek/src/signing.rs index ec866d96..23fab8f7 100644 --- a/ed25519-dalek/src/signing.rs +++ b/ed25519-dalek/src/signing.rs @@ -483,15 +483,43 @@ impl SigningKey { self.verifying_key.verify_strict(message, signature) } - /// Convert this signing key into a byte representation of a(n) (unreduced) Curve25519 scalar. + /// Convert this signing key into a byte representation of an unreduced, unclamped Curve25519 + /// scalar. This is NOT the same thing as `self.to_scalar().to_bytes()`, since `to_scalar()` + /// performs a clamping step, which changes the value of the resulting scalar. /// /// This can be used for performing X25519 Diffie-Hellman using Ed25519 keys. The bytes output - /// by this function are a valid secret key for the X25519 public key given by - /// `self.verifying_key().to_montgomery()`. + /// by this function are a valid corresponding [`StaticSecret`](https://docs.rs/x25519-dalek/2.0.0/x25519_dalek/struct.StaticSecret.html#impl-From%3C%5Bu8;+32%5D%3E-for-StaticSecret) + /// for the X25519 public key given by `self.verifying_key().to_montgomery()`. /// /// # Note /// - /// We do NOT recommend this usage of a signing/verifying key. Signing keys are usually + /// We do NOT recommend using a signing/verifying key for encryption. Signing keys are usually + /// long-term keys, while keys used for key exchange should rather be ephemeral. If you can + /// help it, use a separate key for encryption. + /// + /// For more information on the security of systems which use the same keys for both signing + /// and Diffie-Hellman, see the paper + /// [On using the same key pair for Ed25519 and an X25519 based KEM](https://eprint.iacr.org/2021/509). + pub fn to_scalar_bytes(&self) -> [u8; 32] { + // Per the spec, the ed25519 secret key sk is expanded to + // (scalar_bytes, hash_prefix) = SHA-512(sk) + // where the two outputs are both 32 bytes. scalar_bytes is what we return. Its clamped and + // reduced form is what we use for signing (see impl ExpandedSecretKey) + let mut buf = [0u8; 32]; + let scalar_and_hash_prefix = Sha512::default().chain_update(self.secret_key).finalize(); + buf.copy_from_slice(&scalar_and_hash_prefix[..32]); + buf + } + + /// Convert this signing key into a Curve25519 scalar. This is computed by clamping and + /// reducing the output of [`Self::to_scalar_bytes`]. + /// + /// This can be used anywhere where a Curve25519 scalar is used as a private key, e.g., in + /// [`crypto_box`](https://docs.rs/crypto_box/0.9.1/crypto_box/struct.SecretKey.html#impl-From%3CScalar%3E-for-SecretKey). + /// + /// # Note + /// + /// We do NOT recommend using a signing/verifying key for encryption. Signing keys are usually /// long-term keys, while keys used for key exchange should rather be ephemeral. If you can /// help it, use a separate key for encryption. /// @@ -499,6 +527,11 @@ impl SigningKey { /// and Diffie-Hellman, see the paper /// [On using the same key pair for Ed25519 and an X25519 based KEM](https://eprint.iacr.org/2021/509). pub fn to_scalar(&self) -> Scalar { + // Per the spec, the ed25519 secret key sk is expanded to + // (scalar_bytes, hash_prefix) = SHA-512(sk) + // where the two outputs are both 32 bytes. To use for signing, scalar_bytes must be + // clamped and reduced (see ExpandedSecretKey::from_bytes). We return the clamped and + // reduced form. ExpandedSecretKey::from(&self.secret_key).scalar } } diff --git a/ed25519-dalek/tests/x25519.rs b/ed25519-dalek/tests/x25519.rs index 48dab278..11e72a80 100644 --- a/ed25519-dalek/tests/x25519.rs +++ b/ed25519-dalek/tests/x25519.rs @@ -4,63 +4,77 @@ use curve25519_dalek::scalar::{clamp_integer, Scalar}; use ed25519_dalek::SigningKey; use hex_literal::hex; use sha2::{Digest, Sha512}; - -/// Helper function to return the bytes corresponding to the input bytes after being clamped and -/// reduced mod 2^255 - 19 -fn clamp_and_reduce(bytes: &[u8]) -> [u8; 32] { - assert_eq!(bytes.len(), 32); - Scalar::from_bytes_mod_order(clamp_integer(bytes.try_into().unwrap())).to_bytes() -} +use x25519_dalek::{PublicKey as XPublicKey, StaticSecret as XStaticSecret}; /// Tests that X25519 Diffie-Hellman works when using keys converted from Ed25519. // TODO: generate test vectors using another implementation of Ed25519->X25519 #[test] fn ed25519_to_x25519_dh() { // Keys from RFC8032 test vectors (from section 7.1) - let ed25519_secret_key_a = - hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); - let ed25519_secret_key_b = - hex!("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"); + let ed_secret_key_a = hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60"); + let ed_secret_key_b = hex!("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb"); + + let ed_signing_key_a = SigningKey::from_bytes(&ed_secret_key_a); + let ed_signing_key_b = SigningKey::from_bytes(&ed_secret_key_b); - let ed25519_signing_key_a = SigningKey::from_bytes(&ed25519_secret_key_a); - let ed25519_signing_key_b = SigningKey::from_bytes(&ed25519_secret_key_b); + // Create an x25519 static secret from the ed25519 signing key + let scalar_bytes_a = ed_signing_key_a.to_scalar_bytes(); + let scalar_bytes_b = ed_signing_key_b.to_scalar_bytes(); + let x_static_secret_a = XStaticSecret::from(scalar_bytes_a); + let x_static_secret_b = XStaticSecret::from(scalar_bytes_b); - let scalar_a = ed25519_signing_key_a.to_scalar(); - let scalar_b = ed25519_signing_key_b.to_scalar(); + // Compute the secret scalars too + let scalar_a = ed_signing_key_a.to_scalar(); + let scalar_b = ed_signing_key_b.to_scalar(); // Compare the scalar bytes to the first 32 bytes of SHA-512(secret_key). We have to clamp and // reduce the SHA-512 output because that's what the spec does before using the scalars for // anything. + assert_eq!(scalar_bytes_a, &Sha512::digest(ed_secret_key_a)[..32]); + assert_eq!(scalar_bytes_b, &Sha512::digest(ed_secret_key_b)[..32]); + + // Compare the scalar with the clamped and reduced scalar bytes assert_eq!( - scalar_a.to_bytes(), - clamp_and_reduce(&Sha512::digest(ed25519_secret_key_a)[..32]), + scalar_a, + Scalar::from_bytes_mod_order(clamp_integer(scalar_bytes_a)) ); assert_eq!( - scalar_b.to_bytes(), - clamp_and_reduce(&Sha512::digest(ed25519_secret_key_b)[..32]), + scalar_b, + Scalar::from_bytes_mod_order(clamp_integer(scalar_bytes_b)) ); - let x25519_public_key_a = ed25519_signing_key_a.verifying_key().to_montgomery(); - let x25519_public_key_b = ed25519_signing_key_b.verifying_key().to_montgomery(); - + let x_public_key_a = XPublicKey::from(&x_static_secret_a); + let x_public_key_b = XPublicKey::from(&x_static_secret_b); assert_eq!( - x25519_public_key_a.to_bytes(), + x_public_key_a.to_bytes(), hex!("d85e07ec22b0ad881537c2f44d662d1a143cf830c57aca4305d85c7a90f6b62e") ); assert_eq!( - x25519_public_key_b.to_bytes(), + x_public_key_b.to_bytes(), hex!("25c704c594b88afc00a76b69d1ed2b984d7e22550f3ed0802d04fbcd07d38d47") ); + // Test the claim made in the comments of SigningKey::to_scalar_bytes, i.e., that the resulting + // scalar is a valid private key for the x25519 pubkey represented by + // `sk.verifying_key().to_montgomery()` + assert_eq!( + ed_signing_key_a.verifying_key().to_montgomery().as_bytes(), + x_public_key_a.as_bytes() + ); + assert_eq!( + ed_signing_key_b.verifying_key().to_montgomery().as_bytes(), + x_public_key_b.as_bytes() + ); + + // Check that Diffie-Hellman works let expected_shared_secret = hex!("5166f24a6918368e2af831a4affadd97af0ac326bdf143596c045967cc00230e"); - assert_eq!( - (x25519_public_key_a * scalar_b).to_bytes(), - expected_shared_secret + x_static_secret_a.diffie_hellman(&x_public_key_b).to_bytes(), + expected_shared_secret, ); assert_eq!( - (x25519_public_key_b * scalar_a).to_bytes(), - expected_shared_secret + x_static_secret_b.diffie_hellman(&x_public_key_a).to_bytes(), + expected_shared_secret, ); } From f08bbb7f57e906fd852edc0f9f901a536f4ee8a9 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Tue, 14 Nov 2023 15:35:42 -0500 Subject: [PATCH 17/32] ed: Prep to release v2.1.0 (#600) --- ed25519-dalek/CHANGELOG.md | 7 +++++-- ed25519-dalek/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ed25519-dalek/CHANGELOG.md b/ed25519-dalek/CHANGELOG.md index 1561d055..6d679d75 100644 --- a/ed25519-dalek/CHANGELOG.md +++ b/ed25519-dalek/CHANGELOG.md @@ -8,10 +8,13 @@ Entries are listed in reverse chronological order per undeprecated major series. # Unreleased -* Add `SigningKey::to_scalar_bytes` for getting the unclamped scalar from signing key - # 2.x series +## 2.1.0 + +* Add `SigningKey::to_scalar_bytes` for getting the unclamped scalar from a signing key +* Loosened `signature` dependency to allow version 2.2 + ## 2.0.0 ### Breaking changes diff --git a/ed25519-dalek/Cargo.toml b/ed25519-dalek/Cargo.toml index 447976ad..8f70c0d2 100644 --- a/ed25519-dalek/Cargo.toml +++ b/ed25519-dalek/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.0" edition = "2021" authors = [ "isis lovecruft ", From a2ff6ba9e4ae55e9d11a79be4df23b15c5c03ae7 Mon Sep 17 00:00:00 2001 From: Bram Westerbaan Date: Fri, 17 Nov 2023 08:44:28 +0100 Subject: [PATCH 18/32] {Signing,Verifying}KeyVisitor: visit_borrowed_bytes -> visit_bytes (#602) --- ed25519-dalek/src/signing.rs | 5 +---- ed25519-dalek/src/verifying.rs | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/ed25519-dalek/src/signing.rs b/ed25519-dalek/src/signing.rs index 23fab8f7..e2818fea 100644 --- a/ed25519-dalek/src/signing.rs +++ b/ed25519-dalek/src/signing.rs @@ -746,10 +746,7 @@ impl<'d> Deserialize<'d> for SigningKey { write!(formatter, concat!("An ed25519 signing (private) key")) } - fn visit_borrowed_bytes( - self, - bytes: &'de [u8], - ) -> Result { + fn visit_bytes(self, bytes: &[u8]) -> Result { SigningKey::try_from(bytes).map_err(E::custom) } diff --git a/ed25519-dalek/src/verifying.rs b/ed25519-dalek/src/verifying.rs index 29f8a4d1..b7e12978 100644 --- a/ed25519-dalek/src/verifying.rs +++ b/ed25519-dalek/src/verifying.rs @@ -636,10 +636,7 @@ impl<'d> Deserialize<'d> for VerifyingKey { write!(formatter, concat!("An ed25519 verifying (public) key")) } - fn visit_borrowed_bytes( - self, - bytes: &'de [u8], - ) -> Result { + fn visit_bytes(self, bytes: &[u8]) -> Result { VerifyingKey::try_from(bytes).map_err(E::custom) } From ba7a0734870ee28f0d75e34d5b6f7adfe0bfcf73 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Wed, 22 Nov 2023 14:21:20 +0100 Subject: [PATCH 19/32] doc: Fix markdown PR reference (#605) --- ed25519-dalek/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ed25519-dalek/README.md b/ed25519-dalek/README.md index 7524395d..012695d1 100644 --- a/ed25519-dalek/README.md +++ b/ed25519-dalek/README.md @@ -43,7 +43,7 @@ See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past version of t * Make `rand_core` an optional dependency * Adopt [curve25519-backend selection](https://github.com/dalek-cryptography/curve25519-dalek/#backends) over features * Make all batch verification deterministic remove `batch_deterministic` ([#256](https://github.com/dalek-cryptography/ed25519-dalek/pull/256)) -* Remove `ExpandedSecretKey` API ((#205)[https://github.com/dalek-cryptography/ed25519-dalek/pull/205]) +* Remove `ExpandedSecretKey` API ([#205](https://github.com/dalek-cryptography/ed25519-dalek/pull/205)) * Rename `Keypair` → `SigningKey` and `PublicKey` → `VerifyingKey` * Make `hazmat` feature to expose, `ExpandedSecretKey`, `raw_sign()`, `raw_sign_prehashed()`, `raw_verify()`, and `raw_verify_prehashed()` From 0b45e00ad55c3b966c63c837d684a0e08f1a4bd2 Mon Sep 17 00:00:00 2001 From: Pioua <136521243+dzizazda@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:10:05 +0100 Subject: [PATCH 20/32] chore: typo fix (#608) --- curve25519-dalek/CHANGELOG.md | 2 +- curve25519-dalek/docs/ifma-notes.md | 2 +- ed25519-dalek/tests/validation_criteria.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index 1715e3bf..190958af 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -123,7 +123,7 @@ major series. ### 2.1.2 -* Multiple documenation typo fixes. +* Multiple documentation typo fixes. * Fix `alloc` feature working with stable rust. ### 2.1.1 diff --git a/curve25519-dalek/docs/ifma-notes.md b/curve25519-dalek/docs/ifma-notes.md index c6fd3b3a..faf89280 100644 --- a/curve25519-dalek/docs/ifma-notes.md +++ b/curve25519-dalek/docs/ifma-notes.md @@ -351,7 +351,7 @@ This computation requires 25 `vpmadd52luq` and 25 `vpmadd52huq` operations. For 256-bit vectors, IFMA operations execute on an i3-8121U with latency 4 cycles, throughput 0.5 cycles, so executing 50 instructions requires 25 cycles' worth of throughput. Accumulating -terms with coefficient \\(1\\) and \\(2\\) seperately means that the +terms with coefficient \\(1\\) and \\(2\\) separately means that the longest dependency chain has length 5, so the critical path has length 20 cycles and the bottleneck is throughput. diff --git a/ed25519-dalek/tests/validation_criteria.rs b/ed25519-dalek/tests/validation_criteria.rs index fc5b8a5a..7c45a960 100644 --- a/ed25519-dalek/tests/validation_criteria.rs +++ b/ed25519-dalek/tests/validation_criteria.rs @@ -22,7 +22,7 @@ const VERIFY_ALLOWED_EDGECASES: &[Flag] = &[ const VERIFY_STRICT_ALLOWED_EDGECASES: &[Flag] = &[Flag::LowOrderComponentA, Flag::LowOrderComponentR]; -/// Each variant describes a specfiic edge case that can occur in an Ed25519 signature. Refer to +/// Each variant describes a specific edge case that can occur in an Ed25519 signature. Refer to /// the test vector [README][] for more info. /// /// [README]: https://github.com/C2SP/CCTV/blob/5ea85644bd035c555900a2f707f7e4c31ea65ced/ed25519vectors/README.md From ba737a379071191158bacfa6d138f6249b12fc09 Mon Sep 17 00:00:00 2001 From: Ford <153042616+guerrierindien@users.noreply.github.com> Date: Sun, 21 Jan 2024 16:27:47 +0100 Subject: [PATCH 21/32] Update README.md (#613) --- ed25519-dalek/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ed25519-dalek/README.md b/ed25519-dalek/README.md index 012695d1..fbb30e9d 100644 --- a/ed25519-dalek/README.md +++ b/ed25519-dalek/README.md @@ -130,7 +130,7 @@ Backend selection details and instructions can be found in the [curve25519-dalek # Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) +See [CONTRIBUTING.md](../CONTRIBUTING.md) # Batch Signature Verification From ff1c309b23bf1c0c9b45650a73cc3b3cddff7702 Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Wed, 7 Feb 2024 07:09:29 +1100 Subject: [PATCH 22/32] Fix nightly build (#619) * Fix nightly build * Add nightly feature constraint so AVX-512 requires either x86 or x86_64 Co-authored-by: Tony Arcieri * fmt --------- Co-authored-by: Michael Rosenberg Co-authored-by: Tony Arcieri Co-authored-by: Michael Rosenberg --- curve25519-dalek/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/curve25519-dalek/src/lib.rs b/curve25519-dalek/src/lib.rs index 9097a9a8..d8666453 100644 --- a/curve25519-dalek/src/lib.rs +++ b/curve25519-dalek/src/lib.rs @@ -10,7 +10,14 @@ // - Henry de Valence #![no_std] -#![cfg_attr(all(curve25519_dalek_backend = "simd", nightly), feature(stdsimd))] +#![cfg_attr( + all( + curve25519_dalek_backend = "simd", + nightly, + any(target_arch = "x86", target_arch = "x86_64") + ), + feature(stdarch_x86_avx512) +)] #![cfg_attr( all(curve25519_dalek_backend = "simd", nightly), feature(avx512_target_feature) From 4ac84dd0668b1d2e51654fcdffe4ae6a687bef00 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Tue, 6 Feb 2024 20:09:18 -0500 Subject: [PATCH 23/32] curve,ed,x: Bump patch version to reflect fix to nightly SIMD build (#621) --- curve25519-dalek/CHANGELOG.md | 4 ++++ curve25519-dalek/Cargo.toml | 2 +- ed25519-dalek/CHANGELOG.md | 4 ++++ ed25519-dalek/Cargo.toml | 2 +- x25519-dalek/CHANGELOG.md | 4 ++++ x25519-dalek/Cargo.toml | 2 +- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/curve25519-dalek/CHANGELOG.md b/curve25519-dalek/CHANGELOG.md index 190958af..a4c8452c 100644 --- a/curve25519-dalek/CHANGELOG.md +++ b/curve25519-dalek/CHANGELOG.md @@ -5,6 +5,10 @@ major series. ## 4.x series +### 4.1.2 + +* Fix nightly SIMD build + ### 4.1.1 * Mark `constants::BASEPOINT_ORDER` deprecated from pub API diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml index b6157955..48dcb977 100644 --- a/curve25519-dalek/Cargo.toml +++ b/curve25519-dalek/Cargo.toml @@ -4,7 +4,7 @@ name = "curve25519-dalek" # - update CHANGELOG # - update README if required by semver # - if README was updated, also update module documentation in src/lib.rs -version = "4.1.1" +version = "4.1.2" edition = "2021" rust-version = "1.60.0" authors = ["Isis Lovecruft ", diff --git a/ed25519-dalek/CHANGELOG.md b/ed25519-dalek/CHANGELOG.md index 6d679d75..9d1b65e6 100644 --- a/ed25519-dalek/CHANGELOG.md +++ b/ed25519-dalek/CHANGELOG.md @@ -10,6 +10,10 @@ Entries are listed in reverse chronological order per undeprecated major series. # 2.x series +## 2.1.1 + +* Fix nightly SIMD build + ## 2.1.0 * Add `SigningKey::to_scalar_bytes` for getting the unclamped scalar from a signing key diff --git a/ed25519-dalek/Cargo.toml b/ed25519-dalek/Cargo.toml index 8f70c0d2..626b8da9 100644 --- a/ed25519-dalek/Cargo.toml +++ b/ed25519-dalek/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" edition = "2021" authors = [ "isis lovecruft ", diff --git a/x25519-dalek/CHANGELOG.md b/x25519-dalek/CHANGELOG.md index d2c337c0..10e1a545 100644 --- a/x25519-dalek/CHANGELOG.md +++ b/x25519-dalek/CHANGELOG.md @@ -6,6 +6,10 @@ Entries are listed in reverse chronological order. * Note: All `x255919-dalek` 2.x releases are in sync with the underlying `curve25519-dalek` 4.x releases. +## 2.0.1 + +* Fix nightly SIMD build + ## 2.0.0-rc.3 * `StaticSecret` serialization and `to_bytes()` no longer returns clamped integers. Clamping is still always done during scalar-point multiplication. diff --git a/x25519-dalek/Cargo.toml b/x25519-dalek/Cargo.toml index e4146185..4169c55a 100644 --- a/x25519-dalek/Cargo.toml +++ b/x25519-dalek/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # - update html_root_url # - update CHANGELOG # - if any changes were made to README.md, mirror them in src/lib.rs docs -version = "2.0.0" +version = "2.0.1" authors = [ "Isis Lovecruft ", "DebugSteven ", From 50401ab430cde24f6dc02a4cbb93b2e533baab00 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 12 Feb 2024 09:56:06 -0700 Subject: [PATCH 24/32] curve: mark `ValidityCheck` trait as `allow(dead_code)` (#625) Recent nightlies have started emitting a dead code lint --- curve25519-dalek/src/traits.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/curve25519-dalek/src/traits.rs b/curve25519-dalek/src/traits.rs index a12592b8..870dd32f 100644 --- a/curve25519-dalek/src/traits.rs +++ b/curve25519-dalek/src/traits.rs @@ -409,6 +409,7 @@ pub trait VartimePrecomputedMultiscalarMul: Sized { /// This trait is only for debugging/testing, since it should be /// impossible for a `curve25519-dalek` user to construct an invalid /// point. +#[allow(dead_code)] pub(crate) trait ValidityCheck { /// Checks whether the point is on the curve. Not CT. fn is_valid(&self) -> bool; From 17eab3d6c172b9dd4c27ef01410c6c45cbb0360b Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 12 Feb 2024 14:36:43 -0500 Subject: [PATCH 25/32] ed: Make it possible to convert between VerifyingKey and EdwardsPoint (#624) Adds VerifyingKey::to_edwards and a From conversion See #623 --- ed25519-dalek/src/verifying.rs | 11 +++++++++++ ed25519-dalek/tests/ed25519.rs | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/ed25519-dalek/src/verifying.rs b/ed25519-dalek/src/verifying.rs index b7e12978..b5303214 100644 --- a/ed25519-dalek/src/verifying.rs +++ b/ed25519-dalek/src/verifying.rs @@ -505,6 +505,11 @@ impl VerifyingKey { pub fn to_montgomery(&self) -> MontgomeryPoint { self.point.to_montgomery() } + + /// Return this verifying key in Edwards form. + pub fn to_edwards(&self) -> EdwardsPoint { + self.point + } } impl Verifier for VerifyingKey { @@ -563,6 +568,12 @@ impl TryFrom<&[u8]> for VerifyingKey { } } +impl From for EdwardsPoint { + fn from(vk: VerifyingKey) -> EdwardsPoint { + vk.point + } +} + #[cfg(all(feature = "alloc", feature = "pkcs8"))] impl pkcs8::EncodePublicKey for VerifyingKey { fn to_public_key_der(&self) -> pkcs8::spki::Result { diff --git a/ed25519-dalek/tests/ed25519.rs b/ed25519-dalek/tests/ed25519.rs index c05efa3c..82ac33d7 100644 --- a/ed25519-dalek/tests/ed25519.rs +++ b/ed25519-dalek/tests/ed25519.rs @@ -459,6 +459,29 @@ mod integrations { assert_eq!(v, "Second public key"); assert_eq!(m.len(), 2usize); } + + #[test] + fn montgomery_and_edwards_conversion() { + let mut rng = rand::rngs::OsRng; + let signing_key = SigningKey::generate(&mut rng); + let verifying_key = signing_key.verifying_key(); + + let ed = verifying_key.to_edwards(); + + // Check that to_edwards and From return same result: + assert_eq!(ed, curve25519_dalek::EdwardsPoint::from(verifying_key)); + + // The verifying key serialization is simply the compressed Edwards point + assert_eq!(verifying_key.to_bytes(), ed.compress().0); + + // Check that modulo sign, to_montgomery().to_edwards() returns the original point + let monty = verifying_key.to_montgomery(); + let via_monty0 = monty.to_edwards(0).unwrap(); + let via_monty1 = monty.to_edwards(1).unwrap(); + + assert!(via_monty0 != via_monty1); + assert!(ed == via_monty0 || ed == via_monty1); + } } #[cfg(all(test, feature = "serde"))] From a62e4a5c573ca9a68503a6fbe47e3f189a4765b0 Mon Sep 17 00:00:00 2001 From: Flori <39242991+bitfl0wer@users.noreply.github.com> Date: Wed, 14 Feb 2024 20:01:05 +0100 Subject: [PATCH 26/32] Fix minor spelling mistakes (#629) --- ed25519-dalek/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ed25519-dalek/README.md b/ed25519-dalek/README.md index fbb30e9d..dbb14b00 100644 --- a/ed25519-dalek/README.md +++ b/ed25519-dalek/README.md @@ -31,7 +31,7 @@ This crate is `#[no_std]` compatible with `default-features = false`. # Major Changes -See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past version of this crate. +See [CHANGELOG.md](CHANGELOG.md) for a list of changes made in past versions of this crate. ## Breaking Changes in 2.0.0 @@ -63,7 +63,7 @@ SemVer exemptions are outlined below for MSRV and public API. | 2.x | 1.60 | | 1.x | 1.41 | -From 2.x and on, MSRV changes will be accompanied by a minor version bump. +From 2.x onwards, MSRV changes will be accompanied by a minor version bump. ## Public API SemVer Exemptions From 19c7f4a5d5e577adc9cc65a837abef9ed7ebf0a4 Mon Sep 17 00:00:00 2001 From: "pinkforest(she/her)" <36498018+pinkforest@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:56:52 +1100 Subject: [PATCH 27/32] Fix new nightly redundant import lint warns (#638) --- .../src/backend/serial/scalar_mul/pippenger.rs | 1 - .../src/backend/vector/avx2/edwards.rs | 1 - curve25519-dalek/src/edwards.rs | 15 ++++++++------- curve25519-dalek/src/field.rs | 3 --- curve25519-dalek/src/ristretto.rs | 4 +--- curve25519-dalek/src/scalar.rs | 17 ++++++----------- curve25519-dalek/src/traits.rs | 5 ++--- ed25519-dalek/src/batch.rs | 1 - ed25519-dalek/src/signature.rs | 1 - ed25519-dalek/src/verifying.rs | 1 - ed25519-dalek/tests/ed25519.rs | 5 ++--- 11 files changed, 19 insertions(+), 35 deletions(-) diff --git a/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs b/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs index 9af39e59..f60d9b95 100644 --- a/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs +++ b/curve25519-dalek/src/backend/serial/scalar_mul/pippenger.rs @@ -164,7 +164,6 @@ impl VartimeMultiscalarMul for Pippenger { mod test { use super::*; use crate::constants; - use crate::scalar::Scalar; #[test] fn test_vartime_pippenger() { diff --git a/curve25519-dalek/src/backend/vector/avx2/edwards.rs b/curve25519-dalek/src/backend/vector/avx2/edwards.rs index cf6691e8..fd70d7d2 100644 --- a/curve25519-dalek/src/backend/vector/avx2/edwards.rs +++ b/curve25519-dalek/src/backend/vector/avx2/edwards.rs @@ -35,7 +35,6 @@ #![allow(non_snake_case)] -use core::convert::From; use core::ops::{Add, Neg, Sub}; use subtle::Choice; diff --git a/curve25519-dalek/src/edwards.rs b/curve25519-dalek/src/edwards.rs index accf2277..c49590b3 100644 --- a/curve25519-dalek/src/edwards.rs +++ b/curve25519-dalek/src/edwards.rs @@ -96,7 +96,6 @@ use core::array::TryFromSliceError; use core::borrow::Borrow; use core::fmt::Debug; -use core::iter::Iterator; use core::iter::Sum; use core::ops::{Add, Neg, Sub}; use core::ops::{AddAssign, SubAssign}; @@ -110,10 +109,12 @@ use digest::{generic_array::typenum::U64, Digest}; #[cfg(feature = "group")] use { group::{cofactor::CofactorGroup, prime::PrimeGroup, GroupEncoding}, - rand_core::RngCore, subtle::CtOption, }; +#[cfg(feature = "group")] +use rand_core::RngCore; + use subtle::Choice; use subtle::ConditionallyNegatable; use subtle::ConditionallySelectable; @@ -258,7 +259,7 @@ impl TryFrom<&[u8]> for CompressedEdwardsY { #[cfg(feature = "serde")] use serde::de::Visitor; #[cfg(feature = "serde")] -use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] impl Serialize for EdwardsPoint { @@ -1591,8 +1592,10 @@ impl CofactorGroup for EdwardsPoint { #[cfg(test)] mod test { use super::*; - use crate::{field::FieldElement, scalar::Scalar}; - use subtle::ConditionallySelectable; + + // If `group` is set, then this is already imported in super + #[cfg(not(feature = "group"))] + use rand_core::RngCore; #[cfg(feature = "alloc")] use alloc::vec::Vec; @@ -1600,8 +1603,6 @@ mod test { #[cfg(feature = "precomputed-tables")] use crate::constants::ED25519_BASEPOINT_TABLE; - use rand_core::RngCore; - /// X coordinate of the basepoint. /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202 static BASE_X_COORD_BYTES: [u8; 32] = [ diff --git a/curve25519-dalek/src/field.rs b/curve25519-dalek/src/field.rs index 87058941..68c9c8b8 100644 --- a/curve25519-dalek/src/field.rs +++ b/curve25519-dalek/src/field.rs @@ -25,8 +25,6 @@ #![allow(unused_qualifications)] -use core::cmp::{Eq, PartialEq}; - use cfg_if::cfg_if; use subtle::Choice; @@ -310,7 +308,6 @@ impl FieldElement { #[cfg(test)] mod test { use crate::field::*; - use subtle::ConditionallyNegatable; /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\ diff --git a/curve25519-dalek/src/ristretto.rs b/curve25519-dalek/src/ristretto.rs index dec7ae06..75ba141d 100644 --- a/curve25519-dalek/src/ristretto.rs +++ b/curve25519-dalek/src/ristretto.rs @@ -364,7 +364,7 @@ impl TryFrom<&[u8]> for CompressedRistretto { #[cfg(feature = "serde")] use serde::de::Visitor; #[cfg(feature = "serde")] -use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] impl Serialize for RistrettoPoint { @@ -1277,8 +1277,6 @@ impl Zeroize for RistrettoPoint { mod test { use super::*; use crate::edwards::CompressedEdwardsY; - use crate::scalar::Scalar; - use crate::traits::Identity; use rand_core::OsRng; diff --git a/curve25519-dalek/src/scalar.rs b/curve25519-dalek/src/scalar.rs index 5b9eca1d..1630af5e 100644 --- a/curve25519-dalek/src/scalar.rs +++ b/curve25519-dalek/src/scalar.rs @@ -112,8 +112,6 @@ //! has been enabled. use core::borrow::Borrow; -use core::cmp::{Eq, PartialEq}; -use core::convert::TryInto; use core::fmt::Debug; use core::iter::{Product, Sum}; use core::ops::Index; @@ -124,13 +122,13 @@ use core::ops::{Sub, SubAssign}; use cfg_if::cfg_if; +#[cfg(feature = "group")] +use group::ff::{Field, FromUniformBytes, PrimeField}; #[cfg(feature = "group-bits")] use group::ff::{FieldBits, PrimeFieldBits}; -#[cfg(feature = "group")] -use { - group::ff::{Field, FromUniformBytes, PrimeField}, - rand_core::RngCore, -}; + +#[cfg(any(test, feature = "group"))] +use rand_core::RngCore; #[cfg(any(test, feature = "rand_core"))] use rand_core::CryptoRngCore; @@ -402,7 +400,7 @@ impl ConditionallySelectable for Scalar { #[cfg(feature = "serde")] use serde::de::Visitor; #[cfg(feature = "serde")] -use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde")] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] @@ -1393,13 +1391,10 @@ pub const fn clamp_integer(mut bytes: [u8; 32]) -> [u8; 32] { #[cfg(test)] pub(crate) mod test { use super::*; - use crate::constants; #[cfg(feature = "alloc")] use alloc::vec::Vec; - use rand::RngCore; - /// x = 2238329342913194256032495932344128051776374960164957527413114840482143558222 pub static X: Scalar = Scalar { bytes: [ diff --git a/curve25519-dalek/src/traits.rs b/curve25519-dalek/src/traits.rs index 870dd32f..322787db 100644 --- a/curve25519-dalek/src/traits.rs +++ b/curve25519-dalek/src/traits.rs @@ -15,9 +15,8 @@ use core::borrow::Borrow; -use subtle; - use crate::scalar::{clamp_integer, Scalar}; +use subtle::ConstantTimeEq; // ------------------------------------------------------------------------ // Public Traits @@ -41,7 +40,7 @@ pub trait IsIdentity { /// constructor. impl IsIdentity for T where - T: subtle::ConstantTimeEq + Identity, + T: ConstantTimeEq + Identity, { fn is_identity(&self) -> bool { self.ct_eq(&T::identity()).into() diff --git a/ed25519-dalek/src/batch.rs b/ed25519-dalek/src/batch.rs index ed2618d6..fa79677d 100644 --- a/ed25519-dalek/src/batch.rs +++ b/ed25519-dalek/src/batch.rs @@ -11,7 +11,6 @@ use alloc::vec::Vec; -use core::convert::TryFrom; use core::iter::once; use curve25519_dalek::constants; diff --git a/ed25519-dalek/src/signature.rs b/ed25519-dalek/src/signature.rs index 36174c8d..32fde301 100644 --- a/ed25519-dalek/src/signature.rs +++ b/ed25519-dalek/src/signature.rs @@ -9,7 +9,6 @@ //! An ed25519 signature. -use core::convert::TryFrom; use core::fmt::Debug; use curve25519_dalek::edwards::CompressedEdwardsY; diff --git a/ed25519-dalek/src/verifying.rs b/ed25519-dalek/src/verifying.rs index b5303214..0d154678 100644 --- a/ed25519-dalek/src/verifying.rs +++ b/ed25519-dalek/src/verifying.rs @@ -9,7 +9,6 @@ //! ed25519 public keys. -use core::convert::TryFrom; use core::fmt::Debug; use core::hash::{Hash, Hasher}; diff --git a/ed25519-dalek/tests/ed25519.rs b/ed25519-dalek/tests/ed25519.rs index 82ac33d7..edab8a81 100644 --- a/ed25519-dalek/tests/ed25519.rs +++ b/ed25519-dalek/tests/ed25519.rs @@ -27,10 +27,11 @@ mod vectors { scalar::Scalar, traits::IsIdentity, }; + + #[cfg(not(feature = "digest"))] use sha2::{digest::Digest, Sha512}; use std::{ - convert::TryFrom, fs::File, io::{BufRead, BufReader}, ops::Neg, @@ -288,8 +289,6 @@ mod vectors { mod integrations { use super::*; use rand::rngs::OsRng; - #[cfg(feature = "digest")] - use sha2::Sha512; use std::collections::HashMap; #[test] From 31ccb6705067d68782cb135e23c79b640a6a06ee Mon Sep 17 00:00:00 2001 From: "pinkforest(she/her)" <36498018+pinkforest@users.noreply.github.com> Date: Sat, 2 Mar 2024 01:35:23 +1100 Subject: [PATCH 28/32] Remove platforms in favor using CARGO_CFG_TARGET_POINTER_WIDTH (#636) --- curve25519-dalek/Cargo.toml | 1 - curve25519-dalek/build.rs | 75 ++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml index 48dcb977..f8c7c3a8 100644 --- a/curve25519-dalek/Cargo.toml +++ b/curve25519-dalek/Cargo.toml @@ -38,7 +38,6 @@ rand = "0.8" rand_core = { version = "0.6", default-features = false, features = ["getrandom"] } [build-dependencies] -platforms = "3.0.2" rustc_version = "0.4.0" [[bench]] diff --git a/curve25519-dalek/build.rs b/curve25519-dalek/build.rs index 92d2802c..97fa2852 100644 --- a/curve25519-dalek/build.rs +++ b/curve25519-dalek/build.rs @@ -9,17 +9,31 @@ enum DalekBits { Dalek64, } +use std::fmt::Formatter; + +impl std::fmt::Display for DalekBits { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + let w_bits = match self { + DalekBits::Dalek32 => "32", + DalekBits::Dalek64 => "64", + }; + write!(f, "{}", w_bits) + } +} + fn main() { + let target_arch = match std::env::var("CARGO_CFG_TARGET_ARCH") { + Ok(arch) => arch, + _ => "".to_string(), + }; + let curve25519_dalek_bits = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BITS").as_deref() { Ok("32") => DalekBits::Dalek32, Ok("64") => DalekBits::Dalek64, - _ => deterministic::determine_curve25519_dalek_bits(), + _ => deterministic::determine_curve25519_dalek_bits(&target_arch), }; - match curve25519_dalek_bits { - DalekBits::Dalek64 => println!("cargo:rustc-cfg=curve25519_dalek_bits=\"64\""), - DalekBits::Dalek32 => println!("cargo:rustc-cfg=curve25519_dalek_bits=\"32\""), - } + println!("cargo:rustc-cfg=curve25519_dalek_bits=\"{curve25519_dalek_bits}\""); if rustc_version::version_meta() .expect("failed to detect rustc version") @@ -36,11 +50,6 @@ fn main() { println!("cargo:rustc-cfg=allow_unused_unsafe"); } - let target_arch = match std::env::var("CARGO_CFG_TARGET_ARCH") { - Ok(arch) => arch, - _ => "".to_string(), - }; - // Backend overrides / defaults let curve25519_dalek_backend = match std::env::var("CARGO_CFG_CURVE25519_DALEK_BACKEND").as_deref() { @@ -74,11 +83,12 @@ mod deterministic { use super::*; - // Standard Cargo TARGET environment variable of triplet is required - static ERR_MSG_NO_TARGET: &str = "Standard Cargo TARGET environment variable is not set"; + // Custom Rust non-cargo build tooling needs to set CARGO_CFG_TARGET_POINTER_WIDTH + static ERR_MSG_NO_POINTER_WIDTH: &str = + "Standard Cargo TARGET_POINTER_WIDTH environment variable is not set."; - // Custom Non-Rust standard target platforms require explicit settings. - static ERR_MSG_NO_PLATFORM: &str = "Unknown Rust target platform."; + // When either non-32 or 64 TARGET_POINTER_WIDTH detected + static ERR_MSG_UNKNOWN_POINTER_WIDTH: &str = "Unknown TARGET_POINTER_WIDTH detected."; // Warning when the curve25519_dalek_bits cannot be determined fn determine_curve25519_dalek_bits_warning(cause: &str) { @@ -86,41 +96,30 @@ mod deterministic { } // Determine the curve25519_dalek_bits based on Rust standard TARGET triplet - pub(super) fn determine_curve25519_dalek_bits() -> DalekBits { - use platforms::target::PointerWidth; - - // TARGET environment is supplied by Cargo - // https://doc.rust-lang.org/cargo/reference/environment-variables.html - let target_triplet = match std::env::var("TARGET") { - Ok(t) => t, + pub(super) fn determine_curve25519_dalek_bits(target_arch: &String) -> DalekBits { + let target_pointer_width = match std::env::var("CARGO_CFG_TARGET_POINTER_WIDTH") { + Ok(pw) => pw, Err(_) => { - determine_curve25519_dalek_bits_warning(ERR_MSG_NO_TARGET); - return DalekBits::Dalek32; - } - }; - - // platforms crate is the source of truth used to determine the platform - let platform = match platforms::Platform::find(&target_triplet) { - Some(p) => p, - None => { - determine_curve25519_dalek_bits_warning(ERR_MSG_NO_PLATFORM); + determine_curve25519_dalek_bits_warning(ERR_MSG_NO_POINTER_WIDTH); return DalekBits::Dalek32; } }; #[allow(clippy::match_single_binding)] - match platform.target_arch { + match &target_arch { //Issues: 449 and 456 + //TODO: When adding arch defaults use proper types not String match //TODO(Arm): Needs tests + benchmarks to back this up - //platforms::target::Arch::Arm => DalekBits::Dalek64, //TODO(Wasm32): Needs tests + benchmarks to back this up - //platforms::target::Arch::Wasm32 => DalekBits::Dalek64, - _ => match platform.target_pointer_width { - PointerWidth::U64 => DalekBits::Dalek64, - PointerWidth::U32 => DalekBits::Dalek32, + _ => match target_pointer_width.as_ref() { + "64" => DalekBits::Dalek64, + "32" => DalekBits::Dalek32, // Intended default solely for non-32/64 target pointer widths // Otherwise known target platforms only. - _ => DalekBits::Dalek32, + _ => { + determine_curve25519_dalek_bits_warning(ERR_MSG_UNKNOWN_POINTER_WIDTH); + DalekBits::Dalek32 + } }, } } From 858c4ca8ae03d33fe8b71b4504c4d3f5ff5b45c0 Mon Sep 17 00:00:00 2001 From: "pinkforest(she/her)" <36498018+pinkforest@users.noreply.github.com> Date: Fri, 8 Mar 2024 10:58:20 +1100 Subject: [PATCH 29/32] Address new nightly clippy unnecessary qualifications (#639) --- curve25519-dalek/src/backend/mod.rs | 51 +++++++++---------- .../src/backend/serial/curve_models/mod.rs | 8 +-- .../src/backend/serial/fiat_u32/field.rs | 2 +- .../src/backend/serial/fiat_u64/field.rs | 2 +- .../src/backend/serial/u32/field.rs | 2 +- .../src/backend/serial/u32/scalar.rs | 2 +- .../src/backend/serial/u64/field.rs | 2 +- .../src/backend/serial/u64/scalar.rs | 2 +- curve25519-dalek/src/edwards.rs | 10 ++-- curve25519-dalek/src/ristretto.rs | 8 +-- curve25519-dalek/src/scalar.rs | 6 +-- curve25519-dalek/src/window.rs | 6 +-- ed25519-dalek/src/signature.rs | 2 +- ed25519-dalek/src/signing.rs | 4 +- ed25519-dalek/src/verifying.rs | 2 +- 15 files changed, 52 insertions(+), 57 deletions(-) diff --git a/curve25519-dalek/src/backend/mod.rs b/curve25519-dalek/src/backend/mod.rs index 4424e0a5..9ad1dd3d 100644 --- a/curve25519-dalek/src/backend/mod.rs +++ b/curve25519-dalek/src/backend/mod.rs @@ -87,24 +87,24 @@ where match get_selected_backend() { #[cfg(curve25519_dalek_backend = "simd")] BackendKind::Avx2 => - self::vector::scalar_mul::pippenger::spec_avx2::Pippenger::optional_multiscalar_mul::(scalars, points), + vector::scalar_mul::pippenger::spec_avx2::Pippenger::optional_multiscalar_mul::(scalars, points), #[cfg(all(curve25519_dalek_backend = "simd", nightly))] BackendKind::Avx512 => - self::vector::scalar_mul::pippenger::spec_avx512ifma_avx512vl::Pippenger::optional_multiscalar_mul::(scalars, points), + vector::scalar_mul::pippenger::spec_avx512ifma_avx512vl::Pippenger::optional_multiscalar_mul::(scalars, points), BackendKind::Serial => - self::serial::scalar_mul::pippenger::Pippenger::optional_multiscalar_mul::(scalars, points), + serial::scalar_mul::pippenger::Pippenger::optional_multiscalar_mul::(scalars, points), } } #[cfg(feature = "alloc")] pub(crate) enum VartimePrecomputedStraus { #[cfg(curve25519_dalek_backend = "simd")] - Avx2(self::vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus), + Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus), #[cfg(all(curve25519_dalek_backend = "simd", nightly))] Avx512ifma( - self::vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus, + vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus, ), - Scalar(self::serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus), + Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus), } #[cfg(feature = "alloc")] @@ -119,12 +119,12 @@ impl VartimePrecomputedStraus { match get_selected_backend() { #[cfg(curve25519_dalek_backend = "simd")] BackendKind::Avx2 => - VartimePrecomputedStraus::Avx2(self::vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus::new(static_points)), + VartimePrecomputedStraus::Avx2(vector::scalar_mul::precomputed_straus::spec_avx2::VartimePrecomputedStraus::new(static_points)), #[cfg(all(curve25519_dalek_backend = "simd", nightly))] BackendKind::Avx512 => - VartimePrecomputedStraus::Avx512ifma(self::vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus::new(static_points)), + VartimePrecomputedStraus::Avx512ifma(vector::scalar_mul::precomputed_straus::spec_avx512ifma_avx512vl::VartimePrecomputedStraus::new(static_points)), BackendKind::Serial => - VartimePrecomputedStraus::Scalar(self::serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points)) + VartimePrecomputedStraus::Scalar(serial::scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points)) } } @@ -179,19 +179,16 @@ where match get_selected_backend() { #[cfg(curve25519_dalek_backend = "simd")] BackendKind::Avx2 => { - self::vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::( - scalars, points, - ) + vector::scalar_mul::straus::spec_avx2::Straus::multiscalar_mul::(scalars, points) } #[cfg(all(curve25519_dalek_backend = "simd", nightly))] BackendKind::Avx512 => { - self::vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::< - I, - J, - >(scalars, points) + vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::multiscalar_mul::( + scalars, points, + ) } BackendKind::Serial => { - self::serial::scalar_mul::straus::Straus::multiscalar_mul::(scalars, points) + serial::scalar_mul::straus::Straus::multiscalar_mul::(scalars, points) } } } @@ -209,21 +206,19 @@ where match get_selected_backend() { #[cfg(curve25519_dalek_backend = "simd")] BackendKind::Avx2 => { - self::vector::scalar_mul::straus::spec_avx2::Straus::optional_multiscalar_mul::( + vector::scalar_mul::straus::spec_avx2::Straus::optional_multiscalar_mul::( scalars, points, ) } #[cfg(all(curve25519_dalek_backend = "simd", nightly))] BackendKind::Avx512 => { - self::vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::< + vector::scalar_mul::straus::spec_avx512ifma_avx512vl::Straus::optional_multiscalar_mul::< I, J, >(scalars, points) } BackendKind::Serial => { - self::serial::scalar_mul::straus::Straus::optional_multiscalar_mul::( - scalars, points, - ) + serial::scalar_mul::straus::Straus::optional_multiscalar_mul::(scalars, points) } } } @@ -232,12 +227,12 @@ where pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint { match get_selected_backend() { #[cfg(curve25519_dalek_backend = "simd")] - BackendKind::Avx2 => self::vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar), + BackendKind::Avx2 => vector::scalar_mul::variable_base::spec_avx2::mul(point, scalar), #[cfg(all(curve25519_dalek_backend = "simd", nightly))] BackendKind::Avx512 => { - self::vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar) + vector::scalar_mul::variable_base::spec_avx512ifma_avx512vl::mul(point, scalar) } - BackendKind::Serial => self::serial::scalar_mul::variable_base::mul(point, scalar), + BackendKind::Serial => serial::scalar_mul::variable_base::mul(point, scalar), } } @@ -246,11 +241,11 @@ pub fn variable_base_mul(point: &EdwardsPoint, scalar: &Scalar) -> EdwardsPoint pub fn vartime_double_base_mul(a: &Scalar, A: &EdwardsPoint, b: &Scalar) -> EdwardsPoint { match get_selected_backend() { #[cfg(curve25519_dalek_backend = "simd")] - BackendKind::Avx2 => self::vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b), + BackendKind::Avx2 => vector::scalar_mul::vartime_double_base::spec_avx2::mul(a, A, b), #[cfg(all(curve25519_dalek_backend = "simd", nightly))] BackendKind::Avx512 => { - self::vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b) + vector::scalar_mul::vartime_double_base::spec_avx512ifma_avx512vl::mul(a, A, b) } - BackendKind::Serial => self::serial::scalar_mul::vartime_double_base::mul(a, A, b), + BackendKind::Serial => serial::scalar_mul::vartime_double_base::mul(a, A, b), } } diff --git a/curve25519-dalek/src/backend/serial/curve_models/mod.rs b/curve25519-dalek/src/backend/serial/curve_models/mod.rs index d482d721..1343d370 100644 --- a/curve25519-dalek/src/backend/serial/curve_models/mod.rs +++ b/curve25519-dalek/src/backend/serial/curve_models/mod.rs @@ -527,7 +527,7 @@ impl<'a> Neg for &'a AffineNielsPoint { // ------------------------------------------------------------------------ impl Debug for ProjectivePoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "ProjectivePoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?}\n}}", @@ -537,7 +537,7 @@ impl Debug for ProjectivePoint { } impl Debug for CompletedPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "CompletedPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", @@ -547,7 +547,7 @@ impl Debug for CompletedPoint { } impl Debug for AffineNielsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "AffineNielsPoint{{\n\ty_plus_x: {:?},\n\ty_minus_x: {:?},\n\txy2d: {:?}\n}}", @@ -557,7 +557,7 @@ impl Debug for AffineNielsPoint { } impl Debug for ProjectiveNielsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "ProjectiveNielsPoint{{\n\tY_plus_X: {:?},\n\tY_minus_X: {:?},\n\tZ: {:?},\n\tT2d: {:?}\n}}", &self.Y_plus_X, &self.Y_minus_X, &self.Z, &self.T2d) } diff --git a/curve25519-dalek/src/backend/serial/fiat_u32/field.rs b/curve25519-dalek/src/backend/serial/fiat_u32/field.rs index 94e1f6d3..97695c38 100644 --- a/curve25519-dalek/src/backend/serial/fiat_u32/field.rs +++ b/curve25519-dalek/src/backend/serial/fiat_u32/field.rs @@ -58,7 +58,7 @@ use fiat_crypto::curve25519_32::*; pub struct FieldElement2625(pub(crate) fiat_25519_tight_field_element); impl Debug for FieldElement2625 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "FieldElement2625({:?})", &(self.0).0[..]) } } diff --git a/curve25519-dalek/src/backend/serial/fiat_u64/field.rs b/curve25519-dalek/src/backend/serial/fiat_u64/field.rs index c871b55c..2a022e23 100644 --- a/curve25519-dalek/src/backend/serial/fiat_u64/field.rs +++ b/curve25519-dalek/src/backend/serial/fiat_u64/field.rs @@ -47,7 +47,7 @@ use fiat_crypto::curve25519_64::*; pub struct FieldElement51(pub(crate) fiat_25519_tight_field_element); impl Debug for FieldElement51 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "FieldElement51({:?})", &(self.0).0[..]) } } diff --git a/curve25519-dalek/src/backend/serial/u32/field.rs b/curve25519-dalek/src/backend/serial/u32/field.rs index 4e0b2133..7319288a 100644 --- a/curve25519-dalek/src/backend/serial/u32/field.rs +++ b/curve25519-dalek/src/backend/serial/u32/field.rs @@ -54,7 +54,7 @@ use zeroize::Zeroize; pub struct FieldElement2625(pub(crate) [u32; 10]); impl Debug for FieldElement2625 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "FieldElement2625({:?})", &self.0[..]) } } diff --git a/curve25519-dalek/src/backend/serial/u32/scalar.rs b/curve25519-dalek/src/backend/serial/u32/scalar.rs index c251e8bb..2d135d1d 100644 --- a/curve25519-dalek/src/backend/serial/u32/scalar.rs +++ b/curve25519-dalek/src/backend/serial/u32/scalar.rs @@ -24,7 +24,7 @@ use crate::constants; pub struct Scalar29(pub [u32; 9]); impl Debug for Scalar29 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Scalar29: {:?}", &self.0[..]) } } diff --git a/curve25519-dalek/src/backend/serial/u64/field.rs b/curve25519-dalek/src/backend/serial/u64/field.rs index 9659effa..1263d23e 100644 --- a/curve25519-dalek/src/backend/serial/u64/field.rs +++ b/curve25519-dalek/src/backend/serial/u64/field.rs @@ -43,7 +43,7 @@ use zeroize::Zeroize; pub struct FieldElement51(pub(crate) [u64; 5]); impl Debug for FieldElement51 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "FieldElement51({:?})", &self.0[..]) } } diff --git a/curve25519-dalek/src/backend/serial/u64/scalar.rs b/curve25519-dalek/src/backend/serial/u64/scalar.rs index dab80cdc..1cc2df4a 100644 --- a/curve25519-dalek/src/backend/serial/u64/scalar.rs +++ b/curve25519-dalek/src/backend/serial/u64/scalar.rs @@ -25,7 +25,7 @@ use crate::constants; pub struct Scalar52(pub [u64; 5]); impl Debug for Scalar52 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Scalar52: {:?}", &self.0[..]) } } diff --git a/curve25519-dalek/src/edwards.rs b/curve25519-dalek/src/edwards.rs index c49590b3..856fac12 100644 --- a/curve25519-dalek/src/edwards.rs +++ b/curve25519-dalek/src/edwards.rs @@ -171,7 +171,7 @@ impl ConstantTimeEq for CompressedEdwardsY { } impl Debug for CompressedEdwardsY { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "CompressedEdwardsY: {:?}", self.as_bytes()) } } @@ -302,7 +302,7 @@ impl<'de> Deserialize<'de> for EdwardsPoint { impl<'de> Visitor<'de> for EdwardsPointVisitor { type Value = EdwardsPoint; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("a valid point in Edwards y + sign format") } @@ -338,7 +338,7 @@ impl<'de> Deserialize<'de> for CompressedEdwardsY { impl<'de> Visitor<'de> for CompressedEdwardsYVisitor { type Value = CompressedEdwardsY; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("32 bytes of data") } @@ -1053,7 +1053,7 @@ macro_rules! impl_basepoint_table { } impl Debug for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}([\n", stringify!($name))?; for i in 0..32 { write!(f, "\t{:?},\n", &self.0[i])?; @@ -1264,7 +1264,7 @@ impl EdwardsPoint { // ------------------------------------------------------------------------ impl Debug for EdwardsPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", diff --git a/curve25519-dalek/src/ristretto.rs b/curve25519-dalek/src/ristretto.rs index 75ba141d..c9d16aba 100644 --- a/curve25519-dalek/src/ristretto.rs +++ b/curve25519-dalek/src/ristretto.rs @@ -407,7 +407,7 @@ impl<'de> Deserialize<'de> for RistrettoPoint { impl<'de> Visitor<'de> for RistrettoPointVisitor { type Value = RistrettoPoint; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("a valid point in Ristretto format") } @@ -443,7 +443,7 @@ impl<'de> Deserialize<'de> for CompressedRistretto { impl<'de> Visitor<'de> for CompressedRistrettoVisitor { type Value = CompressedRistretto; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str("32 bytes of data") } @@ -1155,13 +1155,13 @@ impl ConditionallySelectable for RistrettoPoint { // ------------------------------------------------------------------------ impl Debug for CompressedRistretto { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "CompressedRistretto: {:?}", self.as_bytes()) } } impl Debug for RistrettoPoint { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let coset = self.coset4(); write!( f, diff --git a/curve25519-dalek/src/scalar.rs b/curve25519-dalek/src/scalar.rs index 1630af5e..5e0d1c96 100644 --- a/curve25519-dalek/src/scalar.rs +++ b/curve25519-dalek/src/scalar.rs @@ -285,7 +285,7 @@ impl Scalar { } impl Debug for Scalar { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Scalar{{\n\tbytes: {:?},\n}}", &self.bytes) } } @@ -430,7 +430,7 @@ impl<'de> Deserialize<'de> for Scalar { impl<'de> Visitor<'de> for ScalarVisitor { type Value = Scalar; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { formatter.write_str( "a sequence of 32 bytes whose little-endian interpretation is less than the \ basepoint order ℓ", @@ -831,7 +831,7 @@ impl Scalar { } #[cfg(feature = "zeroize")] - zeroize::Zeroize::zeroize(&mut scratch); + Zeroize::zeroize(&mut scratch); ret } diff --git a/curve25519-dalek/src/window.rs b/curve25519-dalek/src/window.rs index 8c575ee0..43c4b3ab 100644 --- a/curve25519-dalek/src/window.rs +++ b/curve25519-dalek/src/window.rs @@ -83,7 +83,7 @@ macro_rules! impl_lookup_table { } impl Debug for $name { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{:?}(", stringify!($name))?; for x in self.0.iter() { @@ -193,7 +193,7 @@ impl NafLookupTable5 { } impl Debug for NafLookupTable5 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "NafLookupTable5({:?})", self.0) } } @@ -240,7 +240,7 @@ impl NafLookupTable8 { #[cfg(any(feature = "precomputed-tables", feature = "alloc"))] impl Debug for NafLookupTable8 { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { writeln!(f, "NafLookupTable8([")?; for i in 0..64 { writeln!(f, "\t{:?},", &self.0[i])?; diff --git a/ed25519-dalek/src/signature.rs b/ed25519-dalek/src/signature.rs index 32fde301..af827683 100644 --- a/ed25519-dalek/src/signature.rs +++ b/ed25519-dalek/src/signature.rs @@ -57,7 +57,7 @@ impl Clone for InternalSignature { } impl Debug for InternalSignature { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Signature( R: {:?}, s: {:?} )", &self.R, &self.s) } } diff --git a/ed25519-dalek/src/signing.rs b/ed25519-dalek/src/signing.rs index e2818fea..e63d34bb 100644 --- a/ed25519-dalek/src/signing.rs +++ b/ed25519-dalek/src/signing.rs @@ -543,7 +543,7 @@ impl AsRef for SigningKey { } impl Debug for SigningKey { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("SigningKey") .field("verifying_key", &self.verifying_key) .finish_non_exhaustive() // avoids printing `secret_key` @@ -742,7 +742,7 @@ impl<'d> Deserialize<'d> for SigningKey { impl<'de> serde::de::Visitor<'de> for SigningKeyVisitor { type Value = SigningKey; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(formatter, concat!("An ed25519 signing (private) key")) } diff --git a/ed25519-dalek/src/verifying.rs b/ed25519-dalek/src/verifying.rs index 0d154678..246951b4 100644 --- a/ed25519-dalek/src/verifying.rs +++ b/ed25519-dalek/src/verifying.rs @@ -642,7 +642,7 @@ impl<'d> Deserialize<'d> for VerifyingKey { impl<'de> serde::de::Visitor<'de> for VerifyingKeyVisitor { type Value = VerifyingKey; - fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(formatter, concat!("An ed25519 verifying (public) key")) } From cc3421a22fa7ee1f557cbe9243b450da53bbe962 Mon Sep 17 00:00:00 2001 From: Boyd Kane <33420535+beyarkay@users.noreply.github.com> Date: Sat, 16 Mar 2024 15:43:25 +0200 Subject: [PATCH 30/32] Indicate that the rand_core feature is required (#641) --- ed25519-dalek/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ed25519-dalek/src/lib.rs b/ed25519-dalek/src/lib.rs index a7cfac48..21d8737b 100644 --- a/ed25519-dalek/src/lib.rs +++ b/ed25519-dalek/src/lib.rs @@ -21,6 +21,7 @@ #![cfg_attr(feature = "rand_core", doc = "```")] #![cfg_attr(not(feature = "rand_core"), doc = "```ignore")] //! # fn main() { +//! // $ cargo add ed25519_dalek --features rand_core //! use rand::rngs::OsRng; //! use ed25519_dalek::SigningKey; //! use ed25519_dalek::Signature; From 1efe6a93b176c4389b78e81e52b2cf85d728aac6 Mon Sep 17 00:00:00 2001 From: Hiroki Kobayashi <3303362+koba-e964@users.noreply.github.com> Date: Sun, 14 Apr 2024 10:37:33 +0900 Subject: [PATCH 31/32] Fix a minor typo in signing.rs (#649) an -> a --- ed25519-dalek/src/signing.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ed25519-dalek/src/signing.rs b/ed25519-dalek/src/signing.rs index e63d34bb..8999f50d 100644 --- a/ed25519-dalek/src/signing.rs +++ b/ed25519-dalek/src/signing.rs @@ -131,7 +131,7 @@ impl SigningKey { /// # Returns /// /// A `Result` whose okay value is an EdDSA [`SigningKey`] or whose error value - /// is an `SignatureError` describing the error that occurred. + /// is a `SignatureError` describing the error that occurred. #[inline] pub fn from_keypair_bytes(bytes: &[u8; 64]) -> Result { let (secret_key, verifying_key) = bytes.split_at(SECRET_KEY_LENGTH); From 9252fa5c0d09054fed4ac4d649e63c40fad7abaf Mon Sep 17 00:00:00 2001 From: "pinkforest(she/her)" <36498018+pinkforest@users.noreply.github.com> Date: Thu, 9 May 2024 23:24:16 +1000 Subject: [PATCH 32/32] Mitigate check-cfg until MSRV 1.77 (#652) --- curve25519-dalek-derive/tests/tests.rs | 9 +-------- curve25519-dalek/src/lib.rs | 2 ++ curve25519-dalek/src/scalar.rs | 2 ++ x25519-dalek/src/lib.rs | 1 - 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/curve25519-dalek-derive/tests/tests.rs b/curve25519-dalek-derive/tests/tests.rs index 1516b352..dce30c86 100644 --- a/curve25519-dalek-derive/tests/tests.rs +++ b/curve25519-dalek-derive/tests/tests.rs @@ -23,10 +23,6 @@ where a - b } -#[unsafe_target_feature("sse2")] -#[cfg(feature = "dummy")] -fn function_with_cfg() {} - #[unsafe_target_feature("sse2")] #[rustfmt::skip] fn function_with_rustfmt_skip() {} @@ -45,9 +41,6 @@ impl Struct { fn member_function_with_const_arg(self) -> u32 { self.a - N } - - #[cfg(feature = "dummy")] - fn member_function_with_cfg() {} } struct StructWithGenerics @@ -93,7 +86,7 @@ mod inner { } } -#[unsafe_target_feature_specialize("sse2", "avx2", conditional("avx512ifma", disabled))] +#[unsafe_target_feature_specialize("sse2", "avx2")] mod inner_spec { #[for_target_feature("sse2")] const CONST: u32 = 1; diff --git a/curve25519-dalek/src/lib.rs b/curve25519-dalek/src/lib.rs index d8666453..fecfe888 100644 --- a/curve25519-dalek/src/lib.rs +++ b/curve25519-dalek/src/lib.rs @@ -42,6 +42,8 @@ unused_lifetimes, unused_qualifications )] +// Requires MSRV 1.77 as it does not allow build.rs gating +#![allow(unexpected_cfgs)] //------------------------------------------------------------------------ // External dependencies: diff --git a/curve25519-dalek/src/scalar.rs b/curve25519-dalek/src/scalar.rs index 5e0d1c96..6afd74ee 100644 --- a/curve25519-dalek/src/scalar.rs +++ b/curve25519-dalek/src/scalar.rs @@ -1233,10 +1233,12 @@ impl Field for Scalar { } fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { + #[allow(unused_qualifications)] group::ff::helpers::sqrt_ratio_generic(num, div) } fn sqrt(&self) -> CtOption { + #[allow(unused_qualifications)] group::ff::helpers::sqrt_tonelli_shanks( self, [ diff --git a/x25519-dalek/src/lib.rs b/x25519-dalek/src/lib.rs index 9a5fc193..7886eeaa 100644 --- a/x25519-dalek/src/lib.rs +++ b/x25519-dalek/src/lib.rs @@ -15,7 +15,6 @@ // README.md as the crate documentation. #![no_std] -#![cfg_attr(feature = "bench", feature(test))] #![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg, doc_cfg_hide))] #![cfg_attr(docsrs, doc(cfg_hide(docsrs)))] #![deny(missing_docs)]