Netdoc: better parsing for objects.
If I'm right this will let us simplify our code for parsing things from directory objects by a lot.
This commit is contained in:
parent
9b581588d6
commit
f6dd702316
|
@ -7,8 +7,16 @@
|
|||
|
||||
pub use b64impl::*;
|
||||
pub use curve25519impl::*;
|
||||
pub use rsa::*;
|
||||
pub use timeimpl::*;
|
||||
|
||||
pub trait FromBytes: Sized {
|
||||
fn from_bytes(b: &[u8]) -> crate::Result<Self>;
|
||||
fn from_vec(v: Vec<u8>) -> crate::Result<Self> {
|
||||
Self::from_bytes(&v[..])
|
||||
}
|
||||
}
|
||||
|
||||
mod b64impl {
|
||||
use crate::{Error, Pos, Result};
|
||||
|
||||
|
@ -89,3 +97,51 @@ mod timeimpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod rsa {
|
||||
use crate::{Error, Pos, Result};
|
||||
use std::ops::RangeBounds;
|
||||
use tor_llcrypto::pk::rsa::PublicKey;
|
||||
|
||||
/// An RSA public key, as parsed from a base64-encoded object.
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct RSAPublic(PublicKey);
|
||||
|
||||
impl From<RSAPublic> for PublicKey {
|
||||
fn from(k: RSAPublic) -> PublicKey {
|
||||
k.0
|
||||
}
|
||||
}
|
||||
impl super::FromBytes for RSAPublic {
|
||||
fn from_bytes(b: &[u8]) -> Result<Self> {
|
||||
let key = PublicKey::from_der(b).ok_or_else(|| {
|
||||
Error::BadObjectVal(Pos::None, "unable to decode RSA public key".into())
|
||||
})?;
|
||||
Ok(RSAPublic(key))
|
||||
}
|
||||
}
|
||||
impl RSAPublic {
|
||||
/// Give an error if the exponent of this key is not 'e'
|
||||
pub fn check_exponent(self, e: u32) -> Result<Self> {
|
||||
if self.0.exponent_is(e) {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(Error::BadObjectVal(
|
||||
Pos::None,
|
||||
"invalid RSA exponent".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
/// Give an error if the exponent of this key is not contained in 'bounds'
|
||||
pub fn check_len<B: RangeBounds<usize>>(self, bounds: B) -> Result<Self> {
|
||||
if bounds.contains(&self.0.bits()) {
|
||||
Ok(self)
|
||||
} else {
|
||||
Err(Error::BadObjectVal(Pos::None, "invalid RSA length".into()))
|
||||
}
|
||||
}
|
||||
pub fn check_len_eq(self, n: usize) -> Result<Self> {
|
||||
self.check_len(n..=n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//! directory document, and NetDocReader, which is used to break a
|
||||
//! string into Items.
|
||||
|
||||
use crate::argtype::FromBytes;
|
||||
use crate::{Error, Pos, Result};
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::str::FromStr;
|
||||
|
@ -321,6 +322,12 @@ impl<'a> Item<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
/// Try to decode the base64 contents of this item's associated object
|
||||
/// as a given type that implements FromBytes.
|
||||
pub fn parse_obj<V: FromBytes>(&self, want_tag: &str) -> Result<V> {
|
||||
let bytes = self.get_obj(want_tag)?;
|
||||
V::from_vec(bytes).map_err(|e| e.at_pos(Pos::at(self.object.unwrap().data)))
|
||||
}
|
||||
/// Return the position of this item.
|
||||
///
|
||||
/// This position won't be useful unless it is later contextualized
|
||||
|
|
Loading…
Reference in New Issue