rustolio_utils/crypto/
signature.rs1use p256::ecdsa::{
13 self,
14 signature::{Signer, Verifier},
15 SigningKey, VerifyingKey,
16};
17
18use crate::bytes::Bytes;
19use crate::prelude::*;
20
21use super::{hash, rand};
22
23pub type Result<T> = std::result::Result<T, Error>;
24
25#[derive(Debug, Clone, Copy, PartialEq)]
26pub enum Error {
27 Parse,
28 InvalidPublicKey,
29 InvalidPrivateKey,
30 InvalidSignature,
31}
32
33impl std::fmt::Display for Error {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 write!(f, "{self:?}")
36 }
37}
38
39impl std::error::Error for Error {}
40
41#[derive(Debug, Clone)]
42pub struct PrivateKey(SigningKey);
43
44impl PrivateKey {
45 pub fn generate() -> rand::Result<Self> {
46 let key = loop {
47 let key = rand::array()?;
48 if key != [0; 32] && key != [0xFF; 32] {
50 break key;
51 }
52 };
53 let signing_key = SigningKey::from_bytes(&key.into()).unwrap();
54 Ok(Self(signing_key))
55 }
56
57 pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self> {
58 let Ok(k) = SigningKey::from_bytes(bytes.as_ref().into()) else {
59 return Err(Error::InvalidPrivateKey);
60 };
61 Ok(Self(k))
62 }
63
64 pub fn to_bytes(&self) -> [u8; 32] {
65 self.0.to_bytes().into()
66 }
67
68 pub fn sign_hash(&self, hash: &hash::Digest) -> Signature {
69 Signature(self.0.sign(hash.as_ref()))
70 }
71
72 pub fn sign<T: std::hash::Hash>(&self, value: T) -> SignedValue<T> {
73 let hash = hash::Hasher::once(&value);
74 let sig = self.sign_hash(&hash);
75 SignedValue {
76 value,
77 sig,
78 signer: self.public_key(),
79 }
80 }
81
82 pub fn public_key(&self) -> PublicKey {
83 PublicKey(VerifyingKey::from(&self.0))
84 }
85}
86
87impl std::ops::Deref for PrivateKey {
88 type Target = SigningKey;
89 fn deref(&self) -> &Self::Target {
90 &self.0
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95pub struct PublicKey(VerifyingKey);
96
97impl std::hash::Hash for PublicKey {
98 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
99 self.to_sec1_bytes().hash(state);
100 }
101}
102
103impl Encode for PublicKey {
104 #[async_impl]
105 async fn encode_async(
106 &self,
107 writer: &mut impl __utils_macros::AsyncEncoder,
108 ) -> crate::Result<()> {
109 self.to_bytes().encode_async(writer).await
110 }
111 fn encode_size(&self) -> usize {
112 65
113 }
114}
115
116impl Decode for PublicKey {
117 #[async_impl]
118 async fn decode_async(reader: &mut impl __utils_macros::AsyncDecoder) -> crate::Result<Self> {
119 let bytes = Bytes::decode_async(reader).await?;
120 Self::from_bytes(bytes).context("Invalid data")
121 }
122}
123
124impl PublicKey {
125 pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self> {
126 let Ok(k) = VerifyingKey::from_sec1_bytes(bytes.as_ref()) else {
127 return Err(Error::InvalidPublicKey);
128 };
129 Ok(Self(k))
130 }
131
132 pub fn to_bytes(&self) -> Bytes {
133 Bytes::from(self.to_sec1_bytes())
134 }
135
136 pub fn verify_hash(&self, hash: &hash::Digest, sig: &Signature) -> Result<()> {
137 if self.0.verify(hash.as_ref(), &sig.0).is_err() {
138 return Err(Error::InvalidSignature);
139 }
140 Ok(())
141 }
142}
143
144impl std::ops::Deref for PublicKey {
145 type Target = VerifyingKey;
146 fn deref(&self) -> &Self::Target {
147 &self.0
148 }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
152pub struct Signature(ecdsa::Signature);
153
154impl Encode for Signature {
155 #[async_impl]
156 async fn encode_async(
157 &self,
158 writer: &mut impl __utils_macros::AsyncEncoder,
159 ) -> crate::Result<()> {
160 self.to_bytes().encode_async(writer).await
161 }
162 fn encode_size(&self) -> usize {
163 64
164 }
165}
166
167impl Decode for Signature {
168 #[async_impl]
169 async fn decode_async(reader: &mut impl __utils_macros::AsyncDecoder) -> crate::Result<Self> {
170 let bytes = <[u8; 64]>::decode_async(reader).await?;
171 Self::from_bytes(bytes).context("Invalid data")
172 }
173}
174
175impl Signature {
176 pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Signature> {
177 let Ok(sig) = ecdsa::Signature::from_bytes(bytes.as_ref().into()) else {
178 return Err(Error::InvalidSignature);
179 };
180 Ok(Self(sig))
181 }
182
183 pub fn to_bytes(&self) -> [u8; 64] {
184 self.0.to_bytes().into()
185 }
186}
187
188impl std::ops::Deref for Signature {
189 type Target = ecdsa::Signature;
190 fn deref(&self) -> &Self::Target {
191 &self.0
192 }
193}
194
195#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
196pub struct SignedValue<T> {
197 value: T,
198 sig: Signature,
199 signer: PublicKey,
200}
201
202impl<T: std::hash::Hash> SignedValue<T> {
203 pub fn verify(&self) -> Result<()> {
204 let hash = hash::Hasher::once(&self.value);
205 self.signer.verify_hash(&hash, &self.sig)
206 }
207
208 pub fn into_value(self) -> T {
209 self.value
210 }
211
212 pub fn signer(&self) -> PublicKey {
213 self.signer
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 #[test]
222 fn test_signing() {
223 let private = PrivateKey::generate().unwrap();
224 let public = private.public_key();
225
226 let message =
227 b"ECDSA proves knowledge of a secret number in the context of a single message";
228 let hash = hash::Hasher::once(message);
229 let sig = private.sign_hash(&hash);
230
231 assert!(public.verify_hash(&hash, &sig).is_ok());
232 }
233
234 #[test]
235 fn test_signing_encoding_decoding() {
236 let private = PrivateKey::generate().unwrap();
237 let public = private.public_key();
238
239 let encoded_private = private.to_bytes();
240 let encoded_public = public.to_bytes();
241
242 let private = PrivateKey::from_bytes(&encoded_private).unwrap();
243 let public = PublicKey::from_bytes(&encoded_public).unwrap();
244
245 let message =
246 b"ECDSA proves knowledge of a secret number in the context of a single message";
247 let hash = hash::Hasher::once(message);
248 let sig = private.sign_hash(&hash);
249
250 assert!(public.verify_hash(&hash, &sig).is_ok());
251 }
252}