phoenix_core/keys/
secret.rs1use dusk_bytes::{DeserializableSlice, Error, Serializable};
8use dusk_jubjub::{GENERATOR_EXTENDED, JubJubScalar};
9use ff::Field;
10use jubjub_schnorr::SecretKey as NoteSecretKey;
11use rand::{CryptoRng, RngCore};
12#[cfg(feature = "rkyv-impl")]
13use rkyv::{Archive, Deserialize, Serialize};
14use subtle::{Choice, ConstantTimeEq};
15use zeroize::Zeroize;
16
17use crate::StealthAddress;
18use crate::keys::hash;
19
20#[derive(Clone, Eq, Debug, Zeroize)]
50#[cfg_attr(
51 feature = "rkyv-impl",
52 derive(Archive, Serialize, Deserialize),
53 archive_attr(derive(bytecheck::CheckBytes))
54)]
55pub struct SecretKey {
56 a: JubJubScalar,
57 b: JubJubScalar,
58}
59
60impl SecretKey {
61 pub fn new(a: JubJubScalar, b: JubJubScalar) -> Self {
64 Self { a, b }
65 }
66
67 pub fn a(&self) -> &JubJubScalar {
69 &self.a
70 }
71
72 pub fn b(&self) -> &JubJubScalar {
74 &self.b
75 }
76
77 pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
80 let a = JubJubScalar::random(&mut *rng);
81 let b = JubJubScalar::random(&mut *rng);
82
83 SecretKey::new(a, b)
84 }
85
86 pub fn gen_note_sk(&self, stealth: &StealthAddress) -> NoteSecretKey {
89 let aR = stealth.R() * self.a;
90
91 NoteSecretKey::from(hash(&aR) + self.b)
92 }
93
94 pub fn owns(&self, stealth_address: &StealthAddress) -> bool {
96 let note_sk = self.gen_note_sk(stealth_address);
97
98 let note_pk = GENERATOR_EXTENDED * note_sk.as_ref();
99
100 stealth_address.note_pk().as_ref() == ¬e_pk
101 }
102}
103
104impl ConstantTimeEq for SecretKey {
105 fn ct_eq(&self, other: &Self) -> Choice {
106 self.a.ct_eq(&other.a) & self.b.ct_eq(&other.b)
107 }
108}
109
110impl PartialEq for SecretKey {
111 fn eq(&self, other: &Self) -> bool {
112 self.ct_eq(other).into()
113 }
114}
115
116impl Serializable<64> for SecretKey {
117 type Error = Error;
118
119 fn to_bytes(&self) -> [u8; 64] {
120 let mut bytes = [0u8; 64];
121 bytes[..32].copy_from_slice(&self.a.to_bytes());
122 bytes[32..].copy_from_slice(&self.b.to_bytes());
123 bytes
124 }
125
126 fn from_bytes(buf: &[u8; 64]) -> Result<Self, Self::Error> {
127 let a = JubJubScalar::from_slice(&buf[..32])?;
128 let b = JubJubScalar::from_slice(&buf[32..])?;
129
130 Ok(Self { a, b })
131 }
132}