phoenix_core/keys/
public.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7use crate::{keys::hash, SecretKey, StealthAddress, ViewKey};
8
9use dusk_jubjub::{JubJubAffine, JubJubExtended, JubJubScalar};
10
11#[cfg(feature = "rkyv-impl")]
12use rkyv::{Archive, Deserialize, Serialize};
13
14use dusk_bytes::{DeserializableSlice, Error, Serializable};
15use dusk_jubjub::GENERATOR_EXTENDED;
16use subtle::{Choice, ConstantTimeEq};
17
18/// Public pair of `a·G` and `b·G` defining a [`PublicKey`]
19#[derive(Debug, Clone, Copy, Eq)]
20#[cfg_attr(
21    feature = "rkyv-impl",
22    derive(Archive, Serialize, Deserialize),
23    archive_attr(derive(bytecheck::CheckBytes))
24)]
25pub struct PublicKey {
26    A: JubJubExtended,
27    B: JubJubExtended,
28}
29
30impl PublicKey {
31    /// This method is used to construct a new `PublicKey` from the given
32    /// public pair of `a·G` and `b·G`
33    pub fn new(A: JubJubExtended, B: JubJubExtended) -> Self {
34        Self { A, B }
35    }
36
37    /// Gets `A` (`a·G`)
38    pub fn A(&self) -> &JubJubExtended {
39        &self.A
40    }
41
42    /// Gets `B` (`b·G`)
43    pub fn B(&self) -> &JubJubExtended {
44        &self.B
45    }
46
47    /// Generates new `note_pk = H(A · r) · G + B` from a given `r`
48    pub fn gen_stealth_address(&self, r: &JubJubScalar) -> StealthAddress {
49        let G = GENERATOR_EXTENDED;
50        let R = G * r;
51
52        let rA = self.A * r;
53        let rA = hash(&rA);
54        let rA = G * rA;
55
56        let note_pk = rA + self.B;
57        let note_pk = note_pk.into();
58
59        StealthAddress { R, note_pk }
60    }
61}
62
63impl ConstantTimeEq for PublicKey {
64    fn ct_eq(&self, other: &Self) -> Choice {
65        self.A.ct_eq(&other.A) & self.B.ct_eq(&other.B)
66    }
67}
68
69impl PartialEq for PublicKey {
70    fn eq(&self, other: &Self) -> bool {
71        self.ct_eq(other).into()
72    }
73}
74
75impl From<&SecretKey> for PublicKey {
76    fn from(sk: &SecretKey) -> Self {
77        let A = GENERATOR_EXTENDED * sk.a();
78        let B = GENERATOR_EXTENDED * sk.b();
79
80        PublicKey::new(A, B)
81    }
82}
83
84impl From<ViewKey> for PublicKey {
85    fn from(vk: ViewKey) -> Self {
86        Self::from(&vk)
87    }
88}
89
90impl From<&ViewKey> for PublicKey {
91    fn from(vk: &ViewKey) -> Self {
92        let A = GENERATOR_EXTENDED * vk.a();
93
94        PublicKey::new(A, *vk.B())
95    }
96}
97
98impl Serializable<64> for PublicKey {
99    type Error = Error;
100
101    fn to_bytes(&self) -> [u8; Self::SIZE] {
102        let mut bytes = [0u8; Self::SIZE];
103        bytes[..32].copy_from_slice(&JubJubAffine::from(self.A).to_bytes());
104        bytes[32..].copy_from_slice(&JubJubAffine::from(self.B).to_bytes());
105        bytes
106    }
107
108    fn from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, Self::Error> {
109        let A = JubJubExtended::from(JubJubAffine::from_slice(&bytes[..32])?);
110        let B = JubJubExtended::from(JubJubAffine::from_slice(&bytes[32..])?);
111
112        Ok(Self { A, B })
113    }
114}