laron_crypto/
public_key.rs1use crate::error::{Error, Result};
19use constant_time_eq::constant_time_eq;
20use k256::elliptic_curve::group::prime::PrimeCurveAffine;
21use k256::elliptic_curve::sec1::ToEncodedPoint;
22use k256::{AffinePoint, NonZeroScalar};
23
24const SIZE: usize = 65;
26
27#[derive(Debug, Clone, Copy)]
29pub struct PublicKey {
30 bytes: [u8; SIZE],
31}
32
33impl PartialEq for PublicKey {
34 fn eq(&self, other: &Self) -> bool {
35 constant_time_eq(&self.bytes, &other.bytes)
36 }
37}
38
39impl Eq for PublicKey {}
40
41impl PublicKey {
42 pub fn from_bytes(bytes: [u8; SIZE]) -> Self {
44 Self { bytes }
45 }
46
47 pub fn from_slice(slice: &[u8]) -> Result<Self> {
49 if slice.len() != SIZE {
50 Err(Error::LengthError(format!(
51 "PublicKey size must be {} bytes got {} bytes.",
52 SIZE,
53 slice.len()
54 )))
55 } else {
56 let mut new_bytes = [0u8; SIZE];
57 new_bytes.copy_from_slice(slice);
58 Ok(Self::from_bytes(new_bytes))
59 }
60 }
61
62 pub fn from_hex(hex: &str) -> Result<Self> {
64 if hex.len() != SIZE * 2 {
65 Err(Error::LengthError(format!(
66 "PublicKey hex must be {} characters got {} characters.",
67 SIZE * 2,
68 hex.len()
69 )))
70 } else {
71 let bytes = hex::decode(hex)?;
72 Self::from_slice(&bytes)
73 }
74 }
75
76 pub fn as_bytes(&self) -> [u8; SIZE] {
78 self.bytes
79 }
80
81 pub fn as_compressed_bytes(&self) -> [u8; 33] {
83 let pk = k256::PublicKey::from_sec1_bytes(&self.bytes).unwrap();
84 let bytes = pk.to_encoded_point(true);
85 bytes.as_bytes().try_into().unwrap()
86 }
87
88 pub fn as_slice(&self) -> &[u8] {
90 &self.bytes
91 }
92
93 pub fn as_hex(&self) -> String {
95 hex::encode(&self.bytes)
96 }
97
98 pub fn derive_child(&self, other: [u8; 32]) -> Result<Self> {
100 let current = k256::PublicKey::from_sec1_bytes(&self.bytes).unwrap();
101 let child_scalar = Option::<NonZeroScalar>::from(NonZeroScalar::from_repr(other.into()))
102 .ok_or(Error::InvalidPublicKey)?;
103 let child_point = current.to_projective() + (AffinePoint::generator() * *child_scalar);
104 let derived = k256::PublicKey::from_affine(child_point.into())
105 .map_err(|_| Error::InvalidPublicKey)?;
106 let bytes = derived.to_encoded_point(false);
107 Self::from_slice(bytes.as_bytes())
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use crate::PrivateKey;
114
115 use super::*;
116
117 #[test]
118 fn test_public_key() {
119 let key = PrivateKey::new();
120 let pk = key.public_key();
121 let pk_bytes = pk.as_bytes();
122 let pk_hex = pk.as_hex();
123 let pk_slice = pk.as_slice();
124 let pk_compressed = pk.as_compressed_bytes();
125 assert_eq!(pk_bytes.len(), SIZE);
126 assert_eq!(pk_hex.len(), SIZE * 2);
127 assert_eq!(pk_slice.len(), SIZE);
128 assert_eq!(pk_compressed.len(), 33);
129 assert_eq!(pk, PublicKey::from_slice(pk_slice).unwrap());
130 assert_eq!(pk, PublicKey::from_hex(&pk_hex).unwrap());
131 }
132}