authnz_common/types/keys/
signature.rs1use crate::{MResult, ServerError};
4
5#[derive(Clone)]
6pub struct SignKeypair {
8 inner: InnerSignKeypair,
9}
10
11#[non_exhaustive]
12#[derive(Clone)]
13enum InnerSignKeypair {
14 #[cfg(feature = "ed25519-utils")]
15 Ed25519(Box<ed25519_dalek::SigningKey>),
16 #[cfg(feature = "pqc-utils")]
17 Dilithium5(Box<authnz_pqc_dilithium::Keypair>),
18}
19
20impl InnerSignKeypair {
21 fn pack(&self) -> String {
22 use base64::{Engine as _, engine::general_purpose::STANDARD};
23
24 #[allow(unreachable_patterns)]
25 match self {
26 #[cfg(feature = "ed25519-utils")]
27 Self::Ed25519(keypair) => STANDARD.encode(keypair.to_keypair_bytes()),
28 #[cfg(feature = "pqc-utils")]
29 Self::Dilithium5(keypair) => format!(
30 "{}::||::{}",
31 STANDARD.encode(keypair.public),
32 STANDARD.encode(keypair.expose_secret())
33 ),
34 _ => unreachable!(),
35 }
36 }
37
38 #[allow(clippy::unwrap_used)]
39 fn unpack(cert: impl AsRef<str>) -> MResult<Self> {
40 use base64::{Engine as _, engine::general_purpose::STANDARD};
41
42 #[cfg(feature = "pqc-utils")]
43 if cert.as_ref().contains("::||::") {
44 let parts = cert.as_ref().split("::||::").collect::<Vec<_>>();
45 if parts.len() != 2 {
46 return Err(
47 ServerError::from_private_str("Certificate have no part divider, this is not the certificate!")
48 .with_private_str("Invalid certificate!")
49 .with_500(),
50 );
51 }
52
53 let public = parts.first().unwrap();
54 let public = STANDARD.decode(public).map_err(|e| {
55 ServerError::from_private(e)
56 .with_private_str("Can't decode public certificate part!")
57 .with_500()
58 })?;
59
60 let private = parts.last().unwrap();
61 let private = STANDARD.decode(private).map_err(|e| {
62 ServerError::from_private(e)
63 .with_private_str("Can't decode private certificate part!")
64 .with_500()
65 })?;
66
67 return Ok(Self::Dilithium5(Box::new(
68 authnz_pqc_dilithium::Keypair::restore(&public, &private).map_err(|e| {
69 ServerError::from_private(e)
70 .with_private_str("Can't restore Dilithium5 keypair!")
71 .with_500()
72 })?,
73 )));
74 }
75
76 #[cfg(feature = "ed25519-utils")]
77 {
78 let keypair = STANDARD.decode(cert.as_ref()).map_err(|e| {
79 ServerError::from_private(e)
80 .with_private_str("Can't decode Ed25519 certificate!")
81 .with_500()
82 })?;
83 return Ok(Self::Ed25519(Box::new(
84 ed25519_dalek::SigningKey::from_keypair_bytes(keypair.as_slice().try_into().map_err(|e| {
85 ServerError::from_private(e)
86 .with_private_str("Incorrect keypair length!")
87 .with_500()
88 })?)
89 .map_err(|e| {
90 ServerError::from_private(e)
91 .with_private_str("Incorrect Ed25519 certificate!")
92 .with_500()
93 })?,
94 )));
95 }
96
97 #[allow(unreachable_code)]
98 Err(ServerError::from_private_str("Enable at least one of `ed25519-utils`, `pqc-utils` to use SignKeypair!").with_500())
99 }
100
101 fn public(&self) -> Vec<u8> {
102 #[cfg(feature = "pqc-utils")]
103 #[allow(irrefutable_let_patterns)]
104 if let Self::Dilithium5(keypair) = &self {
105 return keypair.public.to_vec();
106 }
107
108 #[cfg(feature = "ed25519-utils")]
109 #[allow(irrefutable_let_patterns)]
110 if let Self::Ed25519(keypair) = &self {
111 return keypair.verifying_key().as_bytes().to_vec();
112 }
113
114 unreachable!()
115 }
116
117 fn private(&self) -> Vec<u8> {
118 #[cfg(feature = "pqc-utils")]
119 #[allow(irrefutable_let_patterns)]
120 if let Self::Dilithium5(keypair) = &self {
121 return keypair.expose_secret().to_vec();
122 }
123
124 #[cfg(feature = "ed25519-utils")]
125 #[allow(irrefutable_let_patterns)]
126 if let Self::Ed25519(keypair) = &self {
127 return keypair.as_bytes().to_vec();
128 }
129
130 unreachable!()
131 }
132}
133
134impl SignKeypair {
135 #[cfg(feature = "ed25519-utils")]
136 pub fn new_ed25519() -> MResult<Self> {
140 use rand::TryRngCore;
141
142 let mut csprng = rand::rngs::OsRng;
143
144 let mut secret = ed25519_dalek::SecretKey::default();
145 csprng.try_fill_bytes(&mut secret).map_err(|e| {
146 ServerError::from_private(e)
147 .with_private_str("Can't generate Ed25519 certificate!")
148 .with_500()
149 })?;
150
151 Ok(Self {
152 inner: InnerSignKeypair::Ed25519(Box::new(ed25519_dalek::SigningKey::from_bytes(&secret))),
153 })
154 }
155
156 #[cfg(feature = "pqc-utils")]
157 pub fn new_dilithium5() -> Self {
161 Self {
162 inner: InnerSignKeypair::Dilithium5(Box::new(authnz_pqc_dilithium::Keypair::generate())),
163 }
164 }
165
166 pub fn pack_keypair(&self) -> String {
168 self.inner.pack()
169 }
170
171 pub fn unpack_keypair(keypair: impl AsRef<str>) -> MResult<Self> {
173 Ok(Self {
174 inner: InnerSignKeypair::unpack(keypair)?,
175 })
176 }
177
178 pub fn sign_raw(&self, data: &[u8]) -> Vec<u8> {
180 #[allow(unreachable_patterns)]
181 match &self.inner {
182 #[cfg(feature = "ed25519-utils")]
183 InnerSignKeypair::Ed25519(keypair) => ed25519_dalek::Signer::sign(keypair.as_ref(), data).to_vec(),
184 #[cfg(feature = "pqc-utils")]
185 InnerSignKeypair::Dilithium5(keypair) => keypair.sign(data).to_vec(),
186 _ => unreachable!(),
187 }
188 }
189
190 pub fn verify_raw(data: &[u8], sign: &[u8], public_key: &[u8]) -> MResult<()> {
192 #[cfg(feature = "pqc-utils")]
193 if authnz_pqc_dilithium::verify(sign, data, public_key).is_ok() {
194 return Ok(());
195 }
196 #[cfg(feature = "ed25519-utils")]
197 if let Ok(pkey) = public_key.try_into()
198 && let Ok(vkey) = ed25519_dalek::VerifyingKey::from_bytes(pkey)
199 && let Ok(sign) = ed25519_dalek::Signature::from_slice(sign)
200 && ed25519_dalek::Verifier::verify(&vkey, data, &sign).is_ok()
201 {
202 return Ok(());
203 }
204
205 Err(ServerError::from_public("Invalid signature!").with_401())
206 }
207
208 pub fn sign<T: serde::Serialize>(&self, data: &T) -> MResult<Vec<u8>> {
210 rmp_serde::to_vec(data)
211 .map_err(|e| {
212 ServerError::from_private(e)
213 .with_private_str("Can't serialize data to sign!")
214 .with_500()
215 })
216 .map(|v| self.sign_raw(&v))
217 }
218
219 pub fn verify<T: serde::Serialize>(data: &T, sign: &[u8], public_key: &[u8]) -> MResult<()> {
221 let data = rmp_serde::to_vec(data).map_err(|e| {
222 ServerError::from_private(e)
223 .with_private_str("Can't serialize data to validate signature!")
224 .with_500()
225 })?;
226 Self::verify_raw(&data, sign, public_key)
227 }
228
229 pub fn verify_token(header: &[u8], payload: &[u8], sign: &[u8], public_key: &[u8]) -> MResult<()> {
231 let mut data = header.to_vec();
232 data.extend_from_slice(payload);
233 Self::verify_raw(&data, sign, public_key)
234 }
235
236 pub fn public(&self) -> Vec<u8> {
238 self.inner.public()
239 }
240
241 pub unsafe fn private(&self) -> Vec<u8> {
247 self.inner.private()
248 }
249}