1#![deny(
6 unused_import_braces,
7 unused_imports,
8 unused_comparisons,
9 unused_must_use,
10 unused_variables,
11 non_shorthand_field_patterns,
12 unreachable_code,
13 unused_parens
14)]
15#![cfg_attr(not(feature = "std"), no_std)]
16
17use curve::Field;
18pub use tiny_ec_core::*;
19
20use arrayref::{array_mut_ref, array_ref};
21use core::convert::TryFrom;
22
23use crate::curve::{Affine, ECMultContext, ECMultGenContext, Jacobian, Scalar};
24#[cfg(feature = "std")]
25#[cfg(all(feature = "static-context"))]
26pub static ECMULT_CONTEXT: ECMultContext =
29 unsafe { ECMultContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const.rs"))) };
30
31#[cfg(all(feature = "static-context"))]
32pub static ECMULT_GEN_CONTEXT: ECMultGenContext =
35 unsafe { ECMultGenContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const_gen.rs"))) };
36
37use serde::{Deserialize, Serialize};
38
39#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
40pub struct PublicKey(Affine);
42
43#[derive(Debug, Clone, Copy, Eq, PartialEq)]
44pub struct SecretKey(Scalar);
46
47#[derive(Debug, Clone, Copy, Eq, PartialEq)]
48pub struct Signature {
50 pub r: Scalar,
51 pub s: Scalar,
52}
53
54#[derive(Debug, Clone, Copy, Eq, PartialEq)]
55pub struct RecoveryId(u8);
57
58#[derive(Debug, Clone, Copy, Eq, PartialEq)]
59pub struct Message(pub Scalar);
61
62pub enum PublicKeyFormat {
64 Compressed,
66 Full,
68 Raw,
70}
71
72impl PublicKey {
73 pub fn from_secret_key_with_context(
74 seckey: &SecretKey,
75 context: &ECMultGenContext,
76 ) -> PublicKey {
77 let mut pj = Jacobian::default();
78 context.ecmult_gen(&mut pj, &seckey.0);
79 let mut p = Affine::default();
80 p.set_gej(&pj);
81 PublicKey(p)
82 }
83
84 #[cfg(any(feature = "static-context"))]
85 pub fn from_secret_key(seckey: &SecretKey) -> PublicKey {
86 Self::from_secret_key_with_context(seckey, &ECMULT_GEN_CONTEXT)
87 }
88
89 pub fn parse_slice(p: &[u8], format: Option<PublicKeyFormat>) -> Result<PublicKey, Error> {
90 let format = match (p.len(), format) {
91 (util::FULL_PUBLIC_KEY_SIZE, None)
92 | (util::FULL_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Full)) => PublicKeyFormat::Full,
93 (util::COMPRESSED_PUBLIC_KEY_SIZE, None)
94 | (util::COMPRESSED_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Compressed)) => {
95 PublicKeyFormat::Compressed
96 }
97 (util::RAW_PUBLIC_KEY_SIZE, None)
98 | (util::RAW_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Raw)) => PublicKeyFormat::Raw,
99 _ => return Err(Error::InvalidInputLength),
100 };
101
102 match format {
103 PublicKeyFormat::Full => {
104 let mut a = [0; util::FULL_PUBLIC_KEY_SIZE];
105 a.copy_from_slice(p);
106 Self::parse(&a)
107 }
108 PublicKeyFormat::Raw => {
109 use util::TAG_PUBKEY_FULL;
110
111 let mut a = [0; util::FULL_PUBLIC_KEY_SIZE];
112 a[0] = TAG_PUBKEY_FULL;
113 a[1..].copy_from_slice(p);
114 Self::parse(&a)
115 }
116 PublicKeyFormat::Compressed => {
117 let mut a = [0; util::COMPRESSED_PUBLIC_KEY_SIZE];
118 a.copy_from_slice(p);
119 Self::parse_compressed(&a)
120 }
121 }
122 }
123
124 pub fn parse(p: &[u8; util::FULL_PUBLIC_KEY_SIZE]) -> Result<PublicKey, Error> {
125 use util::{TAG_PUBKEY_FULL, TAG_PUBKEY_HYBRID_EVEN, TAG_PUBKEY_HYBRID_ODD};
126
127 if !(p[0] == TAG_PUBKEY_FULL
128 || p[0] == TAG_PUBKEY_HYBRID_EVEN
129 || p[0] == TAG_PUBKEY_HYBRID_ODD)
130 {
131 return Err(Error::InvalidPublicKey);
132 }
133 let mut x = Field::default();
134 let mut y = Field::default();
135 if !x.set_b32(array_ref!(p, 1, 32)) {
136 return Err(Error::InvalidPublicKey);
137 }
138 if !y.set_b32(array_ref!(p, 33, 32)) {
139 return Err(Error::InvalidPublicKey);
140 }
141 let mut elem = Affine::default();
142 elem.set_xy(&x, &y);
143 if (p[0] == TAG_PUBKEY_HYBRID_EVEN || p[0] == TAG_PUBKEY_HYBRID_ODD)
144 && (y.is_odd() != (p[0] == TAG_PUBKEY_HYBRID_ODD))
145 {
146 return Err(Error::InvalidPublicKey);
147 }
148 if elem.is_infinity() {
149 return Err(Error::InvalidPublicKey);
150 }
151 if elem.is_valid_var() {
152 Ok(PublicKey(elem))
153 } else {
154 Err(Error::InvalidPublicKey)
155 }
156 }
157
158 pub fn parse_compressed(
159 p: &[u8; util::COMPRESSED_PUBLIC_KEY_SIZE],
160 ) -> Result<PublicKey, Error> {
161 use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD};
162
163 if !(p[0] == TAG_PUBKEY_EVEN || p[0] == TAG_PUBKEY_ODD) {
164 return Err(Error::InvalidPublicKey);
165 }
166 let mut x = Field::default();
167 if !x.set_b32(array_ref!(p, 1, 32)) {
168 return Err(Error::InvalidPublicKey);
169 }
170 let mut elem = Affine::default();
171 elem.set_xo_var(&x, p[0] == TAG_PUBKEY_ODD);
172 if elem.is_infinity() {
173 return Err(Error::InvalidPublicKey);
174 }
175 if elem.is_valid_var() {
176 Ok(PublicKey(elem))
177 } else {
178 Err(Error::InvalidPublicKey)
179 }
180 }
181
182 pub fn serialize(&self) -> [u8; util::FULL_PUBLIC_KEY_SIZE] {
183 use util::TAG_PUBKEY_FULL;
184
185 debug_assert!(!self.0.is_infinity());
186
187 let mut ret = [0u8; 65];
188 let mut elem = self.0;
189
190 elem.x.normalize_var();
191 elem.y.normalize_var();
192 elem.x.fill_b32(array_mut_ref!(ret, 1, 32));
193 elem.y.fill_b32(array_mut_ref!(ret, 33, 32));
194 ret[0] = TAG_PUBKEY_FULL;
195
196 ret
197 }
198
199 pub fn serialize_compressed(&self) -> [u8; util::COMPRESSED_PUBLIC_KEY_SIZE] {
200 use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD};
201
202 debug_assert!(!self.0.is_infinity());
203
204 let mut ret = [0u8; 33];
205 let mut elem = self.0;
206
207 elem.x.normalize_var();
208 elem.y.normalize_var();
209 elem.x.fill_b32(array_mut_ref!(ret, 1, 32));
210 ret[0] = if elem.y.is_odd() {
211 TAG_PUBKEY_ODD
212 } else {
213 TAG_PUBKEY_EVEN
214 };
215
216 ret
217 }
218}
219
220impl Into<Affine> for PublicKey {
221 fn into(self) -> Affine {
222 self.0
223 }
224}
225
226impl TryFrom<Affine> for PublicKey {
227 type Error = Error;
228
229 fn try_from(value: Affine) -> Result<Self, Self::Error> {
230 if value.is_infinity() || !value.is_valid_var() {
231 Err(Error::InvalidAffine)
232 } else {
233 Ok(PublicKey(value))
234 }
235 }
236}
237
238impl SecretKey {
239 pub fn parse(p: &[u8; util::SECRET_KEY_SIZE]) -> Result<SecretKey, Error> {
240 let mut elem = Scalar::default();
241 if !bool::from(elem.set_b32(p)) {
242 Self::try_from(elem)
243 } else {
244 Err(Error::InvalidSecretKey)
245 }
246 }
247
248 pub fn parse_slice(p: &[u8]) -> Result<SecretKey, Error> {
249 if p.len() != util::SECRET_KEY_SIZE {
250 return Err(Error::InvalidInputLength);
251 }
252
253 let mut a = [0; 32];
254 a.copy_from_slice(p);
255 Self::parse(&a)
256 }
257
258 pub fn serialize(&self) -> [u8; util::SECRET_KEY_SIZE] {
259 self.0.b32()
260 }
261
262 pub fn tweak_add_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
263 let v = self.0 + tweak.0;
264 if v.is_zero() {
265 return Err(Error::TweakOutOfRange);
266 }
267 self.0 = v;
268 Ok(())
269 }
270
271 pub fn tweak_mul_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
272 if tweak.0.is_zero() {
273 return Err(Error::TweakOutOfRange);
274 }
275
276 self.0 *= &tweak.0;
277 Ok(())
278 }
279
280 pub fn inv(&self) -> Self {
281 SecretKey(self.0.inv())
282 }
283
284 pub fn clear(&mut self) {
285 self.0.clear();
286 }
287
288 pub fn is_zero(&self) -> bool {
289 self.0.is_zero()
290 }
291}
292
293impl Default for SecretKey {
294 fn default() -> SecretKey {
295 let mut elem = Scalar::default();
296 let overflowed = bool::from(elem.set_b32(&[
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x01,
300 ]));
301 debug_assert!(!overflowed);
302 debug_assert!(!elem.is_zero());
303 SecretKey(elem)
304 }
305}
306
307impl Into<Scalar> for SecretKey {
308 fn into(self) -> Scalar {
309 self.0
310 }
311}
312
313impl TryFrom<Scalar> for SecretKey {
314 type Error = Error;
315
316 fn try_from(scalar: Scalar) -> Result<Self, Error> {
317 if scalar.is_zero() {
318 Err(Error::InvalidSecretKey)
319 } else {
320 Ok(Self(scalar))
321 }
322 }
323}
324
325impl core::fmt::LowerHex for SecretKey {
326 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
327 let scalar = self.0;
328
329 write!(f, "{:x}", scalar)
330 }
331}
332
333#[cfg(test)]
334mod tests {
335 use crate::SecretKey;
336 use hex_literal::hex;
337
338 #[test]
339 fn secret_key_inverse_is_sane() {
340 let sk = SecretKey::parse(&[1; 32]).unwrap();
341 let inv = sk.inv();
342 let invinv = inv.inv();
343 assert_eq!(sk, invinv);
344 assert_eq!(
346 inv,
347 SecretKey::parse(&hex!(
348 "1536f1d756d1abf83aaf173bc5ee3fc487c93010f18624d80bd6d4038fadd59e"
349 ))
350 .unwrap()
351 )
352 }
353
354 #[test]
355 fn secret_key_clear_is_correct() {
356 let mut sk = SecretKey::parse(&[1; 32]).unwrap();
357 sk.clear();
358 assert_eq!(sk.is_zero(), true);
359 }
360}