neo3/neo_crypto/
keys.rs

1//! # Secp256r1 Cryptographic Module
2//!
3//! This module provides cryptographic functionalities for the secp256r1 elliptic curve.
4//! It includes implementations for handling public keys, private keys, and signatures,
5//! as well as utilities for signing and verifying data.
6//!
7//! ## Features
8//!
9//! - Generation of public and private keys.
10//! - Conversion between different formats and representations of keys and signatures.
11//! - Signing data with a private key and verifying signatures with a public key.
12//! - Integration with external libraries like `neo-codec`, `p256`, and `rand_core` for cryptographic operations.
13//!
14//! ## Usage
15//!
16//! - `Secp256r1PublicKey`: Represents a public key on the secp256r1 curve. It can be created
17//!   from raw coordinates, existing `PublicKey` instances, or from byte slices.
18//!   It provides functionalities to verify signatures and to encode the key in various formats.
19//!
20//! - `Secp256r1PrivateKey`: Represents a private key on the secp256r1 curve. It can be randomly
21//!   generated or created from a byte slice. It provides methods to sign data and to retrieve
22//!   the associated public key.
23//!
24//! - `Secp256r1Signature`: Represents a digital signature generated using a secp256r1 private key.
25//!   It can be created from scalar values, `U256` representations, or from raw bytes. It offers
26//!   a method to convert the signature back into a byte array.
27//!
28//! ## Examples
29//!
30//! Basic usage involves creating a private key, generating a signature for a message, and then
31//! using the corresponding public key to verify the signature. Public and private keys can be
32//! converted to and from various formats for storage or transmission.
33//!
34//! ```
35//! use rand_core::OsRng;
36//! use neo3::neo_crypto::Secp256r1PrivateKey;
37//!
38//! // Generate a new private key
39//! let private_key = Secp256r1PrivateKey::random(&mut OsRng);
40//!
41//! // Sign a message
42//! let message = b"Example message";
43//! let signature = private_key.sign_tx(message).expect("Failed to sign message");
44//!
45//! // Obtain the public key
46//! let public_key = private_key.to_public_key();
47//!
48//! // Verify the signature
49//! assert!(public_key.verify(message, &signature).is_ok());
50//! ```
51//!
52//! Note: Error handling is crucial for cryptographic operations. Ensure proper error handling
53//! in real-world applications.
54
55use core::fmt;
56use std::{
57	cmp::Ordering,
58	fmt::Debug,
59	hash::{Hash, Hasher},
60};
61
62// use zeroize::Zeroize;
63use crate::{
64	codec::{Decoder, Encoder, NeoSerializable},
65	config::NeoConstants,
66	crypto::CryptoError,
67	neo_crypto::utils::{FromHexString, ToHexString},
68};
69use elliptic_curve::zeroize::Zeroize;
70use p256::{
71	ecdsa::{signature::Signer, Signature, SigningKey, VerifyingKey},
72	elliptic_curve::{
73		sec1::{FromEncodedPoint, ToEncodedPoint},
74		Field,
75	},
76	EncodedPoint, FieldBytes, PublicKey, SecretKey,
77};
78use primitive_types::U256;
79use rand_core::OsRng;
80use serde::{Deserialize, Deserializer, Serialize, Serializer};
81use signature::{hazmat::PrehashSigner, SignerMut, Verifier};
82
83#[cfg_attr(feature = "substrate", serde(crate = "serde_substrate"))]
84#[derive(Debug, Clone)]
85pub struct Secp256r1PublicKey {
86	inner: PublicKey,
87}
88
89#[derive(Debug, Clone)]
90pub struct Secp256r1PrivateKey {
91	inner: SecretKey,
92}
93
94#[derive(Clone)]
95pub struct Secp256r1Signature {
96	inner: Signature,
97}
98
99impl Debug for Secp256r1Signature {
100	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101		write!(f, "Secp256r1Signature")
102	}
103}
104
105#[derive(Debug, PartialEq, Clone)]
106pub struct Secp256r1SignedMsg<T: Serialize> {
107	pub msg: T,
108	pub signature: Secp256r1Signature,
109}
110
111impl Secp256r1PublicKey {
112	/// Constructs a new `Secp256r1PublicKey` from the given x and y coordinates.
113	///
114	/// This function attempts to create a public key from uncompressed x and y coordinates.
115	/// It returns `None` if the provided coordinates do not correspond to a valid point on the curve.
116	///
117	/// - Parameters:
118	///     - gx: The x coordinate of the public key.
119	///     - gy: The y coordinate of the public key.
120	///
121	/// - Returns: An `Option<Secp256r1PublicKey>`.
122	pub fn new(gx: [u8; 32], gy: [u8; 32]) -> Option<Self> {
123		let mut uncompressed_point = Vec::with_capacity(65);
124		uncompressed_point.push(0x04);
125		uncompressed_point.extend_from_slice(&gx);
126		uncompressed_point.extend_from_slice(&gy);
127
128		let encoded_point = EncodedPoint::from_bytes(&uncompressed_point).ok()?;
129		let public_key_option = PublicKey::from_encoded_point(&encoded_point);
130
131		if public_key_option.is_some().into() {
132			// Safe to unwrap since we checked is_some()
133			let public_key = public_key_option.unwrap();
134			Some(Secp256r1PublicKey { inner: public_key })
135		} else {
136			None
137		}
138	}
139
140	/// Constructs a `Secp256r1PublicKey` from an existing `PublicKey`.
141	///
142	/// This method can be used to convert a `PublicKey` from the `p256` crate into a `Secp256r1PublicKey`.
143	///
144	/// - Parameter public_key: A `PublicKey` instance.
145	///
146	/// - Returns: A `Secp256r1PublicKey` instance.
147	pub fn from_public_key(public_key: PublicKey) -> Self {
148		Secp256r1PublicKey { inner: public_key }
149	}
150
151	/// Constructs a `Secp256r1PublicKey` from a byte slice.
152	///
153	/// Attempts to parse a byte slice as an encoded elliptic curve point and create a public key.
154	/// Returns a `CryptoError` if the byte slice does not represent a valid public key.
155	///
156	/// - Parameter bytes: A byte slice representing an encoded elliptic curve point.
157	///
158	/// - Returns: A `Result<Secp256r1PublicKey, CryptoError>`.
159	pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
160		if bytes.len() != 33 && bytes.len() != 65 {
161			return Err(CryptoError::InvalidPublicKey);
162		}
163
164		let point = if bytes.len() == 33 {
165			// Compressed format
166			EncodedPoint::from_bytes(bytes).map_err(|_| CryptoError::InvalidPublicKey)?
167		} else {
168			// Uncompressed format
169			EncodedPoint::from_bytes(bytes).map_err(|_| CryptoError::InvalidPublicKey)?
170		};
171
172		let public_key = PublicKey::from_encoded_point(&point);
173		if public_key.is_some().into() {
174			Ok(Self { inner: public_key.unwrap() })
175		} else {
176			Err(CryptoError::InvalidPublicKey)
177		}
178	}
179
180	/// Verifies a digital signature against a message using this public key.
181	///
182	/// This method checks if the provided signature is valid for the given message under this public key.
183	/// Returns a `CryptoError` if the signature verification fails.
184	///
185	/// - Parameters:
186	///     - message: The message that was signed.
187	///     - signature: The signature to verify.
188	///
189	/// - Returns: A `Result<(), CryptoError>`.
190	pub fn verify(
191		&self,
192		message: &[u8],
193		signature: &Secp256r1Signature,
194	) -> Result<(), CryptoError> {
195		let verifying_key = VerifyingKey::from(&self.inner);
196
197		verifying_key
198			.verify(message, &signature.inner)
199			.map_err(|_| CryptoError::SignatureVerificationError)
200	}
201
202	/// Gets this public key's elliptic curve point encoded as defined in section 2.3.3 of [SEC1](http://www.secg.org/sec1-v2.pdf).
203	///
204	/// - Parameter compressed: If the EC point should be encoded in compressed or uncompressed format
205	///
206	/// - Returns: The encoded public key
207	pub fn get_encoded(&self, compressed: bool) -> Vec<u8> {
208		self.inner.to_encoded_point(compressed).as_bytes().to_vec()
209	}
210
211	pub fn get_encoded_point(&self, compressed: bool) -> EncodedPoint {
212		self.inner.to_encoded_point(compressed)
213	}
214
215	/// Gets this public key's elliptic curve point encoded as defined in section 2.3.3 of [SEC1](http://www.secg.org/sec1-v2.pdf)
216	/// in compressed format as hexadecimal.
217	///
218	/// - Returns: The encoded public key in compressed format as hexadecimal without a prefix
219	pub fn get_encoded_compressed_hex(&self) -> String {
220		let encoded = self.get_encoded(true);
221		encoded.to_hex_string()
222	}
223
224	/// Constructs a `Secp256r1PublicKey` from a hexadecimal string representation.
225	///
226	/// This method attempts to parse a hexadecimal string as an encoded elliptic curve point.
227	/// Returns `None` if the string is not a valid encoding or does not represent a valid public key.
228	///
229	/// - Parameter encoded: A hexadecimal string representing an encoded elliptic curve point.
230	///
231	/// - Returns: An `Option<Secp256r1PublicKey>`.
232	pub fn from_encoded(encoded: &str) -> Option<Self> {
233		let encoded = &encoded.replace("0x", "");
234		let encoded = encoded.from_hex_string().ok()?;
235
236		Secp256r1PublicKey::from_bytes(encoded.as_slice()).ok()
237	}
238
239	fn get_size(&self) -> usize {
240		if self.inner.to_encoded_point(false).is_identity() {
241			1
242		} else {
243			NeoConstants::PUBLIC_KEY_SIZE_COMPRESSED as usize
244		}
245	}
246}
247
248impl Secp256r1PrivateKey {
249	/// Generates a new private key using the provided random number generator (RNG).
250	///
251	/// - Parameter rng: A mutable reference to an `OsRng` instance.
252	///
253	/// - Returns: A new instance of the private key.
254	pub fn new_random() -> Self {
255		let mut rng = OsRng;
256		Self::random(&mut rng)
257	}
258
259	/// Generates a new private key using the provided random number generator (RNG).
260	///
261	/// - Parameter rng: A mutable reference to an `OsRng` instance.
262	///
263	/// - Returns: A new instance of the private key.
264	pub fn random(rng: &mut OsRng) -> Self {
265		Self { inner: SecretKey::random(rng) }
266	}
267
268	/// Creates a private key from a byte slice.
269	///
270	/// This method attempts to construct a private key from a given byte array.
271	/// Returns an error if the byte slice does not represent a valid private key.
272	///
273	/// - Parameter bytes: A byte slice representing the private key.
274	///
275	/// - Returns: A `Result` with the private key or a `CryptoError`
276	pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
277		if bytes.len() != 32 {
278			return Err(CryptoError::InvalidPrivateKey);
279		}
280		SecretKey::from_slice(bytes)
281			.map(|inner| Self { inner })
282			.map_err(|_| CryptoError::InvalidPrivateKey)
283	}
284
285	/// Returns the raw byte representation of the private key.
286	///
287	/// - Returns: A 32-byte array representing the private key.
288	pub fn to_raw_bytes(&self) -> [u8; 32] {
289		self.inner
290			.clone()
291			.to_bytes()
292			.as_slice()
293			.try_into()
294			.expect("Private key should always be 32 bytes")
295	}
296
297	/// Converts the private key to its corresponding public key.
298	///
299	/// - Returns: The corresponding `Secp256r1PublicKey`.
300	pub fn to_public_key(&self) -> Secp256r1PublicKey {
301		Secp256r1PublicKey::from_public_key(self.inner.public_key())
302	}
303
304	pub fn erase(&mut self) {
305		// let mut bytes = self.inner.to_bytes();
306		// bytes.zeroize();
307		let bytes = [1u8; 32];
308		// Recreate the SecretKey from zeroized bytes
309		self.inner = SecretKey::from_bytes(&bytes.into())
310			.expect("Creating SecretKey from fixed bytes should never fail");
311	}
312
313	/// Signs a transaction with the private key.
314	///
315	/// This method signs the provided message (transaction) using the private key
316	/// and returns the signature.
317	///
318	/// - Parameter message: A byte slice representing the message to be signed.
319	///
320	/// - Returns: A `Result` with the `Secp256r1Signature` or a `CryptoError`.
321	pub fn sign_tx(&self, message: &[u8]) -> Result<Secp256r1Signature, CryptoError> {
322		let signing_key = SigningKey::from_slice(&self.inner.to_bytes().as_slice())
323			.map_err(|_| CryptoError::InvalidPrivateKey)?;
324		let (signature, _) =
325			signing_key.try_sign(message).map_err(|_| CryptoError::SigningError)?;
326
327		Ok(Secp256r1Signature { inner: signature })
328	}
329
330	/// Signs a prehashed message with the private key.
331	/// This method signs the provided prehashed message using the private key
332	/// and returns the signature.
333	/// - Parameter message: A byte slice representing the prehashed message to be signed.
334	/// - Returns: A `Result` with the `Secp256r1Signature` or a `CryptoError`.
335	/// - Note: The message should be prehashed using a secure hash function before calling this method.
336	///  The signature is generated using the ECDSA algorithm.
337	pub fn sign_prehash(&self, message: &[u8]) -> Result<Secp256r1Signature, CryptoError> {
338		let signing_key = SigningKey::from_slice(&self.inner.to_bytes().as_slice())
339			.map_err(|_| CryptoError::InvalidPrivateKey)?;
340		let (signature, _) =
341			signing_key.sign_prehash(message).map_err(|_| CryptoError::SigningError)?;
342
343		Ok(Secp256r1Signature { inner: signature })
344	}
345}
346
347impl Secp256r1Signature {
348	/// Creates a signature from the scalar values of `r` and `s`.
349	///
350	/// This method constructs a signature from the provided `r` and `s` values,
351	/// which are expected to be 32-byte arrays each.
352	///
353	/// - Parameters:
354	///     - r: The r scalar value as a 32-byte array.
355	///     - s: The s scalar value as a 32-byte array.
356	///
357	/// - Returns: A `Result<Secp256r1Signature, CryptoError>`. Returns error if the values
358	///   do not form a valid signature.
359	pub fn from_scalars(r: &[u8; 32], s: &[u8; 32]) -> Result<Self, CryptoError> {
360		let r_field: FieldBytes = (*r).into();
361		let s_field: FieldBytes = (*s).into();
362
363		let signature = Signature::from_scalars(r_field, s_field)
364			.map_err(|_| CryptoError::SignatureVerificationError)?;
365
366		Ok(Self { inner: signature })
367	}
368
369	/// Creates a signature from `U256` representations of `r` and `s`.
370	///
371	/// Converts the `U256` values of `r` and `s` into byte arrays and attempts
372	/// to create a signature. Assumes `r` and `s` are big-endian.
373	///
374	/// - Parameters:
375	///     - r: The r value as a `U256`.
376	///     - s: The s value as a `U256`.
377	///
378	/// - Returns: A `Secp256r1Signature`.
379	pub fn from_u256(r: U256, s: U256) -> Result<Self, CryptoError> {
380		let x = r.to_big_endian();
381		let y = s.to_big_endian();
382		Secp256r1Signature::from_scalars(&x, &y)
383	}
384
385	/// Constructs a `Secp256r1Signature` from a byte slice.
386	///
387	/// This method attempts to parse a 64-byte slice as an ECDSA signature.
388	/// The first 32 bytes represent `r` and the following 32 bytes represent `s`.
389	/// Returns an error if the slice is not 64 bytes long or does not represent
390	/// a valid signature.
391	///
392	/// - Parameter bytes: A 64-byte slice representing the signature.
393	///
394	/// - Returns: A `Result<Secp256r1Signature, CryptoError>`.
395	pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
396		if bytes.len() != 64 {
397			return Err(CryptoError::InvalidFormat("Invalid signature length".to_string()));
398		}
399
400		Signature::from_slice(bytes)
401			.map(|inner| Secp256r1Signature { inner })
402			.map_err(|_| CryptoError::InvalidFormat("Invalid signature format".to_string()))
403	}
404
405	/// Converts the signature into a 64-byte array.
406	///
407	/// This method returns a byte array representation of the signature,
408	/// with the first 32 bytes representing `r` and the last 32 bytes representing `s`.
409	///
410	/// - Returns: A 64-byte array representing the signature.
411	pub fn to_bytes(&self) -> [u8; 64] {
412		let r_bytes: FieldBytes = self.inner.r().into();
413		let s_bytes: FieldBytes = self.inner.s().into();
414
415		let mut bytes = [0u8; 64];
416		bytes[..32].copy_from_slice(r_bytes.as_ref());
417		bytes[32..].copy_from_slice(s_bytes.as_ref());
418
419		bytes
420	}
421}
422
423impl fmt::Display for Secp256r1PrivateKey {
424	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
425		write!(f, "Secp256r1PrivateKey: {}\n", hex::encode(self.inner.to_bytes().as_slice()))
426	}
427}
428
429impl fmt::Display for Secp256r1PublicKey {
430	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
431		write!(
432			f,
433			"Secp256r1PublicKey: {}\n",
434			hex::encode(self.inner.to_encoded_point(false).as_bytes())
435		)
436	}
437}
438
439impl fmt::Display for Secp256r1Signature {
440	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
441		write!(f, "Secp256r1Signature\n")?;
442		write!(f, "x: {}\n", hex::encode(&self.to_bytes()))
443	}
444}
445
446impl Serialize for Secp256r1PublicKey {
447	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
448	where
449		S: Serializer,
450	{
451		serializer.serialize_bytes(&self.get_encoded(true))
452	}
453}
454
455impl Serialize for Secp256r1PrivateKey {
456	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
457	where
458		S: Serializer,
459	{
460		serializer.serialize_bytes(&self.to_raw_bytes())
461	}
462}
463
464impl Serialize for Secp256r1Signature {
465	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
466	where
467		S: Serializer,
468	{
469		serializer.serialize_bytes(&self.to_bytes())
470	}
471}
472
473impl<'de> Deserialize<'de> for Secp256r1PublicKey {
474	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
475	where
476		D: Deserializer<'de>,
477	{
478		let bytes = <Vec<u8>>::deserialize(deserializer)?;
479		Secp256r1PublicKey::from_bytes(&bytes)
480			.map_err(|_| serde::de::Error::custom("Invalid public key"))
481	}
482}
483
484impl<'de> Deserialize<'de> for Secp256r1PrivateKey {
485	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
486	where
487		D: Deserializer<'de>,
488	{
489		let bytes = <Vec<u8>>::deserialize(deserializer)?;
490		Secp256r1PrivateKey::from_bytes(&bytes)
491			.map_err(|_| serde::de::Error::custom("Invalid private key"))
492	}
493}
494
495impl<'de> Deserialize<'de> for Secp256r1Signature {
496	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
497	where
498		D: Deserializer<'de>,
499	{
500		let bytes = <Vec<u8>>::deserialize(deserializer)?;
501		Secp256r1Signature::from_bytes(&bytes)
502			.map_err(|_| serde::de::Error::custom("Invalid signature"))
503	}
504}
505
506impl PartialEq for Secp256r1PublicKey {
507	fn eq(&self, other: &Secp256r1PublicKey) -> bool {
508		self.get_encoded(true) == other.get_encoded(true)
509	}
510}
511
512impl PartialOrd for Secp256r1PublicKey {
513	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
514		let self_bytes = self.get_encoded(true);
515		let other_bytes = other.get_encoded(true);
516		self_bytes.partial_cmp(&other_bytes)
517	}
518}
519
520impl Eq for Secp256r1PublicKey {}
521
522impl Ord for Secp256r1PublicKey {
523	fn cmp(&self, other: &Self) -> Ordering {
524		let self_bytes = self.get_encoded(true);
525		let other_bytes = other.get_encoded(true);
526		self_bytes.cmp(&other_bytes)
527	}
528}
529
530impl Hash for Secp256r1PublicKey {
531	fn hash<H: Hasher>(&self, state: &mut H) {
532		self.get_encoded(false).hash(state);
533	}
534}
535
536impl Hash for Secp256r1PrivateKey {
537	fn hash<H: Hasher>(&self, state: &mut H) {
538		self.to_raw_bytes().hash(state);
539	}
540}
541
542impl Hash for Secp256r1Signature {
543	fn hash<H: Hasher>(&self, state: &mut H) {
544		self.to_bytes().hash(state);
545	}
546}
547
548impl PartialEq for Secp256r1PrivateKey {
549	fn eq(&self, other: &Self) -> bool {
550		self.to_raw_bytes() == other.to_raw_bytes()
551	}
552}
553
554impl PartialEq for Secp256r1Signature {
555	fn eq(&self, other: &Self) -> bool {
556		self.to_bytes() == other.to_bytes()
557	}
558}
559
560impl From<Vec<u8>> for Secp256r1PublicKey {
561	fn from(bytes: Vec<u8>) -> Self {
562		Secp256r1PublicKey::from_bytes(&bytes).unwrap_or_else(|e| {
563			eprintln!("Warning: Failed to create public key from bytes: {}", e);
564			// Return a default/zero public key as fallback
565			// Using a known valid compressed public key (generator point)
566			Secp256r1PublicKey::from_encoded(
567				"036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
568			)
569			.expect("Generator point should always be valid")
570		})
571	}
572}
573
574pub trait PrivateKeyExtension
575where
576	Self: Sized,
577{
578	fn to_vec(&self) -> Vec<u8>;
579
580	fn from_slice(slice: &[u8]) -> Result<Self, CryptoError>;
581}
582
583impl PrivateKeyExtension for Secp256r1PrivateKey {
584	fn to_vec(&self) -> Vec<u8> {
585		self.to_raw_bytes().to_vec()
586	}
587
588	fn from_slice(slice: &[u8]) -> Result<Self, CryptoError> {
589		if slice.len() != 32 {
590			return Err(CryptoError::InvalidPublicKey);
591		}
592
593		let mut arr = [0u8; 32];
594		arr.copy_from_slice(slice);
595		Self::from_bytes(&arr).map_err(|_| CryptoError::InvalidPublicKey)
596	}
597}
598
599pub trait PublicKeyExtension
600where
601	Self: Sized,
602{
603	fn to_vec(&self) -> Vec<u8>;
604	fn from_slice(slice: &[u8]) -> Result<Self, CryptoError>;
605}
606
607impl PublicKeyExtension for Secp256r1PublicKey {
608	fn to_vec(&self) -> Vec<u8> {
609		self.get_encoded(true)
610	}
611
612	fn from_slice(slice: &[u8]) -> Result<Self, CryptoError> {
613		if slice.len() != 64 && slice.len() != 33 {
614			return Err(CryptoError::InvalidPublicKey);
615		}
616		Self::from_slice(slice).map_err(|_| CryptoError::InvalidPublicKey)
617	}
618}
619
620impl NeoSerializable for Secp256r1PublicKey {
621	type Error = CryptoError;
622
623	fn size(&self) -> usize {
624		NeoConstants::PUBLIC_KEY_SIZE_COMPRESSED as usize
625	}
626
627	fn encode(&self, writer: &mut Encoder) {
628		writer.write_bytes(&self.get_encoded(true));
629	}
630
631	fn decode(reader: &mut Decoder) -> Result<Self, Self::Error> {
632		let bytes = reader
633			.read_bytes(NeoConstants::PUBLIC_KEY_SIZE_COMPRESSED as usize)
634			.map_err(|_| CryptoError::InvalidPublicKey)?;
635		Secp256r1PublicKey::from_bytes(&bytes).map_err(|_| CryptoError::InvalidPublicKey)
636	}
637
638	fn to_array(&self) -> Vec<u8> {
639		//self.get_encoded(false)
640		let mut writer = Encoder::new();
641		self.encode(&mut writer);
642		writer.to_bytes()
643	}
644}
645
646#[cfg(test)]
647mod tests {
648	use hex_literal::hex;
649	use p256::EncodedPoint;
650
651	use crate::{
652		codec::{Decoder, NeoSerializable},
653		crypto::{
654			HashableForVec, Secp256r1PrivateKey, Secp256r1PublicKey, Secp256r1Signature, ToArray32,
655		},
656		neo_crypto::utils::{FromHexString, ToHexString},
657	};
658
659	const ENCODED_POINT: &str =
660		"03b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e136816";
661
662	#[test]
663	fn test_new_public_key_from_point() {
664		let expected_x = hex!("b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e136816");
665		let expected_y = hex!("5f4f7fb1c5862465543c06dd5a2aa414f6583f92a5cc3e1d4259df79bf6839c9");
666
667		let expected_ec_point =
668			EncodedPoint::from_affine_coordinates(&expected_x.into(), &expected_y.into(), false);
669
670		let enc_ec_point = "03b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e136816";
671		let enc_ec_point_bytes = hex::decode(enc_ec_point).unwrap();
672
673		let pub_key = Secp256r1PublicKey::from_encoded(&enc_ec_point).unwrap();
674
675		assert_eq!(pub_key.get_encoded_point(false), expected_ec_point);
676		assert_eq!(pub_key.get_encoded(true), enc_ec_point_bytes);
677		assert_eq!(pub_key.get_encoded_compressed_hex(), enc_ec_point);
678	}
679
680	#[test]
681	fn test_new_public_key_from_uncompressed_point() {
682		let uncompressed = "04b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e1368165f4f7fb1c5862465543c06dd5a2aa414f6583f92a5cc3e1d4259df79bf6839c9";
683		assert_eq!(
684			Secp256r1PublicKey::from_encoded(uncompressed)
685				.unwrap()
686				.get_encoded_compressed_hex(),
687			ENCODED_POINT
688		);
689	}
690
691	#[test]
692	fn test_new_public_key_from_string_with_invalid_size() {
693		let too_small = "03b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e1368"; //only 32 bits
694		assert!(Secp256r1PublicKey::from_encoded(too_small).is_none());
695	}
696
697	#[test]
698	fn test_new_public_key_from_point_with_hex_prefix() {
699		let prefixed = format!("0x{ENCODED_POINT}");
700		let a = Secp256r1PublicKey::from_encoded(&prefixed).unwrap();
701		assert_eq!(a.get_encoded_compressed_hex(), ENCODED_POINT);
702	}
703
704	#[test]
705	fn test_serialize_public_key() {
706		let enc_point = "03b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e136816";
707		let pub_key = Secp256r1PublicKey::from_encoded(&enc_point).unwrap();
708
709		assert_eq!(pub_key.to_array(), hex::decode(enc_point).unwrap());
710	}
711
712	#[test]
713	fn test_deserialize_public_key() {
714		let data = hex!("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296");
715		let mut decoder = Decoder::new(&data);
716		let public_key = Secp256r1PublicKey::decode(&mut decoder).unwrap();
717		assert_eq!(public_key.get_encoded(true).to_hex_string(), hex::encode(data));
718	}
719
720	#[test]
721	fn test_public_key_size() {
722		let mut key = Secp256r1PublicKey::from_encoded(
723			"036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
724		)
725		.unwrap();
726		assert_eq!(key.get_size(), 33);
727	}
728
729	#[test]
730	fn test_private_key_should_be_zero_after_erasing() {
731		let mut key = Secp256r1PrivateKey::from_bytes(&hex!(
732			"a7038726c5a127989d78593c423e3dad93b2d74db90a16c0a58468c9e6617a87"
733		))
734		.unwrap();
735		key.erase();
736		assert_eq!(key.to_raw_bytes(), [1u8; 32]);
737	}
738
739	#[test]
740	fn test_public_key_comparable() {
741		let encoded_key2 = "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296";
742		let encoded_key1_uncompressed = "04b4af8d061b6b320cce6c63bc4ec7894dce107bfc5f5ef5c68a93b4ad1e1368165f4f7fb1c5862465543c06dd5a2aa414f6583f92a5cc3e1d4259df79bf6839c9";
743
744		let key1 = Secp256r1PublicKey::from_encoded(ENCODED_POINT).unwrap();
745		let key2 = Secp256r1PublicKey::from_encoded(encoded_key2).unwrap();
746		let key1_uncompressed =
747			Secp256r1PublicKey::from_encoded(encoded_key1_uncompressed).unwrap();
748
749		assert!(key1 > key2);
750		assert!(key1 == key1_uncompressed);
751		assert!(!(key1 < key1_uncompressed));
752		assert!(!(key1 > key1_uncompressed));
753	}
754
755	#[test]
756	fn test_sign_message() {
757		let private_key_hex = "9117f4bf9be717c9a90994326897f4243503accd06712162267e77f18b49c3a3";
758		let public_key_hex = "0265bf906bf385fbf3f777832e55a87991bcfbe19b097fb7c5ca2e4025a4d5e5d6";
759		let test_message = "A test message";
760
761		let private_key =
762			Secp256r1PrivateKey::from_bytes(&hex::decode(private_key_hex).unwrap()).unwrap();
763		let public_key =
764			Secp256r1PublicKey::from_bytes(&hex::decode(public_key_hex).unwrap()).unwrap();
765
766		assert_eq!(public_key.clone(), private_key.clone().to_public_key());
767
768		// Hash the message
769		let hashed_msg = test_message.as_bytes().hash256();
770
771		// Sign the message
772		let signature: Secp256r1Signature = private_key.clone().sign_tx(&hashed_msg).unwrap();
773
774		// Verify that the signature is valid (this is the important test)
775		// We don't check specific r/s values since ECDSA signatures are non-deterministic
776		assert!(public_key.verify(&hashed_msg, &signature).is_ok());
777	}
778}