1use crate::{PublicKey, KEY_SIZE};
2use core::{
3 array::TryFromSliceError,
4 fmt::{self, Debug},
5};
6use curve25519_dalek::{
7 scalar::{clamp_integer, Scalar},
8 MontgomeryPoint,
9};
10use subtle::ConstantTimeEq;
11use zeroize::Zeroize;
12
13#[cfg(feature = "rand_core")]
14use aead::rand_core::CryptoRngCore;
15
16#[cfg(feature = "seal")]
17use {
18 crate::{get_seal_nonce, SalsaBox},
19 aead::Aead,
20 alloc::vec::Vec,
21};
22
23#[cfg(feature = "serde")]
24use serdect::serde::{de, ser, Deserialize, Serialize};
25
26#[derive(Clone)]
28pub struct SecretKey {
29 pub(crate) bytes: [u8; KEY_SIZE],
30 pub(crate) scalar: Scalar,
31}
32
33impl SecretKey {
34 #[inline]
36 pub fn from_bytes(bytes: [u8; KEY_SIZE]) -> Self {
37 let scalar = Scalar::from_bytes_mod_order(clamp_integer(bytes));
38 Self { bytes, scalar }
39 }
40
41 pub fn from_slice(slice: &[u8]) -> Result<Self, TryFromSliceError> {
46 slice.try_into().map(Self::from_bytes)
47 }
48
49 #[cfg(feature = "rand_core")]
51 pub fn generate(csprng: &mut impl CryptoRngCore) -> Self {
52 let mut bytes = [0u8; KEY_SIZE];
53 csprng.fill_bytes(&mut bytes);
54 bytes.into()
55 }
56
57 pub fn public_key(&self) -> PublicKey {
59 PublicKey(MontgomeryPoint::mul_base(&self.scalar))
60 }
61
62 pub fn to_bytes(&self) -> [u8; KEY_SIZE] {
85 self.bytes
86 }
87
88 pub fn to_scalar(&self) -> Scalar {
94 self.scalar
95 }
96
97 #[cfg(feature = "seal")]
103 pub fn unseal(&self, ciphertext: &[u8]) -> Result<Vec<u8>, aead::Error> {
104 if ciphertext.len() <= KEY_SIZE {
105 return Err(aead::Error);
106 }
107
108 let ephemeral_sk: [u8; KEY_SIZE] = ciphertext[..KEY_SIZE].try_into().unwrap();
109 let ephemeral_pk = ephemeral_sk.into();
110 let nonce = get_seal_nonce(&ephemeral_pk, &self.public_key());
111 let salsabox = SalsaBox::new(&ephemeral_pk, self);
112 salsabox.decrypt(&nonce, &ciphertext[KEY_SIZE..])
113 }
114}
115
116impl Debug for SecretKey {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.debug_struct("SecretKey").finish_non_exhaustive()
119 }
120}
121
122impl Drop for SecretKey {
123 fn drop(&mut self) {
124 self.scalar.zeroize();
125 }
126}
127
128impl Eq for SecretKey {}
129
130impl From<Scalar> for SecretKey {
131 fn from(scalar: Scalar) -> Self {
132 let bytes = scalar.to_bytes();
133 SecretKey { bytes, scalar }
134 }
135}
136
137impl From<[u8; KEY_SIZE]> for SecretKey {
138 fn from(bytes: [u8; KEY_SIZE]) -> SecretKey {
139 Self::from_bytes(bytes)
140 }
141}
142
143impl PartialEq for SecretKey {
144 fn eq(&self, other: &Self) -> bool {
145 self.scalar.ct_eq(&other.scalar).into()
146 }
147}
148
149impl TryFrom<&[u8]> for SecretKey {
150 type Error = TryFromSliceError;
151
152 fn try_from(slice: &[u8]) -> Result<Self, TryFromSliceError> {
153 Self::from_slice(slice)
154 }
155}
156
157#[cfg(feature = "serde")]
158impl Serialize for SecretKey {
159 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
160 where
161 S: ser::Serializer,
162 {
163 serdect::array::serialize_hex_upper_or_bin(&self.to_bytes(), serializer)
164 }
165}
166
167#[cfg(feature = "serde")]
168impl<'de> Deserialize<'de> for SecretKey {
169 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
170 where
171 D: de::Deserializer<'de>,
172 {
173 let mut bytes = [0u8; KEY_SIZE];
174 serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
175 Ok(SecretKey::from(bytes))
176 }
177}