opcua_crypto/aes/
rsa_private_key.rs1use std::{
7 self,
8 fmt::{self, Debug, Formatter},
9 result::Result,
10};
11
12use rsa::pkcs1;
13use rsa::pkcs1v15;
14use rsa::pkcs8;
15use rsa::pss;
16use rsa::signature::{RandomizedSigner, SignatureEncoding, Verifier};
17use rsa::{RsaPrivateKey, RsaPublicKey};
18
19use x509_cert::spki::SubjectPublicKeyInfoOwned;
20
21use opcua_types::{status_code::StatusCode, Error};
22
23use crate::policy::aes::AesAsymmetricEncryptionAlgorithm;
24
25#[derive(Debug)]
26pub struct PKeyError;
28
29impl fmt::Display for PKeyError {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 write!(f, "PKeyError")
32 }
33}
34
35impl std::error::Error for PKeyError {}
36
37impl From<pkcs8::Error> for PKeyError {
38 fn from(_err: pkcs8::Error) -> Self {
39 PKeyError
40 }
41}
42
43impl From<pkcs1::Error> for PKeyError {
44 fn from(_err: pkcs1::Error) -> Self {
45 PKeyError
46 }
47}
48
49impl From<rsa::Error> for PKeyError {
50 fn from(_err: rsa::Error) -> Self {
51 PKeyError
52 }
53}
54
55#[derive(Clone)]
58pub struct PKey<T> {
59 pub(crate) value: T,
60}
61
62pub type PublicKey = PKey<RsaPublicKey>;
64pub type PrivateKey = PKey<RsaPrivateKey>;
66
67impl<T> Debug for PKey<T> {
68 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
69 write!(f, "[pkey]")
72 }
73}
74
75pub trait KeySize {
77 fn bit_length(&self) -> usize {
79 self.size() * 8
80 }
81
82 fn size(&self) -> usize;
84
85 fn cipher_text_block_size(&self) -> usize {
87 self.size()
88 }
89}
90
91pub(crate) fn calculate_cipher_text_size<T: AesAsymmetricEncryptionAlgorithm>(
93 key_size: usize,
94 data_size: usize,
95) -> usize {
96 let plain_text_block_size = T::get_plaintext_block_size(key_size);
97 let block_count = if data_size.is_multiple_of(plain_text_block_size) {
98 data_size / plain_text_block_size
99 } else {
100 (data_size / plain_text_block_size) + 1
101 };
102
103 block_count * key_size
104}
105
106impl KeySize for PrivateKey {
107 fn size(&self) -> usize {
109 use rsa::traits::PublicKeyParts;
110 self.value.size()
111 }
112}
113
114impl PrivateKey {
115 pub fn new(bit_length: u32) -> Result<PrivateKey, rsa::Error> {
117 let mut rng = rand::thread_rng();
118
119 let key = RsaPrivateKey::new(&mut rng, bit_length as usize)?;
120 Ok(PKey { value: key })
121 }
122
123 pub fn read_pem_file(path: &std::path::Path) -> Result<PrivateKey, PKeyError> {
125 use pkcs8::DecodePrivateKey;
126 use rsa::pkcs1::DecodeRsaPrivateKey;
127
128 let r = RsaPrivateKey::read_pkcs8_pem_file(path);
129 match r {
130 Err(_) => {
131 let val = RsaPrivateKey::read_pkcs1_pem_file(path)?;
132 Ok(PKey { value: val })
133 }
134 Ok(val) => Ok(PKey { value: val }),
135 }
136 }
137
138 pub fn from_pem(bytes: &[u8]) -> Result<PrivateKey, PKeyError> {
140 use pkcs8::DecodePrivateKey;
141 use rsa::pkcs1::DecodeRsaPrivateKey;
142
143 let converted = std::str::from_utf8(bytes);
144 match converted {
145 Err(_) => Err(PKeyError),
146 Ok(pem) => {
147 let r = RsaPrivateKey::from_pkcs8_pem(pem);
148 match r {
149 Err(_) => {
150 let val = RsaPrivateKey::from_pkcs1_pem(pem)?;
151 Ok(PKey { value: val })
152 }
153 Ok(val) => Ok(PKey { value: val }),
154 }
155 }
156 }
157 }
158
159 pub fn to_der(&self) -> pkcs8::Result<pkcs8::SecretDocument> {
161 use pkcs8::EncodePrivateKey;
162
163 self.value.to_pkcs8_der()
164 }
165
166 pub fn public_key_to_info(&self) -> x509_cert::spki::Result<SubjectPublicKeyInfoOwned> {
168 use rsa::pkcs8::EncodePublicKey;
169 SubjectPublicKeyInfoOwned::try_from(
170 self.value
171 .to_public_key()
172 .to_public_key_der()
173 .unwrap()
174 .as_bytes(),
175 )
176 }
177
178 pub fn to_public_key(&self) -> PublicKey {
180 PublicKey {
181 value: self.value.to_public_key(),
182 }
183 }
184
185 pub fn sign_sha1(&self, data: &[u8], signature: &mut [u8]) -> Result<usize, Error> {
187 let mut rng = rand::thread_rng();
188 let signing_key = pkcs1v15::SigningKey::<sha1::Sha1>::new(self.value.clone());
189 match signing_key.try_sign_with_rng(&mut rng, data) {
190 Err(e) => Err(Error::new(StatusCode::BadUnexpectedError, e)),
191 Ok(signed) => {
192 let val = signed.to_vec();
193 signature.copy_from_slice(&val);
194 Ok(val.len())
195 }
196 }
197 }
198
199 pub fn sign_sha256(&self, data: &[u8], signature: &mut [u8]) -> Result<usize, Error> {
201 let mut rng = rand::thread_rng();
202 let signing_key = pkcs1v15::SigningKey::<sha2::Sha256>::new(self.value.clone());
203 match signing_key.try_sign_with_rng(&mut rng, data) {
204 Err(e) => Err(Error::new(StatusCode::BadUnexpectedError, e)),
205 Ok(signed) => {
206 let val = signed.to_vec();
207 signature.copy_from_slice(&val);
208 Ok(val.len())
209 }
210 }
211 }
212
213 pub fn sign_sha256_pss(&self, data: &[u8], signature: &mut [u8]) -> Result<usize, Error> {
215 let mut rng = rand::thread_rng();
216 let signing_key = pss::BlindedSigningKey::<sha2::Sha256>::new(self.value.clone());
217 match signing_key.try_sign_with_rng(&mut rng, data) {
218 Err(e) => Err(Error::new(StatusCode::BadUnexpectedError, e)),
219 Ok(signed) => {
220 let val = signed.to_vec();
221 signature.copy_from_slice(&val);
222 Ok(val.len())
223 }
224 }
225 }
226
227 pub(crate) fn private_decrypt<T: AesAsymmetricEncryptionAlgorithm>(
228 &self,
229 src: &[u8],
230 dst: &mut [u8],
231 ) -> Result<usize, PKeyError> {
232 let cipher_text_block_size = self.cipher_text_block_size();
233 let mut src_idx = 0;
235 let mut dst_idx = 0;
236
237 let src_len = src.len();
238 while src_idx < src_len {
239 let src_end_index = src_idx + cipher_text_block_size;
240
241 dst_idx += {
243 let src = &src[src_idx..src_end_index];
244 let dst = &mut dst[dst_idx..(dst_idx + cipher_text_block_size)];
245
246 let padding = T::get_padding();
247 let decrypted = self.value.decrypt(padding, src)?;
248
249 let size = decrypted.len();
250 if size == dst.len() {
251 dst.copy_from_slice(&decrypted);
252 } else {
253 dst[0..size].copy_from_slice(&decrypted);
254 }
255 size
256 };
257 src_idx = src_end_index;
258 }
259 Ok(dst_idx)
260 }
261}
262
263impl KeySize for PublicKey {
264 fn size(&self) -> usize {
266 use rsa::traits::PublicKeyParts;
267 self.value.size()
268 }
269}
270
271impl PublicKey {
272 pub fn verify_sha1(&self, data: &[u8], signature: &[u8]) -> Result<bool, Error> {
274 let verifying_key = pkcs1v15::VerifyingKey::<sha1::Sha1>::new(self.value.clone());
275 let r = pkcs1v15::Signature::try_from(signature);
276 match r {
277 Err(e) => Err(Error::new(StatusCode::BadUnexpectedError, e)),
278 Ok(val) => match verifying_key.verify(data, &val) {
279 Err(_) => Ok(false),
280 _ => Ok(true),
281 },
282 }
283 }
284
285 pub fn verify_sha256(&self, data: &[u8], signature: &[u8]) -> Result<bool, Error> {
287 let verifying_key = pkcs1v15::VerifyingKey::<sha2::Sha256>::new(self.value.clone());
288 let r = pkcs1v15::Signature::try_from(signature);
289 match r {
290 Err(e) => Err(Error::new(StatusCode::BadUnexpectedError, e)),
291 Ok(val) => match verifying_key.verify(data, &val) {
292 Err(_) => Ok(false),
293 _ => Ok(true),
294 },
295 }
296 }
297
298 pub fn verify_sha256_pss(&self, data: &[u8], signature: &[u8]) -> Result<bool, Error> {
300 let verifying_key = pss::VerifyingKey::<sha2::Sha256>::new(self.value.clone());
301 let r = pss::Signature::try_from(signature);
302 match r {
303 Err(e) => Err(Error::new(StatusCode::BadUnexpectedError, e)),
304 Ok(val) => match verifying_key.verify(data, &val) {
305 Err(_) => Ok(false),
306 _ => Ok(true),
307 },
308 }
309 }
310
311 pub(crate) fn public_encrypt<T: AesAsymmetricEncryptionAlgorithm>(
314 &self,
315 src: &[u8],
316 dst: &mut [u8],
317 ) -> Result<usize, PKeyError> {
318 let cipher_text_block_size = self.cipher_text_block_size();
319 let plain_text_block_size = T::get_plaintext_block_size(self.size());
320
321 let mut rng = rand::thread_rng();
322
323 let mut src_idx = 0;
324 let mut dst_idx = 0;
325
326 let src_len = src.len();
327 while src_idx < src_len {
328 let bytes_to_encrypt = if src_len < plain_text_block_size {
329 src_len
330 } else if (src_len - src_idx) < plain_text_block_size {
331 src_len - src_idx
332 } else {
333 plain_text_block_size
334 };
335
336 let src_end_index = src_idx + bytes_to_encrypt;
337
338 dst_idx += {
340 let src = &src[src_idx..src_end_index];
341
342 let padding = T::get_padding();
343 let encrypted = self.value.encrypt(&mut rng, padding, src)?;
344 dst[dst_idx..(dst_idx + cipher_text_block_size)].copy_from_slice(&encrypted);
345 encrypted.len()
346 };
347
348 src_idx = src_end_index;
350 }
351
352 Ok(dst_idx)
353 }
354}