1#![cfg_attr(not(feature = "std"), no_std)]
2pub use k256;
3use k256::elliptic_curve::group::prime::PrimeCurveAffine;
4use k256::elliptic_curve::point::AffineCoordinates;
5use k256::elliptic_curve::sec1::{FromEncodedPoint, ToEncodedPoint};
6use k256::elliptic_curve::PrimeField;
7use k256::{AffinePoint, EncodedPoint, NonZeroScalar, ProjectivePoint, Scalar};
8use rand_core::{CryptoRng, RngCore};
9use sha3::Digest;
10
11pub mod proof_of_knowledge;
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum Error {
15 InvalidSecretKey,
16 InvalidPublicKey,
17 InvalidSignature,
18}
19
20impl core::fmt::Display for Error {
21 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
22 match self {
23 Self::InvalidSecretKey => write!(f, "invalid secret key"),
24 Self::InvalidPublicKey => write!(f, "invalid public key"),
25 Self::InvalidSignature => write!(f, "invalid signature"),
26 }
27 }
28}
29
30#[cfg(feature = "std")]
31impl std::error::Error for Error {}
32
33pub type Result<T, E = Error> = core::result::Result<T, E>;
34
35#[derive(Clone, Debug, Eq, PartialEq)]
36pub struct Signature {
37 pub e: Scalar,
38 pub z: Scalar,
39}
40
41impl Signature {
42 pub fn new(e: Scalar, z: Scalar) -> Self {
43 Self { e, z }
44 }
45
46 pub fn to_bytes(&self) -> [u8; 64] {
47 let mut bytes = [0; 64];
48 bytes[..32].copy_from_slice(&self.e.to_bytes());
49 bytes[32..].copy_from_slice(&self.z.to_bytes());
50 bytes
51 }
52
53 pub fn from_bytes(bytes: [u8; 64]) -> Result<Self> {
54 let e: &k256::FieldBytes = bytes[..32].try_into().unwrap();
55 let e = Option::from(Scalar::from_repr(*e)).ok_or(Error::InvalidSignature)?;
56 let z: &k256::FieldBytes = bytes[32..].try_into().unwrap();
57 let z = Option::from(Scalar::from_repr(*z)).ok_or(Error::InvalidSignature)?;
58 Ok(Self { e, z })
59 }
60}
61
62#[cfg(feature = "serde")]
63impl serde::Serialize for Signature {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: serde::Serializer,
67 {
68 serializer.serialize_bytes(self.to_bytes().as_ref())
69 }
70}
71
72#[cfg(feature = "serde")]
73impl<'de> serde::Deserialize<'de> for Signature {
74 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
75 where
76 D: serde::Deserializer<'de>,
77 {
78 let bytes = Vec::<u8>::deserialize(deserializer)?;
79 let array = bytes
80 .try_into()
81 .map_err(|_| serde::de::Error::custom("invalid byte length"))?;
82 let signature =
83 Self::from_bytes(array).map_err(|err| serde::de::Error::custom(format!("{err}")))?;
84 Ok(signature)
85 }
86}
87
88#[derive(Clone, Copy)]
89pub struct SigningKey {
90 scalar: NonZeroScalar,
91}
92
93impl SigningKey {
94 pub fn new<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
95 Self {
96 scalar: NonZeroScalar::random(rng),
97 }
98 }
99
100 #[cfg(feature = "std")]
101 pub fn random() -> Self {
102 Self::new(&mut rand_core::OsRng)
103 }
104
105 pub fn to_scalar(&self) -> NonZeroScalar {
106 self.scalar
107 }
108
109 pub fn to_bytes(&self) -> [u8; 32] {
110 self.scalar.to_bytes().into()
111 }
112
113 pub fn from_bytes(bytes: [u8; 32]) -> Result<Self> {
114 let scalar =
115 Option::from(NonZeroScalar::from_repr(bytes.into())).ok_or(Error::InvalidSecretKey)?;
116 Ok(Self { scalar })
117 }
118
119 pub fn public(&self) -> VerifyingKey {
120 VerifyingKey::new(AffinePoint::GENERATOR * self.scalar.as_ref())
121 }
122
123 pub fn sign_prehashed_with_rng<R: RngCore + CryptoRng>(
124 &self,
125 rng: &mut R,
126 hash: [u8; 32],
127 ) -> Signature {
128 let k = NonZeroScalar::random(rng);
129 let r = AffinePoint::GENERATOR * k.as_ref();
130 let public = self.public();
131 let c = public.challenge(hash, r);
132 let z = k.as_ref() + c * self.scalar.as_ref();
133 Signature::new(c, z)
134 }
135
136 #[cfg(feature = "std")]
137 pub fn sign_prehashed(&self, hash: [u8; 32]) -> Signature {
138 self.sign_prehashed_with_rng(&mut rand_core::OsRng, hash)
139 }
140
141 #[cfg(feature = "std")]
142 pub fn sign(&self, msg: &[u8]) -> Signature {
143 let hash = VerifyingKey::message_hash(msg);
144 self.sign_prehashed(hash)
145 }
146}
147
148#[derive(Clone, Copy, Debug, PartialEq)]
149pub struct VerifyingKey {
150 element: ProjectivePoint,
151}
152
153impl VerifyingKey {
154 pub fn new(element: ProjectivePoint) -> Self {
155 Self { element }
156 }
157
158 pub fn from_bytes(bytes: [u8; 33]) -> Result<Self, Error> {
159 let point = EncodedPoint::from_bytes(bytes).map_err(|_| Error::InvalidPublicKey)?;
160 let point: AffinePoint =
161 Option::from(AffinePoint::from_encoded_point(&point)).ok_or(Error::InvalidPublicKey)?;
162 if point.is_identity().into() {
163 return Err(Error::InvalidPublicKey);
164 }
165 Ok(Self::new(ProjectivePoint::from(point)))
166 }
167
168 pub fn to_bytes(self) -> Result<[u8; 33], Error> {
169 let point = self.to_affine().to_encoded_point(true);
170 point
172 .as_bytes()
173 .try_into()
174 .map_err(|_| Error::InvalidPublicKey)
175 }
176
177 pub fn to_element(self) -> ProjectivePoint {
178 self.element
179 }
180
181 fn to_affine(self) -> AffinePoint {
182 self.element.to_affine()
183 }
184
185 pub fn to_px_parity(self) -> ([u8; 32], u8) {
186 let affine = self.to_affine();
187 (affine.x().into(), affine.y_is_odd().unwrap_u8() + 27)
188 }
189
190 pub fn message_hash(message: &[u8]) -> [u8; 32] {
191 sha3::Keccak256::digest(message).into()
192 }
193
194 pub fn challenge(self, message_hash: [u8; 32], r: ProjectivePoint) -> Scalar {
195 let uncompressed = r.to_affine().to_encoded_point(false);
196 let digest = sha3::Keccak256::digest(&uncompressed.as_bytes()[1..]);
197 let address_r: [u8; 20] = digest[12..].try_into().unwrap();
198
199 let (pubkey_x, pubkey_y_parity) = self.to_px_parity();
200 let mut e_hasher = sha3::Keccak256::new();
201 e_hasher.update(address_r);
202 e_hasher.update([pubkey_y_parity]);
203 e_hasher.update(pubkey_x);
204 e_hasher.update(message_hash);
205 Scalar::from_repr(e_hasher.finalize()).unwrap()
206 }
207
208 pub fn verify_prehashed(
209 self,
210 message_hash: [u8; 32],
211 signature: &Signature,
212 ) -> Result<(), Error> {
213 let r = AffinePoint::GENERATOR * signature.z - self.element * signature.e;
214 let ep = self.challenge(message_hash, r);
215 if signature.e != ep {
216 return Err(Error::InvalidSignature);
217 }
218 Ok(())
219 }
220
221 pub fn verify(self, message: &[u8], signature: &Signature) -> Result<(), Error> {
222 self.verify_prehashed(Self::message_hash(message), signature)
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn test_sign() {
232 let key = SigningKey::random();
233 let public = key.public();
234 let sig = key.sign(b"hello world");
235 public.verify(b"hello world", &sig).unwrap();
236 }
237}