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