1use crate::{Error, Mpint, Result};
4use core::hash::{Hash, Hasher};
5use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
6
7#[cfg(feature = "rsa")]
8use {
9 encoding::Uint,
10 rsa::{pkcs1v15, traits::PublicKeyParts},
11 sha2::{Digest, digest::const_oid::AssociatedOid},
12};
13
14#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
18pub struct RsaPublicKey {
19 e: Mpint,
21
22 n: Mpint,
24
25 bits: u32,
27}
28
29impl RsaPublicKey {
30 pub fn new(e: Mpint, n: Mpint) -> Result<Self> {
38 if !e.is_positive() {
39 return Err(Error::FormatEncoding);
40 }
41
42 let bits = match n.as_positive_bytes() {
43 Some(bytes) => bytes
44 .len()
45 .checked_mul(8)
46 .and_then(|bits| u32::try_from(bits).ok())
47 .ok_or(Error::FormatEncoding)?,
48 None => return Err(Error::FormatEncoding),
49 };
50
51 Ok(Self { e, n, bits })
52 }
53
54 #[must_use]
56 pub fn e(&self) -> &Mpint {
57 &self.e
58 }
59
60 #[must_use]
62 pub fn n(&self) -> &Mpint {
63 &self.n
64 }
65
66 #[must_use]
68 pub fn key_size(&self) -> u32 {
69 self.bits
70 }
71}
72
73impl Decode for RsaPublicKey {
74 type Error = Error;
75
76 fn decode(reader: &mut impl Reader) -> Result<Self> {
77 let e = Mpint::decode(reader)?;
78 let n = Mpint::decode(reader)?;
79 Self::new(e, n)
80 }
81}
82
83impl Encode for RsaPublicKey {
84 fn encoded_len(&self) -> encoding::Result<usize> {
85 [self.e.encoded_len()?, self.n.encoded_len()?].checked_sum()
86 }
87
88 fn encode(&self, writer: &mut impl Writer) -> encoding::Result<()> {
89 self.e.encode(writer)?;
90 self.n.encode(writer)
91 }
92}
93
94impl Hash for RsaPublicKey {
95 #[inline]
96 fn hash<H: Hasher>(&self, state: &mut H) {
97 self.e.as_bytes().hash(state);
98 self.n.as_bytes().hash(state);
99 }
100}
101
102#[cfg(feature = "rsa")]
103impl TryFrom<RsaPublicKey> for rsa::RsaPublicKey {
104 type Error = Error;
105
106 fn try_from(key: RsaPublicKey) -> Result<rsa::RsaPublicKey> {
107 rsa::RsaPublicKey::try_from(&key)
108 }
109}
110
111#[cfg(feature = "rsa")]
112impl TryFrom<&RsaPublicKey> for rsa::RsaPublicKey {
113 type Error = Error;
114
115 fn try_from(key: &RsaPublicKey) -> Result<rsa::RsaPublicKey> {
116 let n = Uint::try_from(&key.n)?;
117 let e = Uint::try_from(&key.e)?;
118 let ret = rsa::RsaPublicKey::new(n, e).map_err(|_| Error::Crypto)?;
119
120 Ok(ret)
121 }
122}
123
124#[cfg(feature = "rsa")]
125impl TryFrom<rsa::RsaPublicKey> for RsaPublicKey {
126 type Error = Error;
127
128 fn try_from(key: rsa::RsaPublicKey) -> Result<RsaPublicKey> {
129 RsaPublicKey::try_from(&key)
130 }
131}
132
133#[cfg(feature = "rsa")]
134impl TryFrom<&rsa::RsaPublicKey> for RsaPublicKey {
135 type Error = Error;
136
137 fn try_from(key: &rsa::RsaPublicKey) -> Result<RsaPublicKey> {
138 RsaPublicKey::new(key.e().into(), key.n().as_ref().into())
139 }
140}
141
142#[cfg(feature = "rsa")]
143impl<D> TryFrom<&RsaPublicKey> for pkcs1v15::VerifyingKey<D>
144where
145 D: Digest + AssociatedOid,
146{
147 type Error = Error;
148
149 fn try_from(key: &RsaPublicKey) -> Result<pkcs1v15::VerifyingKey<D>> {
150 Ok(pkcs1v15::VerifyingKey::new(key.try_into()?))
151 }
152}