1use std::fmt;
2
3use cryptoxide::constant_time::CtEqual;
4use cryptoxide::ed25519;
5use cryptoxide::ed25519::signature_extended;
6use cryptoxide::hashing::sha2::Sha512;
7
8use std::convert::{TryFrom, TryInto};
9use std::error::Error;
10use std::hash::{Hash, Hasher};
11
12use super::derivation::{self, DerivationError, DerivationIndex, DerivationScheme};
13use super::hex;
14use super::securemem;
15use super::signature::Signature;
16
17pub const XPRV_SIZE: usize = 96;
19pub const EXTENDED_SECRET_KEY_SIZE: usize = 64;
20
21pub const XPUB_SIZE: usize = 64;
23pub const PUBLIC_KEY_SIZE: usize = 32;
24pub const CHAIN_CODE_SIZE: usize = 32;
25
26#[derive(Debug, PartialEq, Eq)]
32pub enum PrivateKeyError {
33 LengthInvalid(usize),
34 HighestBitsInvalid,
35 LowestBitsInvalid,
36}
37
38#[derive(Debug)]
40pub enum PublicKeyError {
41 LengthInvalid(usize),
42}
43
44pub struct XPrv([u8; XPRV_SIZE]);
49impl XPrv {
50 pub fn normalize_bytes_force3rd(mut bytes: [u8; XPRV_SIZE]) -> Self {
54 bytes[0] &= 0b1111_1000;
55 bytes[31] &= 0b0001_1111;
56 bytes[31] |= 0b0100_0000;
57
58 Self::from_bytes(bytes)
59 }
60
61 pub fn normalize_bytes_ed25519(mut bytes: [u8; XPRV_SIZE]) -> Self {
65 bytes[0] &= 0b1111_1000;
66 bytes[31] &= 0b0011_1111;
67 bytes[31] |= 0b0100_0000;
68
69 Self::from_bytes(bytes)
70 }
71
72 pub fn is_3rd_highest_bit_clear(&self) -> bool {
74 (self.0[31] & 0b0010_0000) == 0
75 }
76
77 pub fn clear_3rd_highest_bit(mut self) -> Self {
79 self.0[31] &= 0b1101_1111;
80 self
81 }
82
83 pub fn from_nonextended_force(bytes: &[u8; 32], chain_code: &[u8; CHAIN_CODE_SIZE]) -> Self {
87 let mut extended_out = [0u8; XPRV_SIZE];
88 extended_out[0..64].copy_from_slice(&Sha512::new().update(bytes).finalize());
89 extended_out[64..96].clone_from_slice(chain_code);
90 Self::normalize_bytes_force3rd(extended_out)
91 }
92
93 pub fn from_nonextended_noforce(
100 bytes: &[u8; 32],
101 chain_code: &[u8; CHAIN_CODE_SIZE],
102 ) -> Result<Self, ()> {
103 let mut extended_out = [0u8; XPRV_SIZE];
104 extended_out[0..64].copy_from_slice(&Sha512::new().update(bytes).finalize());
105 extended_out[64..96].clone_from_slice(chain_code);
106 let xprv = Self::normalize_bytes_ed25519(extended_out);
107 if xprv.is_3rd_highest_bit_clear() {
108 Ok(xprv)
109 } else {
110 Err(())
111 }
112 }
113
114 pub fn from_extended_and_chaincode(
118 sk: &[u8; EXTENDED_SECRET_KEY_SIZE],
119 chain_code: &[u8; CHAIN_CODE_SIZE],
120 ) -> Self {
121 let mut buf = [0u8; XPRV_SIZE];
122 buf[0..64].copy_from_slice(sk);
123 buf[64..96].copy_from_slice(chain_code);
124 Self::from_bytes(buf)
125 }
126
127 pub(crate) fn from_bytes(bytes: [u8; XPRV_SIZE]) -> Self {
132 XPrv(bytes)
133 }
134
135 pub fn from_bytes_verified(bytes: [u8; XPRV_SIZE]) -> Result<Self, PrivateKeyError> {
144 let scalar = &bytes[0..32];
145 let last = scalar[31];
146 let first = scalar[0];
147
148 if (last & 0b1100_0000) != 0b0100_0000 {
149 return Err(PrivateKeyError::HighestBitsInvalid);
150 }
151 if (first & 0b0000_0111) != 0b0000_0000 {
152 return Err(PrivateKeyError::LowestBitsInvalid);
153 }
154
155 Ok(XPrv(bytes))
156 }
157
158 pub fn from_slice_verified(bytes: &[u8]) -> Result<Self, PrivateKeyError> {
159 if bytes.len() != XPRV_SIZE {
160 return Err(PrivateKeyError::LengthInvalid(bytes.len()));
161 }
162
163 let mut buf = [0u8; XPRV_SIZE];
164 buf[..].clone_from_slice(bytes);
165 XPrv::from_bytes_verified(buf)
166 }
167
168 fn from_slice(bytes: &[u8]) -> Result<Self, PrivateKeyError> {
172 if bytes.len() != XPRV_SIZE {
173 return Err(PrivateKeyError::LengthInvalid(bytes.len()));
174 }
175 let mut buf = [0u8; XPRV_SIZE];
176 buf[..].clone_from_slice(bytes);
177 Ok(XPrv::from_bytes(buf))
178 }
179
180 pub fn public(&self) -> XPub {
183 let pk = mk_public_key(self.extended_secret_key_bytes());
184 let mut out = [0u8; XPUB_SIZE];
185 out[0..32].clone_from_slice(&pk);
186 out[32..64].clone_from_slice(&self.as_ref()[64..]);
187 XPub::from_bytes(out)
188 }
189
190 pub fn sign<T>(&self, message: &[u8]) -> Signature<T> {
193 let extended_key = <&[u8; 64]>::try_from(&self.0[0..64]).unwrap();
194 Signature::from_bytes(signature_extended(message, extended_key))
195 }
196
197 pub fn verify<T>(&self, message: &[u8], signature: &Signature<T>) -> bool {
200 let xpub = self.public();
201 xpub.verify(message, signature)
202 }
203
204 pub fn derive(&self, scheme: DerivationScheme, index: DerivationIndex) -> Self {
205 derivation::private(self, index, scheme)
206 }
207
208 pub fn get_extended_mut(&self, out: &mut [u8; EXTENDED_SECRET_KEY_SIZE]) {
209 out.clone_from_slice(self.extended_secret_key_slice())
210 }
211
212 pub fn extended_secret_key_bytes(&self) -> &[u8; 64] {
213 self.0[0..EXTENDED_SECRET_KEY_SIZE].try_into().unwrap()
214 }
215
216 pub fn extended_secret_key_slice(&self) -> &[u8] {
217 &self.0[0..EXTENDED_SECRET_KEY_SIZE]
218 }
219
220 pub fn chain_code(&self) -> &[u8; CHAIN_CODE_SIZE] {
221 self.0[64..96].try_into().unwrap()
222 }
223
224 pub fn chain_code_slice(&self) -> &[u8] {
225 &self.0[64..96]
226 }
227
228 pub fn extended_secret_key(&self) -> [u8; EXTENDED_SECRET_KEY_SIZE] {
229 let mut buf = [0u8; EXTENDED_SECRET_KEY_SIZE];
230 buf.copy_from_slice(self.extended_secret_key_slice());
231 buf
232 }
233}
234impl PartialEq for XPrv {
235 fn eq(&self, rhs: &XPrv) -> bool {
236 self.0.ct_eq(&rhs.0).into()
237 }
238}
239impl Eq for XPrv {}
240impl Clone for XPrv {
241 fn clone(&self) -> Self {
242 Self::from_slice(self.as_ref()).expect("it is already a safely constructed XPrv")
243 }
244}
245impl fmt::Debug for XPrv {
246 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247 write!(f, "{}", hex::encode(self.as_ref()))
248 }
249}
250impl fmt::Display for XPrv {
251 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
252 write!(f, "{}", hex::encode(self.as_ref()))
253 }
254}
255impl AsRef<[u8]> for XPrv {
256 fn as_ref(&self) -> &[u8] {
257 &self.0
258 }
259}
260impl From<XPrv> for [u8; XPRV_SIZE] {
261 fn from(v: XPrv) -> [u8; XPRV_SIZE] {
262 v.0
263 }
264}
265impl Drop for XPrv {
266 fn drop(&mut self) {
267 securemem::zero(&mut self.0);
268 }
269}
270
271#[derive(Clone, Copy)]
273pub struct XPub([u8; XPUB_SIZE]);
274impl XPub {
275 pub fn from_bytes(bytes: [u8; XPUB_SIZE]) -> Self {
277 XPub(bytes)
278 }
279
280 pub fn from_pk_and_chaincode(
282 pk: &[u8; PUBLIC_KEY_SIZE],
283 chain_code: &[u8; CHAIN_CODE_SIZE],
284 ) -> Self {
285 let mut buf = [0u8; XPUB_SIZE];
286 buf[0..32].copy_from_slice(pk);
287 buf[32..64].copy_from_slice(chain_code);
288 Self::from_bytes(buf)
289 }
290
291 pub fn from_slice(bytes: &[u8]) -> Result<Self, PublicKeyError> {
295 if bytes.len() != XPUB_SIZE {
296 return Err(PublicKeyError::LengthInvalid(bytes.len()));
297 }
298 let mut buf = [0u8; XPUB_SIZE];
299 buf[..].clone_from_slice(bytes);
300 Ok(Self::from_bytes(buf))
301 }
302
303 pub fn verify<T>(&self, message: &[u8], signature: &Signature<T>) -> bool {
306 ed25519::verify(
307 message,
308 &self.0[0..32].try_into().unwrap(),
309 signature.to_bytes(),
310 )
311 }
312
313 pub fn derive(
314 &self,
315 scheme: DerivationScheme,
316 index: DerivationIndex,
317 ) -> Result<Self, DerivationError> {
318 derivation::public(self, index, scheme)
319 }
320
321 pub fn get_without_chaincode(&self, out: &mut [u8; 32]) {
322 out.clone_from_slice(&self.0[0..32])
323 }
324
325 pub fn public_key_bytes(&self) -> &[u8; 32] {
326 <&[u8; 32]>::try_from(&self.0[0..32]).unwrap()
327 }
328
329 pub fn public_key_slice(&self) -> &[u8] {
330 &self.0[0..32]
331 }
332
333 pub fn chain_code_slice(&self) -> &[u8] {
334 &self.0[32..64]
335 }
336
337 pub fn public_key(&self) -> [u8; PUBLIC_KEY_SIZE] {
338 let mut buf = [0u8; PUBLIC_KEY_SIZE];
339 buf.copy_from_slice(self.public_key_slice());
340 buf
341 }
342
343 pub fn chain_code(&self) -> &[u8; CHAIN_CODE_SIZE] {
344 (&self.0[32..64]).try_into().unwrap()
345 }
346}
347impl PartialEq for XPub {
348 fn eq(&self, rhs: &XPub) -> bool {
349 self.0.ct_eq(&rhs.0).into()
350 }
351}
352impl Eq for XPub {}
353impl Hash for XPub {
354 fn hash<H: Hasher>(&self, state: &mut H) {
355 state.write(&self.0)
356 }
357}
358impl fmt::Display for XPub {
359 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
360 write!(f, "{}", hex::encode(self.as_ref()))
361 }
362}
363impl fmt::Debug for XPub {
364 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
365 write!(f, "{}", hex::encode(self.as_ref()))
366 }
367}
368impl AsRef<[u8]> for XPub {
369 fn as_ref(&self) -> &[u8] {
370 &self.0
371 }
372}
373impl From<XPub> for [u8; XPUB_SIZE] {
374 fn from(v: XPub) -> [u8; XPUB_SIZE] {
375 v.0
376 }
377}
378
379impl fmt::Display for PublicKeyError {
380 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
381 match self {
382 PublicKeyError::LengthInvalid(length) => write!(
383 f,
384 "Invalid public key length, expected {} but received {}",
385 XPUB_SIZE, length
386 ),
387 }
388 }
389}
390impl Error for PublicKeyError {}
391
392impl fmt::Display for PrivateKeyError {
393 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
394 match self {
395 PrivateKeyError::LengthInvalid(length) => write!(
396 f,
397 "Invalid private key length, expected {} but received {}",
398 XPRV_SIZE, length
399 ),
400 PrivateKeyError::HighestBitsInvalid => f.write_str("Invalid highest bits"),
401 PrivateKeyError::LowestBitsInvalid => f.write_str("Invalid lowest bits"),
402 }
403 }
404}
405impl Error for PrivateKeyError {}
406
407pub(crate) fn mk_xprv(out: &mut [u8; XPRV_SIZE], kl: &[u8], kr: &[u8], cc: &[u8]) {
408 assert!(kl.len() == 32);
409 assert!(kr.len() == 32);
410 assert!(cc.len() == CHAIN_CODE_SIZE);
411
412 out[0..32].clone_from_slice(kl);
413 out[32..64].clone_from_slice(kr);
414 out[64..96].clone_from_slice(cc);
415}
416
417pub(crate) fn mk_xpub(out: &mut [u8; XPUB_SIZE], pk: &[u8], cc: &[u8]) {
418 assert!(pk.len() == 32);
419 assert!(cc.len() == CHAIN_CODE_SIZE);
420
421 out[0..32].clone_from_slice(pk);
422 out[32..64].clone_from_slice(cc);
423}
424
425pub fn mk_public_key(extended_secret: &[u8; 64]) -> [u8; PUBLIC_KEY_SIZE] {
426 ed25519::extended_to_public(extended_secret)
427}