ssh_key/public/
rsa.rs
1use crate::{
4 checked::CheckedSum, decode::Decode, encode::Encode, reader::Reader, writer::Writer, MPInt,
5 Result,
6};
7
8#[cfg(feature = "rsa")]
9use {
10 crate::{private::RsaKeypair, Error},
11 rsa::PublicKeyParts,
12};
13
14#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
18#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
19pub struct RsaPublicKey {
20 pub e: MPInt,
22
23 pub n: MPInt,
25}
26
27impl RsaPublicKey {
28 #[cfg(feature = "rsa")]
30 pub(crate) const MIN_KEY_SIZE: usize = RsaKeypair::MIN_KEY_SIZE;
31}
32
33impl Decode for RsaPublicKey {
34 fn decode(reader: &mut impl Reader) -> Result<Self> {
35 let e = MPInt::decode(reader)?;
36 let n = MPInt::decode(reader)?;
37 Ok(Self { e, n })
38 }
39}
40
41impl Encode for RsaPublicKey {
42 fn encoded_len(&self) -> Result<usize> {
43 [self.e.encoded_len()?, self.n.encoded_len()?].checked_sum()
44 }
45
46 fn encode(&self, writer: &mut impl Writer) -> Result<()> {
47 self.e.encode(writer)?;
48 self.n.encode(writer)
49 }
50}
51
52#[cfg(feature = "rsa")]
53#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
54impl TryFrom<RsaPublicKey> for rsa::RsaPublicKey {
55 type Error = Error;
56
57 fn try_from(key: RsaPublicKey) -> Result<rsa::RsaPublicKey> {
58 rsa::RsaPublicKey::try_from(&key)
59 }
60}
61
62#[cfg(feature = "rsa")]
63#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
64impl TryFrom<&RsaPublicKey> for rsa::RsaPublicKey {
65 type Error = Error;
66
67 fn try_from(key: &RsaPublicKey) -> Result<rsa::RsaPublicKey> {
68 let ret = rsa::RsaPublicKey::new(
69 rsa::BigUint::try_from(&key.n)?,
70 rsa::BigUint::try_from(&key.e)?,
71 )
72 .map_err(|_| Error::Crypto)?;
73
74 if ret.size().saturating_mul(8) >= RsaPublicKey::MIN_KEY_SIZE {
75 Ok(ret)
76 } else {
77 Err(Error::Crypto)
78 }
79 }
80}
81
82#[cfg(feature = "rsa")]
83#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
84impl TryFrom<rsa::RsaPublicKey> for RsaPublicKey {
85 type Error = Error;
86
87 fn try_from(key: rsa::RsaPublicKey) -> Result<RsaPublicKey> {
88 RsaPublicKey::try_from(&key)
89 }
90}
91
92#[cfg(feature = "rsa")]
93#[cfg_attr(docsrs, doc(cfg(feature = "rsa")))]
94impl TryFrom<&rsa::RsaPublicKey> for RsaPublicKey {
95 type Error = Error;
96
97 fn try_from(key: &rsa::RsaPublicKey) -> Result<RsaPublicKey> {
98 Ok(RsaPublicKey {
99 e: key.e().try_into()?,
100 n: key.n().try_into()?,
101 })
102 }
103}