Skip to main content

tor_llcrypto/pk/
rsa.rs

1//! Re-exporting RSA implementations.
2//!
3//! This module can currently handle public keys and signature
4//! verification used in the Tor directory protocol and
5//! similar places.
6//!
7//! Currently, that means validating PKCSv1 signatures, and encoding
8//! and decoding RSA public keys from DER.
9//!
10//! # Limitations:
11//!
12//! Currently missing are support for signing and RSA-OEAP.  In Tor,
13//! RSA signing is only needed for relays and authorities, and
14//! RSA-OAEP padding is only needed for the (obsolete) TAP protocol.
15//!
16//! This module should expose RustCrypto trait-based wrappers,
17//! but the [`rsa`] crate didn't support them as of initial writing.
18use rsa::pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey};
19use std::fmt;
20use subtle::{Choice, ConstantTimeEq};
21
22#[cfg(feature = "memquota-memcost")]
23use {derive_deftly::Deftly, tor_memquota_cost::derive_deftly_template_HasMemoryCost};
24
25use crate::util::{ct::CtByteArray, rng::RngCompat};
26
27pub use rsa::Error;
28
29/// How many bytes are in an "RSA ID"?  (This is a legacy tor
30/// concept, and refers to identifying a relay by a SHA1 digest
31/// of its RSA public identity key.)
32pub const RSA_ID_LEN: usize = 20;
33
34/// An identifier for an RSA key, based on SHA1 and DER.
35///
36/// These are used (for legacy purposes) all over the Tor protocol.
37///
38/// This object is an "identity" in the sense that it identifies (up to) one RSA
39/// key.  It may also represent the identity for a particular entity, such as a
40/// relay or a directory authority.
41///
42/// Note that for modern purposes, you should almost always identify a relay by
43/// its [`Ed25519Identity`](crate::pk::ed25519::Ed25519Identity) instead of by
44/// this kind of identity key.
45#[derive(Clone, Copy, Hash, Ord, PartialOrd, Eq, PartialEq)]
46#[cfg_attr(
47    feature = "memquota-memcost",
48    derive(Deftly),
49    derive_deftly(HasMemoryCost)
50)]
51pub struct RsaIdentity {
52    /// SHA1 digest of a DER encoded public key.
53    id: CtByteArray<RSA_ID_LEN>,
54}
55
56impl ConstantTimeEq for RsaIdentity {
57    fn ct_eq(&self, other: &Self) -> Choice {
58        self.id.ct_eq(&other.id)
59    }
60}
61
62impl fmt::Display for RsaIdentity {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(f, "${}", hex::encode(&self.id.as_ref()[..]))
65    }
66}
67impl fmt::Debug for RsaIdentity {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        write!(f, "RsaIdentity {{ {} }}", self)
70    }
71}
72
73impl safelog::Redactable for RsaIdentity {
74    /// Warning: This displays 16 bits of the RSA identity, which is
75    /// enough to narrow down a public relay by a great deal.
76    fn display_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        write!(f, "${}…", hex::encode(&self.id.as_ref()[..1]))
78    }
79
80    fn debug_redacted(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "RsaIdentity {{ {} }}", self.redacted())
82    }
83}
84
85impl serde::Serialize for RsaIdentity {
86    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
87    where
88        S: serde::Serializer,
89    {
90        if serializer.is_human_readable() {
91            serializer.serialize_str(&hex::encode(&self.id.as_ref()[..]))
92        } else {
93            serializer.serialize_bytes(&self.id.as_ref()[..])
94        }
95    }
96}
97
98impl<'de> serde::Deserialize<'de> for RsaIdentity {
99    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
100    where
101        D: serde::Deserializer<'de>,
102    {
103        if deserializer.is_human_readable() {
104            /// Deserialization helper
105            struct RsaIdentityVisitor;
106            impl<'de> serde::de::Visitor<'de> for RsaIdentityVisitor {
107                type Value = RsaIdentity;
108                fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> fmt::Result {
109                    fmt.write_str("hex-encoded RSA identity")
110                }
111                fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
112                where
113                    E: serde::de::Error,
114                {
115                    RsaIdentity::from_hex(s)
116                        .ok_or_else(|| E::custom("wrong encoding for RSA identity"))
117                }
118            }
119
120            deserializer.deserialize_str(RsaIdentityVisitor)
121        } else {
122            /// Deserialization helper
123            struct RsaIdentityVisitor;
124            impl<'de> serde::de::Visitor<'de> for RsaIdentityVisitor {
125                type Value = RsaIdentity;
126                fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> fmt::Result {
127                    fmt.write_str("RSA identity")
128                }
129                fn visit_bytes<E>(self, bytes: &[u8]) -> Result<Self::Value, E>
130                where
131                    E: serde::de::Error,
132                {
133                    RsaIdentity::from_bytes(bytes)
134                        .ok_or_else(|| E::custom("wrong length for RSA identity"))
135                }
136            }
137            deserializer.deserialize_bytes(RsaIdentityVisitor)
138        }
139    }
140}
141
142impl RsaIdentity {
143    /// Expose an RsaIdentity as a slice of bytes.
144    pub fn as_bytes(&self) -> &[u8] {
145        &self.id.as_ref()[..]
146    }
147
148    /// Expose an RsaIdentity as a byte array.
149    pub fn to_bytes(&self) -> [u8; 20] {
150        self.id.into()
151    }
152
153    /// Expose an RsaIdentity as an uppercase hexadecimal string.
154    pub fn as_hex_upper(&self) -> String {
155        hex::encode_upper(self.as_bytes())
156    }
157
158    /// Construct an RsaIdentity from a slice of bytes.
159    ///
160    /// Returns None if the input is not of the correct length.
161    ///
162    /// ```
163    /// use tor_llcrypto::pk::rsa::RsaIdentity;
164    ///
165    /// let bytes = b"xyzzyxyzzyxyzzyxyzzy";
166    /// let id = RsaIdentity::from_bytes(bytes);
167    /// assert_eq!(id.unwrap().as_bytes(), bytes);
168    ///
169    /// let truncated = b"xyzzy";
170    /// let id = RsaIdentity::from_bytes(truncated);
171    /// assert_eq!(id, None);
172    /// ```
173    pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
174        Some(RsaIdentity {
175            id: CtByteArray::from(<[u8; RSA_ID_LEN]>::try_from(bytes).ok()?),
176        })
177    }
178    /// Decode an `RsaIdentity` from a hexadecimal string.
179    ///
180    /// The string must have no spaces, or any extra characters.
181    pub fn from_hex(s: &str) -> Option<Self> {
182        let mut array = [0_u8; 20];
183        match hex::decode_to_slice(s, &mut array) {
184            Err(_) => None,
185            Ok(()) => Some(RsaIdentity::from(array)),
186        }
187    }
188
189    /// Return true if this `RsaIdentity` is composed entirely of zero-valued
190    /// bytes.
191    ///
192    /// Such all-zero values should not be used internally, since they are not
193    /// the ID of any valid key.  Instead, they are used in some places in the
194    /// Tor protocols.
195    pub fn is_zero(&self) -> bool {
196        // We do a constant-time comparison to avoid side-channels.
197        self.id.ct_eq(&[0; RSA_ID_LEN].into()).into()
198    }
199}
200
201impl From<[u8; 20]> for RsaIdentity {
202    fn from(id: [u8; 20]) -> RsaIdentity {
203        RsaIdentity { id: id.into() }
204    }
205}
206
207/// An RSA public key.
208///
209/// This implementation is a simple wrapper so that we can define new
210/// methods and traits on the type.
211#[derive(Clone, Debug, Eq, PartialEq)]
212pub struct PublicKey(rsa::RsaPublicKey);
213
214/// An RSA private key.
215///
216/// This is not so useful at present, since Arti currently only has
217/// client support, and Tor clients never actually need RSA private
218/// keys.
219pub struct KeyPair(rsa::RsaPrivateKey);
220
221impl KeyPair {
222    /// Generate a new random RSA keypair.
223    ///
224    /// This is hardcoded to generate a 1024-bit keypair, since this only exists to support the RSA
225    /// keys that we require for backwards compatibility (which are all 1024 bit), and we don't
226    /// anticipate adding anything new that uses RSA in the future.
227    pub fn generate<R: rand_core::RngCore + rand_core::CryptoRng>(
228        csprng: &mut R,
229    ) -> Result<Self, tor_error::Bug> {
230        // It's maybe a bit strange to return tor_error::Bug here, but I think it makes sense: The
231        // only way this call can fail is if we choose invalid values for the size and exponent,
232        // and those values are fixed. Ideally the `rsa` crate would give us a way to check that at
233        // compile time and thus have a infallible call, but they don't. I don't think it's
234        // reasonable to bubble up the underlying rsa::Error type, because I don't expect a caller
235        // to be able to figure out what to do with a error that we expect to never happen.
236        // Returning tor_error::Bug clearly indicates that the caller won't be able to do anything
237        // in particular about this error, without hiding a panic anywhere unexpected.
238        Ok(Self(
239            rsa::RsaPrivateKey::new(&mut RngCompat::new(csprng), 1024).map_err(|_| {
240                tor_error::internal!("Generating RSA key failed, despite fixed exponent and size")
241            })?,
242        ))
243    }
244    /// Return the public component of this key.
245    pub fn to_public_key(&self) -> PublicKey {
246        PublicKey(self.0.to_public_key())
247    }
248    /// Construct a PrivateKey from DER pkcs1 encoding.
249    pub fn from_der(der: &[u8]) -> Option<Self> {
250        Some(KeyPair(rsa::RsaPrivateKey::from_pkcs1_der(der).ok()?))
251    }
252    /// Return a reference to the underlying key type.
253    pub fn as_key(&self) -> &rsa::RsaPrivateKey {
254        &self.0
255    }
256    /// Sign a message using this keypair.
257    ///
258    /// This uses PKCS#1 v1.5 padding and takes a raw bytes, rather than doing the hashing
259    /// internally. This is because we use PKCS padding without specifying the hash OID, which is a
260    /// slightly unusual setup that is understandably not supported by the rsa crate.
261    pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rsa::Error> {
262        self.0.sign(rsa::Pkcs1v15Sign::new_unprefixed(), message)
263    }
264}
265impl PublicKey {
266    /// Return true iff the exponent for this key is the same
267    /// number as 'e'.
268    pub fn exponent_is(&self, e: u32) -> bool {
269        use rsa::traits::PublicKeyParts;
270        *self.0.e() == rsa::BigUint::new(vec![e])
271    }
272    /// Return the number of bits in the modulus for this key.
273    pub fn bits(&self) -> usize {
274        use rsa::traits::PublicKeyParts;
275        self.0.n().bits()
276    }
277    /// Try to check a signature (as used in Tor.)  The signed hash
278    /// should be in 'hashed', and the alleged signature in 'sig'.
279    ///
280    /// Tor uses RSA-PKCSv1 signatures, with hash algorithm OIDs
281    /// omitted.
282    pub fn verify(&self, hashed: &[u8], sig: &[u8]) -> Result<(), signature::Error> {
283        let padding = rsa::pkcs1v15::Pkcs1v15Sign::new_unprefixed();
284        self.0
285            .verify(padding, hashed, sig)
286            .map_err(|_| signature::Error::new())
287    }
288    /// Decode an alleged DER byte string into a PublicKey.
289    ///
290    /// Return None  if the DER string does not have a valid PublicKey.
291    ///
292    /// (This function expects an RsaPublicKey, as used by Tor.  It
293    /// does not expect or accept a PublicKeyInfo.)
294    pub fn from_der(der: &[u8]) -> Option<Self> {
295        Some(PublicKey(rsa::RsaPublicKey::from_pkcs1_der(der).ok()?))
296    }
297    /// Encode this public key into the DER format as used by Tor.
298    ///
299    /// The result is an RsaPublicKey, not a PublicKeyInfo.
300    pub fn to_der(&self) -> Vec<u8> {
301        use der_parser::ber::BerObject;
302        use rsa::traits::PublicKeyParts;
303
304        let mut n = self.0.n().to_bytes_be();
305        // prepend 0 if high bit is 1 to ensure correct signed encoding
306        if n[0] & 0b10000000 != 0 {
307            n.insert(0, 0_u8);
308        }
309        let n = BerObject::from_int_slice(&n);
310
311        let mut e = self.0.e().to_bytes_be();
312        // prepend 0 if high bit is 1 to ensure correct signed encoding
313        if e[0] & 0b10000000 != 0 {
314            e.insert(0, 0_u8);
315        }
316        let e = BerObject::from_int_slice(&e);
317
318        let asn1 = BerObject::from_seq(vec![n, e]);
319        asn1.to_vec().expect("RSA key not encodable as DER")
320    }
321
322    /// Compute the RsaIdentity for this public key.
323    pub fn to_rsa_identity(&self) -> RsaIdentity {
324        use crate::d::Sha1;
325        use digest::Digest;
326        let id: [u8; RSA_ID_LEN] = Sha1::digest(self.to_der()).into();
327        RsaIdentity { id: id.into() }
328    }
329
330    /// Return a reference to the underlying key type.
331    pub fn as_key(&self) -> &rsa::RsaPublicKey {
332        &self.0
333    }
334}
335
336impl<'a> From<&'a KeyPair> for PublicKey {
337    fn from(value: &'a KeyPair) -> Self {
338        PublicKey(value.to_public_key().0)
339    }
340}
341
342impl From<rsa::RsaPrivateKey> for KeyPair {
343    fn from(value: rsa::RsaPrivateKey) -> Self {
344        Self(value)
345    }
346}
347
348impl From<rsa::RsaPublicKey> for PublicKey {
349    fn from(value: rsa::RsaPublicKey) -> Self {
350        Self(value)
351    }
352}
353
354/// An RSA signature plus all the information needed to validate it.
355pub struct ValidatableRsaSignature {
356    /// The key that allegedly signed this signature
357    key: PublicKey,
358    /// The signature in question
359    sig: Vec<u8>,
360    /// The value we expect to find that the signature is a signature of.
361    expected_hash: Vec<u8>,
362}
363
364impl ValidatableRsaSignature {
365    /// Construct a new ValidatableRsaSignature.
366    pub fn new(key: &PublicKey, sig: &[u8], expected_hash: &[u8]) -> Self {
367        ValidatableRsaSignature {
368            key: key.clone(),
369            sig: sig.into(),
370            expected_hash: expected_hash.into(),
371        }
372    }
373}
374
375impl super::ValidatableSignature for ValidatableRsaSignature {
376    fn is_valid(&self) -> bool {
377        self.key
378            .verify(&self.expected_hash[..], &self.sig[..])
379            .is_ok()
380    }
381}