From 0c68d6a6d789039692ac864da239d8279820dd74 Mon Sep 17 00:00:00 2001
From: Tony Arcieri <bascule@gmail.com>
Date: Thu, 9 Nov 2023 19:22:14 -0700
Subject: [PATCH] p521: `serde` feature

Adds `serde::{Serialize, Deserialize}` impls for `AffinePoint` and
`Scalar`.
---
 Cargo.lock                    |  1 +
 p521/Cargo.toml               |  4 +++-
 p521/src/arithmetic/scalar.rs | 20 ++++++++++++++++++++
 p521/src/lib.rs               | 10 ++++++++++
 4 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/Cargo.lock b/Cargo.lock
index c35b0a45..e05fbe62 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -785,6 +785,7 @@ dependencies = [
  "hex-literal",
  "primeorder",
  "rand_core",
+ "serdect",
  "sha2",
 ]
 
diff --git a/p521/Cargo.toml b/p521/Cargo.toml
index 9d7fd6bd..18829e28 100644
--- a/p521/Cargo.toml
+++ b/p521/Cargo.toml
@@ -24,6 +24,7 @@ ecdsa-core = { version = "0.16.5", package = "ecdsa", optional = true, default-f
 hex-literal = { version = "0.4", optional = true }
 primeorder = { version = "0.13.3", optional = true, path = "../primeorder" }
 rand_core = { version = "0.6", optional = true, default-features = false }
+serdect = { version = "0.2", optional = true, default-features = false }
 sha2 = { version = "0.10", optional = true, default-features = false }
 
 [dev-dependencies]
@@ -45,7 +46,8 @@ ecdsa = ["arithmetic", "ecdsa-core/signing", "ecdsa-core/verifying", "sha512"]
 getrandom = ["rand_core/getrandom"]
 jwk = ["elliptic-curve/jwk"]
 pem = ["elliptic-curve/pem", "pkcs8"]
-pkcs8 = ["elliptic-curve/pkcs8"]
+pkcs8 = ["ecdsa-core?/pkcs8", "elliptic-curve/pkcs8"]
+serde = ["ecdsa-core?/serde", "elliptic-curve/serde", "primeorder?/serde", "serdect"]
 sha512 = ["digest", "dep:sha2"]
 test-vectors = ["dep:hex-literal"]
 voprf = ["elliptic-curve/voprf", "dep:sha2"]
diff --git a/p521/src/arithmetic/scalar.rs b/p521/src/arithmetic/scalar.rs
index 4bccab3f..66de4997 100644
--- a/p521/src/arithmetic/scalar.rs
+++ b/p521/src/arithmetic/scalar.rs
@@ -654,6 +654,26 @@ impl TryFrom<U576> for Scalar {
     }
 }
 
+#[cfg(feature = "serde")]
+impl Serialize for Scalar {
+    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
+    where
+        S: ser::Serializer,
+    {
+        ScalarPrimitive::from(self).serialize(serializer)
+    }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> Deserialize<'de> for Scalar {
+    fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
+    where
+        D: de::Deserializer<'de>,
+    {
+        Ok(ScalarPrimitive::deserialize(deserializer)?.into())
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::Scalar;
diff --git a/p521/src/lib.rs b/p521/src/lib.rs
index 83a61a5c..e0056a01 100644
--- a/p521/src/lib.rs
+++ b/p521/src/lib.rs
@@ -15,6 +15,16 @@
     unused_qualifications
 )]
 
+//! ## `serde` support
+//!
+//! When the `serde` feature of this crate is enabled, `Serialize` and
+//! `Deserialize` are impl'd for the following types:
+//!
+//! - [`AffinePoint`]
+//! - [`Scalar`]
+//!
+//! Please see type-specific documentation for more information.
+
 #[cfg(feature = "arithmetic")]
 mod arithmetic;