zeus_wallet/
secure_key.rs1use alloy_network::EthereumWallet;
2use alloy_primitives::{Address, hex};
3use alloy_signer_local::PrivateKeySigner;
4use k256::ecdsa::{SigningKey, VerifyingKey};
5use secure_types::{SecureArray, SecureString, Zeroize};
6
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Clone)]
10pub struct SecureKey {
11 address: Address,
12 data: SecureArray<u8, 32>,
13}
14
15impl SecureKey {
16 pub fn random() -> Self {
18 let signer = PrivateKeySigner::random();
19 Self::from(signer)
20 }
21
22 pub fn key(&self) -> SecureArray<u8, 32> {
24 self.data.clone()
25 }
26
27 pub fn key_string(&self) -> SecureString {
29 let signer = self.to_signer();
30 let mut key = signer.to_bytes();
31 let string = hex::encode(&key);
32 key.zeroize();
33 SecureString::from(string)
34 }
35
36 pub fn erase(&mut self) {
38 self.data.erase();
39 }
40
41 pub fn is_erased(&self) -> bool {
42 self.data.unlock(|slice| slice.iter().all(|byte| byte == &0))
43 }
44
45 pub fn address(&self) -> Address {
46 self.address
47 }
48
49 pub fn to_signer(&self) -> PrivateKeySigner {
55 self.data.unlock(|bytes| PrivateKeySigner::from_slice(bytes).unwrap())
56 }
57
58 pub fn to_signing_key(&self) -> SigningKey {
64 self.data.unlock(|bytes| SigningKey::from_slice(bytes).unwrap())
65 }
66
67 pub fn to_wallet(&self) -> EthereumWallet {
73 EthereumWallet::from(self.to_signer())
74 }
75
76 pub fn verifying_key(&self) -> VerifyingKey {
82 let key = self.to_signing_key();
83 *key.verifying_key()
84 }
85}
86
87impl From<SecureArray<u8, 32>> for SecureKey {
88 fn from(value: SecureArray<u8, 32>) -> Self {
93 let signer = value.unlock(|slice| PrivateKeySigner::from_slice(slice).unwrap());
94 let address = signer.address();
95 SecureKey {
96 address,
97 data: value,
98 }
99 }
100}
101
102impl From<PrivateKeySigner> for SecureKey {
103 fn from(value: PrivateKeySigner) -> Self {
104 let address = value.address();
105 let mut key_bytes = value.to_bytes();
106 let data = SecureArray::from_slice_mut(key_bytes.as_mut()).unwrap();
107
108 SecureKey { address, data }
109 }
110}
111
112impl From<SigningKey> for SecureKey {
113 fn from(value: SigningKey) -> Self {
114 let mut bytes = value.to_bytes();
115 let signer = PrivateKeySigner::from_slice(&bytes).unwrap();
116 let address = signer.address();
117 let data = SecureArray::from_slice_mut(bytes.as_mut()).unwrap();
118
119 SecureKey { address, data }
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use std::str::FromStr;
126
127 use super::*;
128
129 #[test]
130 fn test_create() {
131 let signer = PrivateKeySigner::random();
132 let secure_signer = SecureKey::from(signer.clone());
133 let signer2 = secure_signer.to_signer();
134 assert_eq!(signer.address(), signer2.address());
135 }
136
137 #[test]
138 fn sanity_check() {
139 let signer = PrivateKeySigner::random();
140 let secure_signer = SecureKey::from(signer.clone());
141 let signing_key = secure_signer.to_signing_key();
142 let secure_signer2 = SecureKey::from(signing_key);
143 assert_eq!(secure_signer.address(), secure_signer2.address());
144 }
145
146 #[test]
147 fn test_key_string() {
148 let signer = PrivateKeySigner::random();
149 let secure_signer = SecureKey::from(signer.clone());
150 let key_secure_string = secure_signer.key_string();
151
152 key_secure_string.unlock_str(|key_string| {
153 let new_signer = PrivateKeySigner::from_str(key_string).unwrap();
154 assert_eq!(signer.address(), new_signer.address());
155 });
156 }
157
158 #[test]
159 #[should_panic]
160 fn test_erase() {
161 let signer = PrivateKeySigner::random();
162 let mut secure_signer = SecureKey::from(signer.clone());
163 secure_signer.erase();
164 let _address = secure_signer.to_signer().address();
165 }
166
167 #[test]
168 fn test_is_erased() {
169 let signer = PrivateKeySigner::random();
170 let mut secure_signer = SecureKey::from(signer.clone());
171 assert!(!secure_signer.is_erased());
172 secure_signer.erase();
173 assert!(secure_signer.is_erased());
174 }
175
176 #[cfg(feature = "serde")]
177 #[test]
178 fn test_serde() {
179 let signer = PrivateKeySigner::random();
180 let secure_signer = SecureKey::from(signer.clone());
181
182 let json_string = serde_json::to_string(&secure_signer).unwrap();
183 let json_bytes = serde_json::to_vec(&secure_signer).unwrap();
184
185 let deserialized_string: SecureKey = serde_json::from_str(&json_string).unwrap();
186 let deserialized_bytes: SecureKey = serde_json::from_slice(&json_bytes).unwrap();
187
188 let signer2 = deserialized_string.to_signer();
189 let signer3 = deserialized_bytes.to_signer();
190
191 assert_eq!(signer.address(), signer2.address());
192 assert_eq!(signer.address(), signer3.address());
193 }
194}