laron_crypto/
private_key.rs1use constant_time_eq::constant_time_eq;
19use k256::ecdsa::VerifyingKey;
20use k256::NonZeroScalar;
21use rand::RngCore;
22
23use crate::{
24 error::{Error, Result},
25 PublicKey,
26};
27
28const SIZE: usize = 32;
30
31#[derive(Debug, Clone, Copy)]
33pub struct PrivateKey {
34 bytes: [u8; SIZE],
35}
36
37impl PartialEq for PrivateKey {
38 fn eq(&self, other: &Self) -> bool {
39 constant_time_eq(&self.bytes, &other.bytes)
40 }
41}
42
43impl Eq for PrivateKey {}
44
45impl PrivateKey {
46 pub fn new() -> Self {
48 let mut rng = rand::thread_rng();
49 let mut bytes = [0u8; SIZE];
50 rng.fill_bytes(&mut bytes);
51 Self { bytes }
52 }
53
54 pub fn from_bytes(bytes: [u8; SIZE]) -> Self {
56 Self { bytes }
57 }
58
59 pub fn from_slice(slice: &[u8]) -> Result<Self> {
61 if slice.len() != SIZE {
62 Err(Error::LengthError(
63 "PrivateKey size must be 32 bytes".to_string(),
64 ))
65 } else {
66 let mut new_bytes = [0u8; SIZE];
67 new_bytes.copy_from_slice(slice);
68 Ok(Self::from_bytes(new_bytes))
69 }
70 }
71
72 pub fn from_hex(hex: &str) -> Result<Self> {
74 if hex.len() != SIZE * 2 {
75 Err(Error::LengthError(
76 "PrivateKey hex must be 64 characters".to_string(),
77 ))
78 } else {
79 let bytes = hex::decode(hex)?;
80 Self::from_slice(&bytes)
81 }
82 }
83
84 pub fn as_bytes(&self) -> [u8; SIZE] {
86 self.bytes
87 }
88
89 pub fn as_slice(&self) -> &[u8] {
91 &self.bytes
92 }
93
94 pub fn as_hex(&self) -> String {
96 hex::encode(self.bytes)
97 }
98
99 pub fn public_key(&self) -> PublicKey {
101 let sk = k256::SecretKey::from_slice(&self.bytes).unwrap();
102 let pk = sk.public_key();
103 let vk: VerifyingKey = pk.into();
104 let bytes = vk.to_encoded_point(false);
105 PublicKey::from_slice(bytes.as_bytes()).unwrap()
106 }
107
108 pub fn derive_child(&self, other: [u8; 32]) -> Result<Self> {
110 let current = k256::SecretKey::from_slice(&self.bytes).unwrap();
111 let child_scalar = Option::<NonZeroScalar>::from(NonZeroScalar::from_repr(other.into()))
112 .ok_or(Error::PrivateKeyError)?;
113 let derived_scalar = current.to_nonzero_scalar().as_ref() + child_scalar.as_ref();
114 let derived: k256::SecretKey =
115 Option::<NonZeroScalar>::from(NonZeroScalar::new(derived_scalar))
116 .map(Into::into)
117 .ok_or(Error::PrivateKeyError)?;
118 let bytes = derived.to_bytes();
119 Self::from_slice(bytes.as_slice())
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_private_key() {
129 let key = PrivateKey::new();
130 let bytes = key.as_bytes();
131 assert_eq!(bytes.len(), 32);
132 let slice = key.as_slice();
133 assert_eq!(slice.len(), 32);
134 let hex = key.as_hex();
135 assert_eq!(hex.len(), 64);
136 let key2 = PrivateKey::from_hex(&hex).unwrap();
137 assert_eq!(key, key2);
138 }
139}