netdoc: Parser for microdesc consensus documents

There's more to do here, and things to refactor, but this ought to
be enough to get a rudimentary client working.
This commit is contained in:
Nick Mathewson 2020-08-27 14:30:16 -04:00
parent e221146d9e
commit 6fabb54033
7 changed files with 1375 additions and 0 deletions

View File

@ -63,11 +63,16 @@ lazy_static! {
/// A single authority certificate
#[allow(dead_code)]
pub struct AuthCert {
// These fields are taken right from the certificate.
address: Option<net::SocketAddrV4>,
identity_key: rsa::PublicKey,
signing_key: rsa::PublicKey,
published: time::SystemTime,
expires: time::SystemTime,
// These fields are derived.
id_fingerprint: rsa::RSAIdentity,
sk_fingerprint: rsa::RSAIdentity,
}
impl AuthCert {
@ -93,6 +98,21 @@ impl AuthCert {
when < self.published || when > self.expires
}
/// Return the signing key certified by this certificate.
pub fn get_signing_key(&self) -> &rsa::PublicKey {
&self.signing_key
}
/// Return an RSAIdentity for this certificate's identity key.
pub fn get_id_fingerprint(&self) -> &rsa::RSAIdentity {
&self.id_fingerprint
}
/// Return an RSAIdentity for this certificate's signing key.
pub fn get_sk_fingerprint(&self) -> &rsa::RSAIdentity {
&self.sk_fingerprint
}
/// Parse an authority certificate from a reader.
fn take_from_reader(reader: &mut NetDocReader<'_, AuthCertKW>) -> Result<AuthCert> {
use AuthCertKW::*;
@ -199,12 +219,17 @@ impl AuthCert {
}
}
let id_fingerprint = identity_key.to_rsa_identity();
let sk_fingerprint = signing_key.to_rsa_identity();
Ok(AuthCert {
address,
identity_key,
signing_key,
published,
expires,
id_fingerprint,
sk_fingerprint,
})
}

View File

@ -210,6 +210,12 @@ pub enum Error {
/// There was an ipv4 or ipv6 policy entry that we couldn't parse.
#[error("invalid policy entry{0}: {1}")]
BadPolicy(Pos, #[source] PolicyError),
/// Versioned document with an unrecognized version.
#[error("unrecognied document version {0}")]
BadDocumentVersion(u32),
/// Unexpected document type
#[error("unexpected document type")]
BadDocumentType,
}
impl Error {
@ -240,6 +246,8 @@ impl Error {
BadSignature(p) => Some(p),
BadVersion(p) => Some(p),
BadPolicy(p, _) => Some(p),
BadDocumentVersion(_) => None,
BadDocumentType => None,
}
}

View File

@ -36,6 +36,7 @@ mod macros;
pub mod authcert;
pub mod family;
pub mod microdesc;
pub mod netstatus;
pub mod policy;
pub mod routerdesc;
pub mod version;

1104
tor-netdoc/src/netstatus.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -330,6 +330,11 @@ impl<'a, K: Keyword> Item<'a, K> {
pub fn get_arg(&self, idx: usize) -> Option<&'a str> {
self.args_as_vec().get(idx).copied()
}
/// Return the nth argument of this item, or an error if it isn't there.
pub fn required_arg(&self, idx: usize) -> Result<&'a str> {
self.get_arg(idx)
.ok_or_else(|| Error::MissingArgument(Pos::at(self.args)))
}
/// Try to parse the nth argument (if it exists) into some type
/// that supports FromStr.
///

138
tor-netdoc/testdata/authcerts2.txt vendored Normal file
View File

@ -0,0 +1,138 @@
dir-key-certificate-version 3
dir-address 127.0.0.1:7000
fingerprint 5A23BA701776C9C1AB1C06E734E92AB3D5350D64
dir-key-published 2020-08-07 12:40:25
dir-key-expires 2021-08-07 12:40:25
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBigKCAYEAtitks3CQo7QOYYhJmYJGOJoA9XOREzl38tl6zrGq4XtwOioTUivP
M51l483083x5DsBw6+Ec9LOkVSClETOIHDzjIzg78O4a6uEr7HemTI7JKEbIXUtj
bu1/JxOb7Bd8HrA/9Vw6hp3GJT7wqO33K/XhmRVzH2SMhmLP0cZT5MfaaE38QViI
eWrTFze+U1Z16RPWx8djaepCgLaVT2tP9WXKtk+6O0Kyjz1toF9wfZUb4jfEHNQ2
6Np5IaJcpsMaaovx2ClNOy23MadsLhBQxquCC1IFilMwKDDjVN9BIUd3eZJDBgyy
yY4PvO6fMsVxtK+7dlw2pWpdc2YSTGh9TY+UfWyPn+7oUD2AB/liJ/HOSqdXw5kl
YLeu2DwVUkv4ZieExUjyCmjmwkAdpEfMRE77hru+hbAV3E/vUj7571I1alMRZQU3
PItAQkfygL+0yI0Ysk4kVt0zxkFv19o1YD6yS+vBkY2oVGflBS6TVl2v/YsVDBEU
L6ifTkCQ8zIPAgMBAAE=
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAuMZaaW/p0CyTxWmr3SkBdrLz1uRiTZFadYNQmVcyeEfHw+siOO2Z
GZCpLW14AilxrGgIqacbj4p1bnP1Fqt48SW06TJpfg8LL5u9A0taBTrvl4d+y0PU
muk5/Y03QDUQ0Mqa5wFqXwq0gpFYNAF60fUcILU+RfC/eLF8p/8tMH6VqHbYJNvA
amHoi5b/cSX26y2AJG9NeRuljx9kGBKcQ3nyIUr5KtNmMAxtznnz6cxsXneCtfxo
H4Ubwy3NhSEfrjlSE4B/iASKalXgmQSSXR/PA+iBsG+zZ8+6/kKtxc5MQmnEQ3Qg
q6M1hfp9K89K/EzaxQ06PLvY1FylGqpc1wIDAQAB
-----END RSA PUBLIC KEY-----
dir-key-crosscert
-----BEGIN ID SIGNATURE-----
UrMAQ97L/Aoz0pY+IahRnlTYFdJ3jLM28WxRvZ3eP8ShCmDHYYN7fMwnstDjZZ8N
mGL8PuYP4mYfIRGjCBrMr5doLKtaOoyxnuuE81y08Yd8xWkIt9zelc5baGj1iJjn
1kxRCeClli0v05M31Z5zTNAfdMDD+yai4husa/0oEIMBJvjEAmeRcyjxfWIV8R0D
e+PR7+GAxprbJFGRL9bn27PlR7Lbm03jZIpBhCdTAeBxyGHyS8wgaXaIJCR7e3GH
uJytP7OvPoWLAggHSBp1LwsY++lLayJrTjm3/yoWv7BOXnXP0XHwDoPoXySS519p
lxq5rwk1RrSwa93+nwnEXw==
-----END ID SIGNATURE-----
dir-key-certification
-----BEGIN SIGNATURE-----
fp1nrLUFamnIg6rZnG/hMuM00SpBVTW6/XgEgMw9QIfE3lQxzR/hKF6iFcasYi2z
gg6r2JAvGevQxzajV8nDgKcLSnDurh6Q7OJw9p4v1ksXLJazHbLAhKi+Aa/daSmb
6Klp3XVDgVNhYzTleN26/El+Z1oEjbqRs72Vvlazem5lKaOZvm7jolgWQn5TiWZY
TQ9D7cP9TDAm7WBvYQ97CUnSDobVJyVBtCQrNb5vppTQw6+FON0U2h75Vl+T/Qhd
wugYKJ+UbZhwBCy0EOM23BU7QS6jbYW2bBjeo5I7/K32Cci8YZKuib9N/j3NPuFz
7jRAYSgiEd4uwktG4RP55EV7RVTO28/XeEvvlM/iVVYoqS+bMoCRkO8LqHvKB6+0
Wkei7KASZzIVe5YcgRHzts/oBt8w59DIaGUtEPQQ2BEIYtkl4N3mfR9VgW5HpTUI
2kPs1DjukQslB6Ilz6G+qOaZtJyOhdkWtwdR/fMcDWmTEifLZDbAdiLUpg/xc26p
-----END SIGNATURE-----
dir-key-certificate-version 3
dir-address 127.0.0.1:7002
fingerprint 7C47DCB4A90E2C2B7C7AD27BD641D038CF5D7EBE
dir-key-published 2020-08-07 12:40:26
dir-key-expires 2021-08-07 12:40:26
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBigKCAYEAyE1/XqjBgaNCSp36thnqlRzzt/4vEXXUIcutCkGAsI/An408vj+Z
tSo844vMMtSb8z1z0xDzApz2GPe7n5BTdPGjV1YQUd3Vr0z3z1j9EolV8NoXlUod
Mj9pSa2dB9Hpz1ZooAEX+egRXPXOp6kHb2QyUIVupKUo/kCRwyUcqV6M52oPZ0i4
o2uhhExXkExY1f7y6yee7QzLOxIgDhtWpkBhfMjRfa856ULXcRPwsQ99A1RclWTb
c1i6aU3NIt+AYthamu6G4jnYTrg4tPUyr7Gc4+j34rT/SwLS5waKZwZFObGNitK0
dLMMgPHfeJMW7wVN/scNDXCwZ19XzYEdat+SGP9jUaxPoabdOgzibfQINanw7pzm
G5bEmOuqWr1vYy3oRs1rIJJ18vy6yTF379sKdkB1gSau6svSIJfvUpnVA2pjvjL0
UGxXCCMozU+ctoe1PtXAEDFTE30vHo2pDe0pvJI+7bO09NAbTpIFfoxILqKRstJ7
PcU/6Ncbmfd7AgMBAAE=
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAy+3L8ISKlSQ7nOmHgi1rNSpSp00e4VrMcgXU8+kn0yjYZB6jOSMs
/LZDk14eX8jlvPsJg/SIl4c2OD+AYJtiyB1DZnZY/QbZ48faVwi9FkfCcZLkrD1i
PiiYmpM+DS+sh1oiBZX/wTSvx0MeEjyd9t8ZhH5R86k7QA7TW7Fe9rRrLshPSGFp
4ipj1fG+NuEG58kXeWSLwXJvNl4Hdezvvjii5la9b2S37/D6DZDfRLib35tXfA4T
y/zUK1pjzEQaAUeuIOgB+olX6bsOyL2eQORd5y5MtfF4x4FklPcz/e1l7gmahWGp
RpSUIRszrEbfxgCA8zCz/ta+jrrXq1lkpQIDAQAB
-----END RSA PUBLIC KEY-----
dir-key-crosscert
-----BEGIN ID SIGNATURE-----
HvUJXA95l45NFYuD5y5jSf4aFE0f3TlABjKK159WeSjDD/4Vn1GJQQjX6ske8MDh
x54GpTllhLmPLRq5GXn/DRCvxG9TGpyP3vL8pq2TWLBscCVxg4D9xj6OSYvbBKRw
QolqW8wfGKPj2OgCnTB3jzvnshP9rDq/ruEzlZfJTrb4pxQrPzOAlwaKEDCoO9zy
IW/gmVn1/vGNU/qhuGAKa4FGKUjvTg699MFE2SIF7gLo+oOGkFfL37WhHDlh7HPR
JiAHgTp6nHp+2+B/EHR5u94b3g66qPRNN6KxWcTAqcUxX9t0dKlsROZksr1268P6
PEN3+GtdwiA4n3reP+Wsxw==
-----END ID SIGNATURE-----
dir-key-certification
-----BEGIN SIGNATURE-----
FqKvXdB2bcwFYEWdQDW0eot/5cRTBnb8frAzoA/khWUSLhYIE55b/xtDg2OMWMhx
/yBiGuNGHT82+jKDh92RfxVKH8D32/r6p1SP1ot8POGWU/ke6/lABZkd5Aa5xSb7
Hcqik24bbnlvePtqze7UlvJQZN3ktYHUV2LTyw4ZbY1NEmMoPGE7FWe1iHSCiAvn
I8u3ePREY2gQ4ZzkcjuPzIMX4Th18OEQFTanNgJqmW5l4XDkXO4yAOaO21/7kdTg
iTqQnoWn8PfoVRvXVYvrgWKMyRUT/6R2zUnNWaP9z7JKv3SSZSXyMowbcyb5QFTX
KKhfO7fLMdGUs/yhXvqVgaQdguOcLfTUU7rV8aZjKsGiDPsFJKTBw9Xt5obGGJN4
4CLP+J9lSi/aZ2M4/qD5tkuE0kUNzeHuZuhze3MOObRZxLC5I3skwzTuflODVtTP
llMKUqZjbySFnSHEMvs+rhPOiUPNzXDl7/hQAVbWrzIyjjJ0WpoIUyHcIETWsv6Y
-----END SIGNATURE-----
dir-key-certificate-version 3
dir-address 127.0.0.1:7001
fingerprint 5696AB38CB3852AFA476A5C07B2D4788963D5567
dir-key-published 2020-08-07 12:40:25
dir-key-expires 2021-08-07 12:40:25
dir-identity-key
-----BEGIN RSA PUBLIC KEY-----
MIIBigKCAYEA5uDA8p4NhKPwOX/sMeMn6RtZLmNM2Ye4a1EPk2LQ7LYWQyeBZqsq
GzZnQANclC0YbGi7cw7GiGY6NKXZNWtaPxX5rCWOw8IhGjNo56/kSfHJX+Gvtzzp
dbxW/9JIYi8WyXQfMBhmfWtUrkdNIEyuW//H08haH+viCMePSv6zmPoc0xV//+XK
ycHe/hLQZMKHIhHLGz0k3fRtousy+3y/vQFjw2PVwMB7xXnbHFPc0b+jUU3QO2V6
jUAXVdIyHU+y1FzynUPo6C5d8mVQIlz/NcL1k0IKGUn1ItaQicYs28ooC+/I/lvV
yub7LHHN7HX2IBwKLf135DQvSwXBWBFYwaYWGKDyN6IOGxCncKp9Cplz+Dk8P93m
vTPYdpF0F0M1kP5dmakVqXyivJZMHGsQr2V0qGXr6I1wwu3SOdO0fmogWmEOmeT+
3L4elBnC9BjPhCfX7vnzksLp6BZe20Btiu1TqxA0SUTk3t2kOJulwDcgYAyUbKeJ
NSKK8YOMyhvrAgMBAAE=
-----END RSA PUBLIC KEY-----
dir-signing-key
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAld61NikA0aqQnT2rO6YRelSnWCZjC3axXlrRV5QP1vJrPOdRRS53
xHgkFEo8dX63X1bl67MBiZmgcP+cD/p9aFi9XGJyTU84wdBvmNU65LJ4sH0jKL1E
DBt9RiDFCh9MhxqniVBp91is7m5RKV34Cwyco3Ti54uLO0FNGAh49nvNyANO0FlQ
YFdM9yRQRciv20rWYO9M6brxK7LQMYVTg899yFnqa/vc+3USonKVLnmXeViNYyui
bekkmN6E9EtSujpsfVAwsMSZy73n0n/PTRfXa+58npNgNbxX6mgQ6i7Nhy9KyFP4
9BzKA9Q3CmeM/Z339awAtCtSaLoEb0Vh3QIDAQAB
-----END RSA PUBLIC KEY-----
dir-key-crosscert
-----BEGIN ID SIGNATURE-----
WKrcO0K/e8XWRhTD0fh7+fqTJvL3A296/Yad16SS6Bdz1yh/QihSpffdS3PBi+ka
WhHdXNYZJ68BPr4kNUC6xwlObeVlt0SVVpE2avqpfFtZL1pV6he2dNKZ5MMv6Ctm
7BOaavpLwcEyXs2H1XxH6wjQU719FCbvJvBESclAAIq3K3D5fmFg68RNWHHz3r3F
MyXnaR5bylKkgQHwwz5Q3HVjWUJ6S7Fz8KTfO1Q7rvfgHpXzYJqAyXivhaGnJmWQ
+zHVscRSI3NpGgqnzeqylXkZVqrHWNO5mkVSeMXt2hMYP61Zkm7KO6lqtOBON7Db
AKOs+q8j2T3XoR5VD9YtAQ==
-----END ID SIGNATURE-----
dir-key-certification
-----BEGIN SIGNATURE-----
fJEeVmr7caG8pfwO9XFeCGnWVgyqKSg90xpIfcWbPHrn5brAXEwJm/+dX7V9tazx
8y6i43ULt3MI+7Et2o46A3wYGA0a3OqpxAHdJjxeafJ9bDXRyVETh2MHsd0I337A
JhSuufKyGS+K2y20s2VYMPXkX2AFKpN1H0Stc7RdpssGyrmidZSXXzCgTitqn52g
Ms9iWjCU6Ra5AjMzp/D93CFZ0fYMhKot42ZXYJga8drQHdY06+5Fb7RSTpFs9vhf
t4XdeMef+N9ty/yaLNDmYiLJbKTTAarfkM2czXuuk3s+qwLN7+O4yGUNQz4tPJ8E
h7VALUNE80QNDLb4rXiIUE+EI3tCqo9mQ/tnCVVofM6sQyTFjTWyIIRBABnaODlO
meOIIEIR6ht2qSseZDe4dme7cg5/misTnIv7BNbErpYO5r9C2yHHFqSe8sivExCo
tEkNtxufKS2mn6Tkm7wcJfp1Temxk/INUtvPA6Dlf3wNTnwzuGfk7LWCQ9BPeFqv
-----END SIGNATURE-----

94
tor-netdoc/testdata/mdconsensus1.txt vendored Normal file
View File

@ -0,0 +1,94 @@
network-status-version 3 microdesc
vote-status consensus
consensus-method 28
valid-after 2020-08-07 12:42:40
fresh-until 2020-08-07 12:43:00
valid-until 2020-08-07 12:43:20
voting-delay 4 4
client-versions
server-versions
known-flags Authority Exit Fast Guard HSDir NoEdConsensus Running Stable V2Dir Valid
recommended-client-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 Microdesc=1-2 Relay=2
recommended-relay-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 Microdesc=1-2 Relay=2
required-client-protocols Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 Microdesc=1-2 Relay=2
required-relay-protocols Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=3-4 Microdesc=1 Relay=1-2
dir-source test001a 5696AB38CB3852AFA476A5C07B2D4788963D5567 127.0.0.1 127.0.0.1 7001 5001
contact auth1@test.test
vote-digest 32902D6653D3CBD4F709C1E788E7188A4514B469
dir-source test000a 5A23BA701776C9C1AB1C06E734E92AB3D5350D64 127.0.0.1 127.0.0.1 7000 5000
contact auth0@test.test
vote-digest BD69154582ADD167985FBA5B6BEF39A48FCF57E4
dir-source test002a 7C47DCB4A90E2C2B7C7AD27BD641D038CF5D7EBE 127.0.0.1 127.0.0.1 7002 5002
contact auth2@test.test
vote-digest 279F105B47E08D18391BC83CA862AD7E949BF16B
r test002a CjBXrykQQVeU2OpDAwnZrF9dUks 2020-08-07 12:40:41 127.0.0.1 5002 7002
a [::1]:5002
m c9q+CgRo9PemeBChjRHjZzG7HS7DY020WRAGCfOz9TU
s Authority Exit Fast Guard HSDir Running Stable V2Dir Valid
v Tor 0.3.5.11-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=0 Unmeasured=1
r test005r H5UFqVFxddqiKglhjS1a0IO534A 2020-08-07 12:40:27 127.0.0.1 5005 7005
a [::1]:5005
m 0PzCUr40s+j2dkL8QhiOQdO+mcOVM//TMuErDAV/V8A
s Exit Fast Guard HSDir Running Stable V2Dir Valid
v Tor 0.3.5.11-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=0 Unmeasured=1
r test001a RjuldU/uZiFnywOINM/Bo/Jl2XQ 2020-08-07 12:40:45 127.0.0.1 5001 7001
a [::1]:5001
m PyZmS8i3xBSMI92mxrIOzreeQVBjszo6gQM6sE4su7g
s Authority Exit Fast Guard HSDir Running Stable V2Dir Valid
v Tor 0.3.5.11-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=0 Unmeasured=1
r test003r WxID2gau2vvHyK7RhgmBHA/esoc 2020-08-07 12:40:27 127.0.0.1 5003 7003
a [::1]:5003
m rJ6+6FvO35iW0UQjPz/3V9B4zmVVAJjMzkXStJ9p0uE
s Exit Fast Guard HSDir Running Stable V2Dir Valid
v Tor 0.3.5.11-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=0 Unmeasured=1
r test004r odYQPeDLKV7J7EpWd8eUAoV4eSI 2020-08-07 12:40:27 127.0.0.1 5004 7004
a [::1]:5004
m r5XiWKH7oSILBJQl8sst/DGFJ5/TYc6cv0kf1yKHbuI
s Exit Fast Guard HSDir Running Stable V2Dir Valid
v Tor 0.3.5.11-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=0 Unmeasured=1
r test000a 3uQGx/h8HZl6EZOMag6DKbRwbKY 2020-08-07 12:40:41 127.0.0.1 5000 7000
a [::1]:5000
m l7OtNY+5akUSlwrElozHUCWC9LljbAYM5RTCWcA/Dr0
s Authority Exit Fast Guard HSDir Running Stable V2Dir Valid
v Tor 0.3.5.11-dev
pr Cons=1-2 Desc=1-2 DirCache=1-2 HSDir=1-2 HSIntro=3-4 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Relay=1-2
w Bandwidth=0 Unmeasured=1
directory-footer
bandwidth-weights Wbd=3333 Wbe=0 Wbg=0 Wbm=10000 Wdb=10000 Web=10000 Wed=3333 Wee=10000 Weg=3333 Wem=10000 Wgb=10000 Wgd=3333 Wgg=10000 Wgm=10000 Wmb=10000 Wmd=3333 Wme=0 Wmg=0 Wmm=10000
directory-signature sha256 5696AB38CB3852AFA476A5C07B2D4788963D5567 F6ED4AA64D83CAEDE34E19693A7FCF331AAE8A6A
-----BEGIN SIGNATURE-----
UUu8VroTU5iELNuh9sQAep3KIBmB8foN4Vil3pC6m+1G+iJFxCeMotXW5pQANLwu
WT5rX8wI3w5YT8MX2xADUN0PlG7YRBirBVeE6i/C42D5AN6ecqWLF78h1+CyktNb
g09SHub48vyjTJw+17HpVrhS+UzhF5s9C9yVpoRSr9vizxX2pV2o6e6XeIsQjOmd
6QjjA/8YHrXTshYr6baeZGh8ApeqLsuG+4YZMABkxVlRWo5Fmk4vJbd6MRRsLJwK
ePPyjBmSpRINJsBSTsgbz5YaIqtXVp+78F1VnlY1/4v9K+EUV90+y7HHsJKZnhIX
YooJRkMOJVWj37PDRVJ+1g==
-----END SIGNATURE-----
directory-signature sha256 5A23BA701776C9C1AB1C06E734E92AB3D5350D64 D08E965CC6DCB6CB6ED776DB43E616E93AF61177
-----BEGIN SIGNATURE-----
IiG1SB9sgKg3+NIhFFCojLXD8VuI4DKAKMaFM+sURDhxP9sVHLwoIRYcZM85DuUV
OaDs8aF+Y6Nfji7Kvqp7OYsRC3WgGVdmsexfwSmXgDuxnVbYVI/aG77jj8qIf5wh
wRTufBn7fFevTwz8HIGJyGHrebICzrtWKAvcxWV6vJLnfAKON957xGdutY3xjE5E
/NWZ3Ags/2MwaF1D7lsEjvPnRNWbZEz1GW6BcGVtbiszqWNlJp77ywSFIMbbIyOC
Vy6WxOrn/c5xhqoQxvzfSCCfWzDUOX9guebd1SApC249PsyhSIu1oSBfAN+GI/UN
qLHpjfj58pN8uknQU+aSIw==
-----END SIGNATURE-----
directory-signature sha256 7C47DCB4A90E2C2B7C7AD27BD641D038CF5D7EBE D3C013E0E6C82E246090D1C0798B75FCB7ACF120
-----BEGIN SIGNATURE-----
IIVukYddJQH8dsLmHGL8Nbdr9QRvDl0ngf79j3qCd9NnEnWKSf7b09kEdAAv57JZ
aVleTAiLev5Sa+CW4aXsrfCJp92t9S4Lm2YLYfuTwcn7DjDpLXJsl8VDO0iXF4Uc
yMk4os1FS5We/LVFs9+O9LfsN6y9OI+JlRT2EDmUi3Nm7Trjamjv658h3CdXZQ/L
7kvEAmZ8/CAR+cDUrsPwR2dWWrtmWhz0fiE3IvnwwCd/FzQyAvCW2TcySK50pvT2
wCI6+ZEYCk8+REjoHhEEhIaAOUeVd4XEe0EOtttivhoi+WNX5iNgl5F0SDRtX9jr
2iiMtFT1LaX/e8A7Ti681Q==
-----END SIGNATURE-----