Commit df909da5d8

Chris Heyes <22148308+hazeycode@users.noreply.github.com>
2023-05-21 13:00:48
std.crypto: expose Fe isOdd & add basic parity tests for each pcurve (#15734)
* std Secp256k1 Scalar: expose Fe isOdd & add basic parity test * std.crypto: also add Scalar.isOdd convenience fn for p256 and p384 curves
1 parent b7cb883
Changed files (6)
lib
std
crypto
lib/std/crypto/pcurves/p256/scalar.zig
@@ -109,6 +109,11 @@ pub const Scalar = struct {
         return n.fe.isZero();
     }
 
+    /// Return true if the scalar is odd.
+    pub fn isOdd(n: Scalar) bool {
+        return n.fe.isOdd();
+    }
+
     /// Return true if a and b are equivalent.
     pub fn equivalent(a: Scalar, b: Scalar) bool {
         return a.fe.equivalent(b.fe);
lib/std/crypto/pcurves/p384/scalar.zig
@@ -98,6 +98,11 @@ pub const Scalar = struct {
         return n.fe.isZero();
     }
 
+    /// Return true if the scalar is odd.
+    pub fn isOdd(n: Scalar) bool {
+        return n.fe.isOdd();
+    }
+
     /// Return true if a and b are equivalent.
     pub fn equivalent(a: Scalar, b: Scalar) bool {
         return a.fe.equivalent(b.fe);
lib/std/crypto/pcurves/secp256k1/scalar.zig
@@ -109,6 +109,11 @@ pub const Scalar = struct {
         return n.fe.isZero();
     }
 
+    /// Return true if the scalar is odd.
+    pub fn isOdd(n: Scalar) bool {
+        return n.fe.isOdd();
+    }
+
     /// Return true if a and b are equivalent.
     pub fn equivalent(a: Scalar, b: Scalar) bool {
         return a.fe.equivalent(b.fe);
lib/std/crypto/pcurves/tests/p256.zig
@@ -134,3 +134,9 @@ test "p256 scalar inverse" {
     const inverse = scalar.invert();
     try std.testing.expectEqualSlices(u8, &out, &inverse.toBytes(.Big));
 }
+
+test "p256 scalar parity" {
+    try std.testing.expect(P256.scalar.Scalar.zero.isOdd() == false);
+    try std.testing.expect(P256.scalar.Scalar.one.isOdd());
+    try std.testing.expect(P256.scalar.Scalar.one.dbl().isOdd() == false);
+}
lib/std/crypto/pcurves/tests/p384.zig
@@ -144,3 +144,9 @@ test "p384 scalar inverse" {
     const sqr = try sq.sqrt();
     try testing.expect(sqr.equivalent(scalar));
 }
+
+test "p384 scalar parity" {
+    try std.testing.expect(P384.scalar.Scalar.zero.isOdd() == false);
+    try std.testing.expect(P384.scalar.Scalar.one.isOdd());
+    try std.testing.expect(P384.scalar.Scalar.one.dbl().isOdd() == false);
+}
lib/std/crypto/pcurves/tests/secp256k1.zig
@@ -135,3 +135,9 @@ test "secp256k1 scalar inverse" {
     const inverse = scalar.invert();
     try std.testing.expectEqualSlices(u8, &out, &inverse.toBytes(.Big));
 }
+
+test "secp256k1 scalar parity" {
+    try std.testing.expect(Secp256k1.scalar.Scalar.zero.isOdd() == false);
+    try std.testing.expect(Secp256k1.scalar.Scalar.one.isOdd());
+    try std.testing.expect(Secp256k1.scalar.Scalar.one.dbl().isOdd() == false);
+}