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