1use crate::{SecretKey, KEY_SIZE};
2use core::{array::TryFromSliceError, cmp::Ordering};
3use curve25519_dalek::MontgomeryPoint;
4
5#[cfg(feature = "seal")]
6use {
7 crate::{get_seal_nonce, SalsaBox, TAG_SIZE},
8 aead::{rand_core::CryptoRngCore, Aead},
9 alloc::vec::Vec,
10};
11
12#[cfg(feature = "serde")]
13use serdect::serde::{de, ser, Deserialize, Serialize};
14
15#[derive(Clone, Debug, Eq, PartialEq, Hash)]
19pub struct PublicKey(pub(crate) MontgomeryPoint);
20
21impl PublicKey {
22 pub fn from_bytes(bytes: [u8; KEY_SIZE]) -> Self {
24 PublicKey(MontgomeryPoint(bytes))
25 }
26
27 pub fn from_slice(slice: &[u8]) -> Result<Self, TryFromSliceError> {
32 slice.try_into().map(Self::from_bytes)
33 }
34
35 pub fn as_bytes(&self) -> &[u8; KEY_SIZE] {
37 self.0.as_bytes()
38 }
39
40 pub fn to_bytes(&self) -> [u8; KEY_SIZE] {
42 self.0.to_bytes()
43 }
44
45 #[cfg(feature = "seal")]
51 pub fn seal(
52 &self,
53 csprng: &mut impl CryptoRngCore,
54 plaintext: &[u8],
55 ) -> Result<Vec<u8>, aead::Error> {
56 let mut out = Vec::with_capacity(KEY_SIZE + TAG_SIZE + plaintext.len());
57 let ephemeral_sk = SecretKey::generate(csprng);
58 let ephemeral_pk = ephemeral_sk.public_key();
59 out.extend_from_slice(ephemeral_pk.as_bytes());
60
61 let nonce = get_seal_nonce(&ephemeral_pk, self);
62 let salsabox = SalsaBox::new(self, &ephemeral_sk);
63 let encrypted = salsabox.encrypt(&nonce, plaintext)?;
64 out.extend_from_slice(&encrypted);
65
66 Ok(out)
67 }
68}
69
70impl AsRef<[u8]> for PublicKey {
71 fn as_ref(&self) -> &[u8] {
72 self.as_bytes()
73 }
74}
75
76impl From<&SecretKey> for PublicKey {
77 fn from(secret_key: &SecretKey) -> PublicKey {
78 secret_key.public_key()
79 }
80}
81
82impl From<[u8; KEY_SIZE]> for PublicKey {
83 fn from(bytes: [u8; KEY_SIZE]) -> PublicKey {
84 Self::from_bytes(bytes)
85 }
86}
87
88impl TryFrom<&[u8]> for PublicKey {
89 type Error = TryFromSliceError;
90
91 fn try_from(slice: &[u8]) -> Result<Self, TryFromSliceError> {
92 Self::from_slice(slice)
93 }
94}
95
96impl PartialOrd for PublicKey {
97 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
98 Some(self.cmp(other))
99 }
100}
101
102impl Ord for PublicKey {
103 fn cmp(&self, other: &Self) -> Ordering {
104 self.as_bytes().cmp(other.as_bytes())
105 }
106}
107
108impl From<MontgomeryPoint> for PublicKey {
109 fn from(value: MontgomeryPoint) -> Self {
110 PublicKey(value)
111 }
112}
113
114#[cfg(feature = "serde")]
115impl Serialize for PublicKey {
116 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
117 where
118 S: ser::Serializer,
119 {
120 serdect::array::serialize_hex_upper_or_bin(self.as_bytes(), serializer)
121 }
122}
123
124#[cfg(feature = "serde")]
125impl<'de> Deserialize<'de> for PublicKey {
126 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
127 where
128 D: de::Deserializer<'de>,
129 {
130 let mut bytes = [0u8; KEY_SIZE];
131 serdect::array::deserialize_hex_or_bin(&mut bytes, deserializer)?;
132 Ok(PublicKey::from(bytes)) }
134}