Skip to main content

sequoia_wot/
lib.rs

1//! A web of trust engine.
2//!
3//! # Introduction
4//!
5//! The [web of trust] is a decentralized trust model popularized by
6//! PGP.  It is [a superset] of [X.509], which is a hierarchical trust
7//! model, and is the most popular trust model on the public internet
8//! today.  As used on the public internet, however, X.509 relies on a
9//! handful of global [certification authorities] (CAs) who often
10//! [undermine its security].
11//!
12//!   [web of trust]: https://en.wikipedia.org/wiki/Web_of_trust
13//!   [a superset]: https://www.oreilly.com/library/view/beautiful-security/9780596801786/ch07.html
14//!   [X.509]: https://de.wikipedia.org/wiki/X.509
15//!   [certification authorities]: https://en.wikipedia.org/wiki/Certificate_authority
16//!   [undermine its security]: https://sslmate.com/resources/certificate_authority_failures
17//!
18//! The web of trust is more nuanced than X.509.  A user can partially
19//! trust a CA thereby preventing a single bad actor from compromising
20//! their security.  And those who have stronger security requirements
21//! can use the web of trust in a completely decentralized manner.
22//!
23//! Today, the tooling around the web of trust is primitive at best.
24//! Many people interpret this lack of good tooling as a sign that the
25//! web of trust is intrinsically difficult to use.  We disagree and
26//! think that efforts like our [OpenPGP CA] project provide evidence
27//! that this is not the case.
28//!
29//!   [OpenPGP CA]: https://openpgp-ca.org/
30//!
31//! # Web of Trust
32//!
33//! A web of trust is a network where the nodes are certificates,
34//! which are also called public keys, and the edges are
35//! certifications.  In OpenPGP's web of trust, edges may include
36//! non-local constraints.  For instance, the trust depth parameter
37//! determines whether the edges of subsequent nodes should be
38//! followed.  This means that many graph algorithms cannot be used
39//! without modification.
40//!
41//! This crate implements a web of trust engine.  It is designed
42//! around [OpenPGP]'s authentication concepts, but it does not
43//! require OpenPGP data structures and, as such, can be used in other
44//! contexts.
45//!
46//!   [OpenPGP]: https://datatracker.ietf.org/doc/html/rfc4880
47//!
48//! We model a web of trust using the [`Network`] data structure.  As
49//! shown in the [examples below], a `Network` can be created either
50//! directly from OpenPGP data structures ([`Network::from_certs`]) or
51//! it can be created manually ([`Network::new`]).  The latter is
52//! useful when the web of trust has been cached.  It can also be used
53//! to build a web of trust from non-OpenPGP data.
54//!
55//! [examples below]: #examples
56//!
57//! To authenticate a binding, you instantiate a [`Network`] object.
58//! You then call [`Network::authenticate`] to authenticate the
59//! binding.  The method returns the degree to which a binding (a
60//! fingerprint and a User ID) can be considered authentic.  Because
61//! authentication is not binary in the web of trust, and because
62//! multiple paths can be combined to increase confidence, this
63//! function returns a set of paths using the [`Paths`] data
64//! structure.
65//!
66//! By using a variant of [Dijkstra's algorithm] to authenticate a
67//! binding, authentication is fast even for large, highly connected
68//! web of trusts.  Specifically, its run time is `O((|V| + |E|) *
69//! log(|V|))` where `V` are the vertices or certificates, and `E` are
70//! the edges or certifications.
71//!
72//!   [Dijkstra's algorithm]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
73//!
74//! OpenPGP defines several authentication mechanisms, but it does not
75//! define how they should be used to authenticate a binding.
76//! Although both PGP and GnuPG implement a web of trust, neither
77//! documents their exact semantics.  This engine treats the network
78//! as a [flow network], which is similar, but not identical, to how
79//! PGP 7 and later work.
80//!
81//!  [flow network]: https://en.wikipedia.org/wiki/Flow_network
82//!
83//! ## OpenPGP's Authentication Mechanisms
84//!
85//! OpenPGP provides four simple, yet powerful and flexible mechanisms
86//! to facilitate authentication.  These are [third-party
87//! certifications], a [trust amount] parameter, a [trust depth]
88//! parameter, and a [regular expression] parameter.
89//!
90//!   [third-party certifications]: https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.1
91//!   [trust amount]: https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.3.13
92//!   [trust depth]: https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.3.13
93//!   [regular expression]: https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.3.14
94//!
95//! A third-party certification is a machine-readable artifact that
96//! says that the issuer believes that a binding between a User ID and
97//! a certificate is correct.  OpenPGP distinguishes four different
98//! types of third-party certifications ([signature types] 0x10 through
99//! 0x13).  This engine treats all of these different signature types
100//! identically.  In common practice, a persona certification
101//! (signature type 0x11) is often treated as an invalid certification.
102//! This engine ignores this distinction.
103//!
104//!   [signature types]: https://datatracker.ietf.org/doc/html/rfc4880#section-5.2.1
105//!
106//! The [trust amount] parameter is the degree to which the issuer of
107//! a certification is convinced that the binding is correct.  This
108//! can vary from 0 to 255.  Values that are 120 or larger mean that
109//! the issuer is fully convinced.  Traditionally, an issuer uses 60
110//! to indicate that they are partially (aka marginally) convinced,
111//! however, any value between 1 and 119 can be used.
112//!
113//! This web of trust implementation interprets the trust amount as an
114//! amount of evidence.  It assumes that evidence is independent and
115//! can be combined linearly.  That is, if we have two paths that
116//! don't share any edges, say a trust root partially trusts two
117//! [certification authorities] (CAs) and they both certify a binding,
118//! then the two paths can be added together.
119//!
120//!   [certification authorities]: https://en.wikipedia.org/wiki/Certificate_authority
121//!
122//! The [trust depth] parameter is used to indicate that the target
123//! should also be used as a CA.  When this type of delegation is done
124//! in OpenPGP, the target is sometimes called a trusted introducer.
125//!
126//! The trust depth parameter ranges from 0 to 255.  A value of 0
127//! means that the target is not a trusted introducer, and this is
128//! just a normal certification of the binding.  If the issuer of a
129//! certification uses a value of 1, it means that they consider the
130//! target to also be a trusted introducer.  A value of 2 means that
131//! not only is the issuer willing to rely on certifications made by
132//! the target, but the target can designate other certificates as
133//! trusted introducers.  A value of 3 means that the third party can
134//! delegate the certification capability.  In general, a value of `n`
135//! means that a certificate that is at most `n` steps away from the
136//! issuer may be considered a trusted introducer, and certificates
137//! that are at most `n+1` steps away from the issuer can be
138//! authenticated.  Consider the following network where the number is
139//! the certification's trust depth parameter:
140//!
141//! ```text
142//! alice --2--> bob --2--> carol --2--> dave --2--> ed
143//! ```
144//!
145//! alice certifies bob and uses a trust depth of 2.  This means that
146//! she considers bob to be a trusted introducer and that he can
147//! delegate that capability to someone else, which he does when he
148//! certifies carol and uses a positive trust depth parameter.  Then,
149//! because carol certifies dave, alice can authenticate dave.  That
150//! is, `alice - bob - carol - dave` is a valid path.
151//!
152//! But, alice cannot authenticate ed even though dave considers ed to
153//! be a trusted introducer.  This is because alice does not consider
154//! dave to be a trusted introducer: he is too far away; alice would
155//! have had to set the trust depth on her certification of bob to 3
156//! for her to consider dave a trusted introducer.
157//!
158//! The trust amount and trust depth parameters interact.  If alice
159//! certifies bob's certificate and sets a trust depth of 1 and a
160//! trust amount of 60, then the trust amount of any certifications
161//! that bob makes are limited to 60.  Consider:
162//!
163//! ```text
164//! alice --60/1--> bob --120/0--> carol
165//! ```
166//!
167//! In the above network, alice says that bob is a partially trusted
168//! introducer (amount = 60).  Even though bob has certificated
169//! carol's key with a trust amount of 120, alice only assigns the
170//! path `alice - bob - carol` a trust amount of 60.  In general, a
171//! path's trust amount is the minimum trust amount of any
172//! certification in the path.
173//!
174//! The final parameter is a regular expression.  A certification can
175//! include zero or more regular expressions.  If it includes at least
176//! one regular expression, then at least one of them has to match the
177//! target User ID for the path to be valid.
178//!
179//! Regular expressions are a mechanism for a user to make use of a CA
180//! in a limited way.  For instance, ed might be willing to rely on
181//! `ca@nsa.gov` to certify other `nsa.gov` User IDs, but doesn't want
182//! to rely on `ca@nsa.gov` to make a statement about any other User
183//! ID.
184//!
185//! This implementation only applies the regular expression parameter
186//! to the target User ID; it does not apply it to any CAs along the
187//! path.  Thus, `ca@nsa.gov` could consider `ca@fbi.gov` a CA and
188//! `ca@fbi.gov` might certify `paul@nsa.gov`.  And, even though the
189//! regular expression does not match the intermediate CA's User ID
190//! (`ca@fbi.gov`), it does match the target so that path would be
191//! valid.
192//!
193//! ## Multiple Paths and Maximum Flow
194//!
195//! OpenPGP does not only support binary authentication; it also
196//! supports degrees of authentication.  If the path that this
197//! implementation finds does not authenticate the binding to the
198//! required degree, then the implementation will look for additional
199//! paths.  If paths overlap, then the degree of authentication is the
200//! [maximum flow] where the capacity of an edge is the
201//! certification's trust amount.  Consider the following web of
202//! trust:
203//!
204//!   [maximum flow]: https://en.wikipedia.org/wiki/Maximum_flow_problem
205//!
206//! ```text
207//!         root
208//!          |  90/2
209//!          v
210//!        alice
211//! 40/1  /     \  60/1
212//!      v       v
213//!     bob    carol
214//! 120   \     /   120
215//!        v   v
216//!        david
217//! ```
218//!
219//! There are two paths from `root` to `david`: `root - alice - bob -
220//! david` and `root - alice - carol - david`.  The degree of
221//! authentication of each of the paths is the minimum trust amount of
222//! any certification along the path, which, in this case, is 40 and
223//! 60, respectively.  Combining these paths only results in a trust
224//! amount of 90, however, since both paths use the `root - alice`
225//! certification and its capacity is 90.
226//!
227//! ### Multiple User IDs
228//!
229//! It is possible to use a certificate to certify multiple User IDs
230//! on another certificate using different parameters.  When this
231//! happens, the path finding algorithm is run as usual and considers
232//! all certifications to find the best path; no certifications are
233//! trimmed a priori.
234//!
235//! The algorithm then creates a type of residual network where the
236//! path is removed.  But instead of subtracting capacity from the
237//! edges that occur in the path (i.e., the certifications), the
238//! capacity is subtracted from the multi-edges.  That is the capacity
239//! is removed from all of the certifications between two
240//! certificates.
241//!
242//! Consider the following network where alice has certified both
243//! `bob@some.org` and `bob@other.org` on bob's certificate:
244//!
245//! ```text
246//!              alice
247//!       40/2  /     \ 30/3
248//!            v       v
249//! bob@some.org - b - bob@other.org
250//!         20/1 /   \ 120/2
251//!             v     v
252//!           carol  dave
253//!             |     | 120/1
254//!         120 |     v
255//!             |     ed
256//!              \   / 120
257//!               v v
258//!              frank
259//! ```
260//!
261//! The algorithm first finds the path `a - b - c - f`, which has a
262//! trust amount of 20.  When the algorithm is run on the residual
263//! network, it finds `a - b - d - e - f`, which has a trust amount of
264//! 10.  This is because the algorithm has to use the `bob@other.org`
265//! certification (the `bob@some.org` certification's depth parameter
266//! is too small) and all certifications between alice and bob are
267//! suppressed by 20.
268//!
269//! Critically, the paths `a - bob@some.org - c - f` and `a -
270//! bob@other.org - d - e - f` are not combined for an aggregate trust
271//! amount of 70, even though they have no overlapped edges: they
272//! share a multi-edge, which is partially suppressed.
273//!
274//! ## Examples
275//!
276//! Authenticating a binding is a two-step process.  First, you build
277//! the network.  Then you query it.
278//!
279//! There are two ways to build the network.  You can provide OpenPGP
280//! data structures and let the library build the network for you.
281//! Or, you can describe the network.  The latter approach is useful
282//! when you've saved a network, e.g., in a database, and don't want
283//! reparse and revalidate the OpenPGP data structures, which can be
284//! computationally expensive.  It is also useful when you don't
285//! actually have OpenPGP data, but want to use the web of trust.
286//!
287//! The following two examples show each of these approaches using the
288//! following network:
289//!
290//! ```text
291//!           0xAA, alice@example.org
292//!                    |  40/1/some.org
293//!                    v
294//!             0xCA, ca@some.org
295//!     120/0  /                 \  120/0
296//!           v                   v
297//! 0xBB, bob@some.org     0xCC, carol@other.org
298//! ```
299//!
300//! (The numbers next to the edges are the trust amount and trust
301//! depth.  They are sometimes followed by a domain.  The domain
302//! corresponds to a regular expression that matches email addresses
303//! in that domain.)
304//!
305//! There are four certificates.  `alice@example.org` has certified
306//! `ca@some.org` to be a partially trusted (amount = 40) trusted
307//! introducer (depth = 1), scoped to `some.org`.  And, `ca@some.org`
308//! has certified `bob@some.org` and `carol@other.org`.
309//!
310//! With `alice@example.org` as a root, we can partially authenticate
311//! `bob@some.org`, but, due to the scoping rule, we can't
312//! authenticate `carol@other.org` at all: the User ID doesn't match
313//! the regular expression.
314//!
315//! ### Using OpenPGP Data Structures
316//!
317//! ```
318//! use sequoia_openpgp as openpgp;
319//! use openpgp::Cert;
320//! use openpgp::cert::CertParser;
321//! use openpgp::Fingerprint;
322//! use openpgp::packet::UserID;
323//! use openpgp::parse::Parse;
324//! use openpgp::policy::StandardPolicy;
325//!
326//! use sequoia_wot::Network;
327//! use sequoia_wot::FULLY_TRUSTED;
328//! use sequoia_wot::PARTIALLY_TRUSTED;
329//!
330//! # fn main() -> anyhow::Result<()> {
331//!
332//! let keyring = "-----BEGIN PGP PUBLIC KEY BLOCK-----
333//!
334//!     xjMEYW/3iRYJKwYBBAHaRw8BAQdAnjTe1KqODINdZOIHuaG8s9aOoJxNJ+CunEI5
335//! #   XM3nCGbCwAsEHxYKAH0FgmFv94kDCwkHCRAT3t2aD+UaV0cUAAAAAAAeACBzYWx0
336//! #   QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmfX931STLM0Jms6P9W4v8WGhgmfuuaO
337//! #   TT8Umsbx55vS8AMVCggCmwECHgEWIQQ3B3E3Sb1zXwy91VUT3t2aD+UaVwAAy+gA
338//! #   /1lMXxNzxQLbjQsrioAKi+k0Wb2JxlJU1/9bWmGWUu78AP4gUXAYc7eWYa49iiuG
339//! #   d2CIwnMu++/6gA2tCU9Oj3BbCc0NPGNhQHNvbWUub3JnPsLADgQTFgoAgAWCYW/3
340//! #   iQMLCQcJEBPe3ZoP5RpXRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt
341//! #   cGdwLm9yZ6aTpERi74O/4kUhJybOIrhCgMjzqntoWNdLZCPnvl79AxUKCAKZAQKb
342//! #   AQIeARYhBDcHcTdJvXNfDL3VVRPe3ZoP5RpXAAArdAD9EeFG8OylF5aykO7c6uxE
343//! #   of3DafAzDzIpbZ5rNC1jrDgBAOUjPP4z9Y040MsPVZaUnAY/1Cz3EnNSmwUyX8kw
344//! #   5ocOwsAfBBAWCgCRBYJhcAVJBYMJZ5o7A4UBKBeGPFtePl0rW0AuXXNvbWVcLm9y
345//! #   Zz4kAAkQ0WzsWOrfU01HFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1w
346//! #   Z3Aub3JnTJBFIWL2tBbfuUxHvEXeqG+eYezdu9/ZHLRGhPmaJSgWIQTOOYvmU4lU
347//! #   jsIzT+jRbOxY6t9TTQAAqEIBAOFaZ5WNUYgzLQm0cONZ18NcETl5CLtXs5nAvkOy
348//! #   RCALAP9I9XXLsTZ3yhrQ2DLxY0Ofc2AYnIZbSUoH/Mp4B61oDs4zBGFv94kWCSsG
349//! #   AQQB2kcPAQEHQHCTaKwm4GF8Pq/4yELj2mDQeavJtS5tseDG7PNofRqtwsC/BBgW
350//! #   CgExBYJhb/eJCRAT3t2aD+UaV0cUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1
351//! #   b2lhLXBncC5vcme6uYEsVIk0S5cxjhSAoWzvT8JO6EVVD1V5cjVvKrNsBQKbAr6g
352//! #   BBkWCgBvBYJhb/eJCRA3bmybINBvi0cUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5z
353//! #   ZXF1b2lhLXBncC5vcmeQxtudFLbnDAdIkeDYGvY/SDGK/8WjZj6OIeaB9lN9XxYh
354//! #   BEr0Vidlm4mGYZWHADdubJsg0G+LAABWowD+PWlZo6HD/E1msiCzbsQE3kymenO2
355//! #   0zi9wO9K6tpWSjEBAPfJwl3P75DfuZFk7oFfs1dEu13Y6sqFNXtWAdv9pSAOFiEE
356//! #   NwdxN0m9c18MvdVVE97dmg/lGlcAAFbUAQC+q7zIXXpAsYPtgkZFLwE7P6FT6Mwc
357//! #   fNQsWJThSs3l2wEAu3w17et6Um462YyA7/e8oYoof0jmE6zm8J+rpiJ9vAzGMwRh
358//! #   b/eJFgkrBgEEAdpHDwEBB0Dy4HQX3KNylOVGxcr1fCsPLrKRMXU4NBEuN4tKA9Bf
359//! #   NMLACwQfFgoAfQWCYW/3iQMLCQcJENFs7Fjq31NNRxQAAAAAAB4AIHNhbHRAbm90
360//! #   YXRpb25zLnNlcXVvaWEtcGdwLm9yZ3H4ZFguXTuDstdPt/4OEHz7pzPAeDfnrqVN
361//! #   31tK7REeAxUKCAKbAQIeARYhBM45i+ZTiVSOwjNP6NFs7Fjq31NNAAAGMwEAq7HL
362//! #   EhSsj6m3/d5w+brM5wPy5NfeRU//KDlypn+k/jkBAJgjigEl7PHou/S/7xCl3/yN
363//! #   jrSmctNaPcWKaHvA8mYGzRM8YWxpY2VAZXhhbXBsZS5vcmc+wsAOBBMWCgCABYJh
364//! #   b/eJAwsJBwkQ0WzsWOrfU01HFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9p
365//! #   YS1wZ3Aub3JnwiIwVUPZ4cWc6uxMET790yfw9FNMyNVSv5sprbnM7S4DFQoIApkB
366//! #   ApsBAh4BFiEEzjmL5lOJVI7CM0/o0WzsWOrfU00AAJshAP98sZXu0EOhQhvuiVrk
367//! #   Td/3nuOTDBEP7vbS9IQdz/1O0wD+IXMHZDL4kAoYaRzdBN67lTPNoF86CgF5o6Xj
368//! #   ss+JOwHOMwRhb/eJFgkrBgEEAdpHDwEBB0BEpXxuCZPOh5bZHmIxM8t1pW1QVM4G
369//! #   pgDIOKVfT7p+DMLAvwQYFgoBMQWCYW/3iQkQ0WzsWOrfU01HFAAAAAAAHgAgc2Fs
370//! #   dEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3Jn7sWL0sTBq10p7d2GN7ZgsZkUxVY+
371//! #   JUnn9R4WhFaH06YCmwK+oAQZFgoAbwWCYW/3iQkQY8VPvdEOAONHFAAAAAAAHgAg
372//! #   c2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3Jn+DEKCHP+xYMcV5LLB5K5dH2I
373//! #   w9BmJxSJckTsAkIX/OQWIQRvo9S/vEXV8ksghTZjxU+90Q4A4wAAorAA/2eO42HY
374//! #   FVH3wJj3SvhqT8EQ7qe/hpMPAb7uznxhL6CfAP9nlen3sa+Hb1FvEQIjCXjYv0G/
375//! #   vMJMdEujNIydIhgMCxYhBM45i+ZTiVSOwjNP6NFs7Fjq31NNAABvHwEA0LH6AxAs
376//! #   5hGYltx9cevRYBOBp6IZgcHjFe8ul+BluRkBAKoOtddLcHVWqkQvwhJfZeFsWh4Z
377//! #   xmCcSRIPhKIQKd8FxjMEYW/3iRYJKwYBBAHaRw8BAQdAaTuo6QJUO97wvBRzLjrr
378//! #   3TtHWNDmsqfNW822cxziIXfCwAsEHxYKAH0FgmFv94kDCwkHCRDHSeVh6tRJFEcU
379//! #   AAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmeOVXbQyo69KDqD
380//! #   DwF3tHvUQ+TcAo36x0OVEvO/5Tiz/wMVCggCmwECHgEWIQSU4urbpMNHKjgy1aHH
381//! #   SeVh6tRJFAAA1TEBAN9JsM3mR/mfsc8MDv4jAPHfme1Fb1kzfeSAGErxcoXCAP9Y
382//! #   SVUUITnu5an8pEq+VvfrmI3+GlUHcwHqRweNZzuyCc0OPGJvYkBzb21lLm9yZz7C
383//! #   wA4EExYKAIAFgmFv94kDCwkHCRDHSeVh6tRJFEcUAAAAAAAeACBzYWx0QG5vdGF0
384//! #   aW9ucy5zZXF1b2lhLXBncC5vcmcQLXTmQuGBBrqvrQcp9bAJRReeM6iGoKGZwyaA
385//! #   uFvJiwMVCggCmQECmwECHgEWIQSU4urbpMNHKjgy1aHHSeVh6tRJFAAAKxkBALVZ
386//! #   0bfvmTiZGdRdwmmN11o8jW7Y4Dl03qBxM4mnlImpAPkB8aHacdJqayTGXAHEpCYs
387//! #   in4Rub0MrpL8sHXLVGHPCMLAAwQQFgoAdQWCYXAFSQWDCWeaOwkQE97dmg/lGldH
388//! #   FAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3JnQXhNpXB+3MHz
389//! #   Ga1xoefNExdGLVxZYUjz7aFcAhoaKRYWIQQ3B3E3Sb1zXwy91VUT3t2aD+UaVwAA
390//! #   tvoBANTItWBApjgY/JhR6iODkuzs0NgUa8FB7dciX0NKcCvuAPsFEsZ8MvZNpDWr
391//! #   wygyZqBXrfGeVF9XX5gea+YjPszJD84zBGFv94kWCSsGAQQB2kcPAQEHQCw202vX
392//! #   S2AO45UCegla3BdT5Ni04rU0UmmPb9VdEiEYwsC/BBgWCgExBYJhb/eJCRDHSeVh
393//! #   6tRJFEcUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmeNRh9E
394//! #   KpZbEAC5BGlRwmdRJ+ezFjLbFRTBODMnakTtdAKbAr6gBBkWCgBvBYJhb/eJCRDr
395//! #   Orxt/dguCUcUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmfO
396//! #   n5KJiwXj8/+4OcbCxpa2WAtmlN48ryqBuNgu0pzVuRYhBAz8pIL7wcszRr42iOs6
397//! #   vG392C4JAAARegEA7RV9eqlrzRep7Oh0LRDD6zXoambuyOtttJQRKE/OKlABAMyI
398//! #   Ha/5V3O4lfspfI0ghuTMxTPc81rRcREhwYuqXNwDFiEElOLq26TDRyo4MtWhx0nl
399//! #   YerUSRQAAEB0AQDgyVqdYxHb1XmGbKqmzAK7hClGXDkqGjngOh6r3l8oQAD+I330
400//! #   E8ZHE0PBWJ6Rb6YXmtPEsvcsEgfm/pN0augU7A/GMwRhb/eKFgkrBgEEAdpHDwEB
401//! #   B0DR6YaeeCOax42CffJndlZvv/r09cCVjt0ORB90j9lEP8LACwQfFgoAfQWCYW/3
402//! #   igMLCQcJEFJtELjzPANJRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEt
403//! #   cGdwLm9yZyvJ6GlUekEcAqYsIeiFEyhdlqAW/OvPq1fDs/yMXdUJAxUKCAKbAQIe
404//! #   ARYhBLIOjtMetcD960cJ6lJtELjzPANJAAB0EQEA/OuyDfAHgqfTd2bRzYzT7I2o
405//! #   PiB/ihV0WUuUc88j/NkBAIe0op34YsVQKLU9Ix+JbZTfRkdYnTgOriY2lzHR5+oE
406//! #   zRE8Y2Fyb2xAb3RoZXIub3JnPsLADgQTFgoAgAWCYW/3igMLCQcJEFJtELjzPANJ
407//! #   RxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ0pWZ7F81PpB
408//! #   rbYdp6JBWdbl0VqHn1AWIlR1Ry+uUvm9AxUKCAKZAQKbAQIeARYhBLIOjtMetcD9
409//! #   60cJ6lJtELjzPANJAAAXFAEA4jXm0znj0C/Ye6JYHOneGpoFgfCWy7kx+qR0zKJh
410//! #   ocoA/22vYYb0g+L6Kdo+gTITaibHoWYkztcisqJcirONz8YJwsADBBAWCgB1BYJh
411//! #   cAVJBYMJZ5o7CRAT3t2aD+UaV0cUAAAAAAAeACBzYWx0QG5vdGF0aW9ucy5zZXF1
412//! #   b2lhLXBncC5vcmc6zt9LwAW1nYyI2k0zINUYzXj9pWLfh2Uij020D+014RYhBDcH
413//! #   cTdJvXNfDL3VVRPe3ZoP5RpXAADe/wD/eKl+iefK1jhuGecOD2MBFOGuWKdmTjL6
414//! #   x8lx08W1iFYA/i2kkP6uUIX8rn4HlWcY+tdWxzEfT3ExrW8UGtFov+wEzjMEYW/3
415//! #   ihYJKwYBBAHaRw8BAQdAvHEeR20eC+45UsCaUdfxkG/CkEYzzyyCZk/gc4RRDVTC
416//! #   wL8EGBYKATEFgmFv94oJEFJtELjzPANJRxQAAAAAAB4AIHNhbHRAbm90YXRpb25z
417//! #   LnNlcXVvaWEtcGdwLm9yZyyvZrTVCn1hbMFSGPoXmek6QbeFvJIxDH8IiTgx2LXa
418//! #   ApsCvqAEGRYKAG8FgmFv94oJEFVL1AWo5KwsRxQAAAAAAB4AIHNhbHRAbm90YXRp
419//! #   b25zLnNlcXVvaWEtcGdwLm9yZ5vdUn08uTdpCKTyvFDQiOYJbemhOguSoBlGbunb
420//! #   vYXWFiEEZsOhvCD6arW5g7qnVUvUBajkrCwAAGuvAQCb2J/W/pV0q7AOLDFJ3PmH
421//! #   p6LXdEFyMM8MOsF9HXF0ewD/cqW1f0GnZpUqppVNWJ5UaxzwH4LJN2Syuy5dZgv5
422//! #   PAAWIQSyDo7THrXA/etHCepSbRC48zwDSQAAsIcBAL9fexChDBcBlscpSSmtzUbh
423//! #   eqZRftsm4rzrUlzU3bknAP413jTBeSQItsUjpvwBLM3jFohGLRTI8gu96jWvTXKZ
424//! #   BA==
425//! #   =QO4G
426//! #   -----END PGP PUBLIC KEY BLOCK-----" /* docstring trickery ahead:
427//!     // ...
428//!     -----END PGP PUBLIC KEY BLOCK-----";
429//! # */;
430//!
431//! let certs: Vec<Cert> = CertParser::from_bytes(keyring)?
432//!     // Silently discard invalid certifications.
433//!     .filter_map(|r| r.ok())
434//!     .collect();
435//! assert_eq!(certs.len(), 4);
436//!
437//! let alice_fpr: Fingerprint =
438//!     "CE398BE65389548EC2334FE8D16CEC58EADF534D"
439//!    .parse().expect("valid fingerprint");
440//! let alice_uid
441//!     = UserID::from("<alice@example.org>");
442//!
443//! let ca_fpr: Fingerprint =
444//!     "3707713749BD735F0CBDD55513DEDD9A0FE51A57"
445//!    .parse().expect("valid fingerprint");
446//! let ca_uid
447//!     = UserID::from("<ca@some.org>");
448//!
449//! let bob_fpr: Fingerprint =
450//!     "94E2EADBA4C3472A3832D5A1C749E561EAD44914"
451//!    .parse().expect("valid fingerprint");
452//! let bob_uid
453//!     = UserID::from("<bob@some.org>");
454//!
455//! let carol_fpr: Fingerprint =
456//!     "B20E8ED31EB5C0FDEB4709EA526D10B8F33C0349"
457//!    .parse().expect("valid fingerprint");
458//! let carol_uid
459//!     = UserID::from("<carol@other.org>");
460//!
461//! let p = &StandardPolicy::new();
462//! let n = Network::from_cert_refs(certs.iter(), p, None,
463//!                                 &[ alice_fpr.clone() ])?;
464//!
465//! let paths = n.authenticate(bob_uid, bob_fpr.clone(), FULLY_TRUSTED);
466//! assert_eq!(paths.len(), 1);
467//! assert_eq!(paths[0].0.amount(), PARTIALLY_TRUSTED);
468//! assert_eq!(paths[0].0.certificates().map(|c| c.fingerprint()).collect::<Vec<_>>(),
469//!            vec![ alice_fpr, ca_fpr, bob_fpr ]);
470//!
471//! let paths = n.authenticate(carol_uid, carol_fpr.clone(), FULLY_TRUSTED);
472//! eprintln!("{:?}", paths);
473//! assert_eq!(paths.len(), 0);
474//! # Ok(())
475//! # }
476//! ```
477//!
478//! ### Building a Network By Hand
479//!
480//! ```
481//! use std::time::SystemTime;
482//! use std::iter::once;
483//!
484//! use sequoia_openpgp as openpgp;
485//! use openpgp::Fingerprint;
486//! use openpgp::regex::RegexSet;
487//!
488//! use sequoia_wot::CertSynopsis;
489//! use sequoia_wot::UserIDSynopsis;
490//! use sequoia_wot::Certification;
491//! use sequoia_wot::Network;
492//! use sequoia_wot::RevocationStatus;
493//! use sequoia_wot::FULLY_TRUSTED;
494//! use sequoia_wot::PARTIALLY_TRUSTED;
495//!
496//! # fn main() -> anyhow::Result<()> {
497//! let reference_time = SystemTime::now();
498//!
499//! let alice_fpr: Fingerprint =
500//!     "CE398BE65389548EC2334FE8D16CEC58EADF534D"
501//!    .parse().expect("valid fingerprint");
502//! let alice_uid
503//!     = UserIDSynopsis::from("<alice@example.org>");
504//!
505//! let ca_fpr: Fingerprint =
506//!     "3707713749BD735F0CBDD55513DEDD9A0FE51A57"
507//!    .parse().expect("valid fingerprint");
508//! let ca_uid
509//!     = UserIDSynopsis::from("<ca@some.org>");
510//!
511//! let bob_fpr: Fingerprint =
512//!     "94E2EADBA4C3472A3832D5A1C749E561EAD44914"
513//!    .parse().expect("valid fingerprint");
514//! let bob_uid
515//!     = UserIDSynopsis::from("<bob@some.org>");
516//!
517//! let carol_fpr: Fingerprint =
518//!     "B20E8ED31EB5C0FDEB4709EA526D10B8F33C0349"
519//!    .parse().expect("valid fingerprint");
520//! let carol_uid
521//!     = UserIDSynopsis::from("<carol@other.org>");
522//!
523//! let alice = CertSynopsis::new(
524//!     alice_fpr.clone(), None, RevocationStatus::NotAsFarAsWeKnow,
525//!     once(alice_uid.clone()));
526//! let ca = CertSynopsis::new(
527//!     ca_fpr.clone(), None, RevocationStatus::NotAsFarAsWeKnow,
528//!     once(ca_uid.clone()));
529//! let bob = CertSynopsis::new(
530//!     bob_fpr.clone(), None, RevocationStatus::NotAsFarAsWeKnow,
531//!     once(bob_uid.clone()));
532//! let carol = CertSynopsis::new(
533//!     carol_fpr.clone(), None, RevocationStatus::NotAsFarAsWeKnow,
534//!     once(carol_uid.clone()));
535//!
536//! let alice_certifies_ca = Certification::new(
537//!     alice.clone(), Some(ca_uid.userid().clone()), ca.clone(),
538//!     reference_time)
539//!     .set_amount(PARTIALLY_TRUSTED)
540//!     .set_depth(1)
541//!     .set_regular_expressions(
542//!         [ &b"<[^>]+[@.]some.org>$"[..] ].into_iter());
543//!
544//! let ca_certifies_bob = Certification::new(
545//!     ca.clone(), Some(bob_uid.userid().clone()), bob.clone(),
546//!     reference_time);
547//!
548//! let certs = &[ alice, ca, bob, carol ][..];
549//! let certifications = &[ alice_certifies_ca, ca_certifies_bob ];
550//! let n = Network::from_synopses(
551//!     certs, certifications,
552//!     reference_time,
553//!     &[ alice_fpr.clone() ])?;
554//!
555//! let paths = n.authenticate(bob_uid.userid().clone(), bob_fpr.clone(),
556//!                            FULLY_TRUSTED);
557//! assert_eq!(paths.len(), 1);
558//! assert_eq!(paths[0].0.amount(), PARTIALLY_TRUSTED);
559//! assert_eq!(paths[0].0.certificates().map(|c| c.fingerprint()).collect::<Vec<_>>(),
560//!            vec![ alice_fpr, ca_fpr, bob_fpr ]);
561//! # Ok(())
562//! # }
563//! ```
564
565// Public re-exports.
566pub use sequoia_cert_store;
567
568type Result<T, E=anyhow::Error> = std::result::Result<T, E>;
569
570#[macro_use] mod log;
571
572pub mod store;
573mod userid;
574pub use userid::UserIDSynopsis;
575mod cert;
576pub use cert::CertSynopsis;
577mod certification;
578pub use certification::Depth;
579pub use certification::Certification;
580mod revocation;
581pub use revocation::RevocationStatus;
582pub use certification::CertificationSet;
583pub use certification::CertificationError;
584mod network;
585pub use network::{
586    CertLints,
587    CertificationLints,
588    Network,
589    NetworkBuilder,
590    PathError,
591    PathLints,
592    Root,
593    Roots,
594};
595// mod forward_propagation;
596mod backward_propagation;
597mod path;
598pub use path::{Path, Paths};
599mod priority_queue;
600use priority_queue::PriorityQueue;
601
602#[cfg(test)]
603mod testdata;
604
605const TRACE: bool = false;
606
607/// The amount of trust needed for a binding to be fully trusted.
608pub const FULLY_TRUSTED: usize = 120;
609/// The usual amount of trust assigned to a partially trusted
610/// trusted introducer.
611///
612/// Normally, three partially trusted introducers are needed to
613/// authenticate a binding.  Thus, this is a third of `FULLY_TRUSTED`.
614pub const PARTIALLY_TRUSTED: usize = 40;
615
616/// Errors used in this crate.
617///
618/// Note: This enum cannot be exhaustively matched to allow future
619/// extensions.
620#[non_exhaustive]
621#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
622pub enum Error {
623    /// Not a revocation revocation certificate.
624    #[error("Not a revocation revocation certificate")]
625    NotARevocationCertificate,
626}
627
628/// Formats the given time.
629pub(crate) fn format_time(t: &std::time::SystemTime) -> String {
630    chrono::DateTime::<chrono::Utc>::from(t.clone())
631        .format("%Y-%m-%d %H:%M.%S")
632        .to_string()
633}
634
635/// Like std::time::SystemTime::now, but works on WASM.
636fn now() -> std::time::SystemTime {
637    #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
638        chrono::Utc::now().into()
639    }
640    #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] {
641        std::time::SystemTime::now()
642    }
643}
644
645#[cfg(test)]
646mod tests {
647    use super::*;
648
649    use std::slice;
650    use std::time;
651
652    use sequoia_openpgp as openpgp;
653
654    use openpgp::Cert;
655    use openpgp::cert::CertParser;
656    use openpgp::Fingerprint;
657    use openpgp::KeyHandle;
658    use openpgp::KeyID;
659    use openpgp::parse::Parse;
660    use openpgp::packet::UserID;
661    use openpgp::policy::StandardPolicy;
662    use openpgp::Result;
663
664    use crate::store::Backend;
665    use crate::store::CertStore;
666    use crate::store::Store;
667
668    // Authenticates the target.
669    fn check<'a, S>(q: &Network<S>,
670                    target_fpr: &Fingerprint, target_userid: &UserID,
671                    expected: &[ (usize, &[ &Fingerprint ]) ],
672                    min_trust_amount: Option<usize>,
673                    gossip: bool)
674    where S: Store + Backend<'a>
675    {
676        eprintln!("\nauthenticating: {}, {}",
677                  target_fpr,
678                  String::from_utf8_lossy(target_userid.value()));
679        let got = if gossip {
680            assert!(min_trust_amount.is_none());
681            q.gossip(target_fpr.clone(),
682                     target_userid.clone())
683        } else {
684            q.authenticate(target_userid.clone(),
685                           target_fpr.clone(),
686                           min_trust_amount.unwrap_or(120))
687        };
688        match (got.iter().count() > 0, expected.len() > 0) {
689            (false, false) => {
690                eprintln!("Can't authenticate == can't authenticate (good)");
691            }
692            (false, true) => {
693                panic!("Couldn't authenticate.  Expected: paths:\n{}",
694                       expected.iter()
695                           .enumerate()
696                           .flat_map(|(i, (_, p))| {
697                               p.iter().enumerate().map(move |(j, f)| {
698                                   format!("  {}.{}. {}", i, j, f.to_hex())
699                               })
700                           })
701                           .collect::<Vec<_>>()
702                           .join("\n  "));
703            }
704            (true, false) => {
705                panic!("Unexpectedly authenticated binding.  Got:\n{}",
706                       got.iter().enumerate().map(|(i, p)| {
707                           format!("PATH #{}\n{:?}", i, p)
708                       })
709                       .collect::<Vec<_>>()
710                       .join("\n"));
711            }
712            (true, true) => {
713                eprintln!("Paths: {:?}", got);
714
715                assert_eq!(got.iter().count(), expected.len(),
716                           "Expected {:?} paths, got {:?}",
717                           expected, got);
718                for (i, ((got_amount, got_path), (expected_amount, expected_path)))
719                    in got.iter().map(|(p, a)| {
720                        (a,
721                         p.certificates().map(|c| c.fingerprint()).collect::<Vec<_>>())
722                    })
723                    .zip(expected.iter().map(|(a, fprs)| {
724                        (a, fprs.iter().map(|&fpr| {
725                            fpr.clone()
726                        }).collect::<Vec<Fingerprint>>())
727                    }))
728                    .enumerate()
729                {
730                    assert_eq!(got_path, expected_path,
731                               "got vs. expected path (#{})",
732                               i);
733                    assert_eq!(got_amount, expected_amount,
734                               "got vs. expected trust amount (#{})",
735                               i);
736                }
737                assert_eq!(got.amount(),
738                           expected.iter().map(|(a, _)| a).sum::<usize>());
739            }
740        }
741
742        // Make sure Network::path agrees that the paths are good.
743        for &(amount, path) in expected.iter() {
744            if let Err(err) = q.path(
745                &path
746                    .iter()
747                    .map(|&fpr| KeyHandle::from(fpr))
748                    .collect::<Vec<_>>()[..],
749                target_userid,
750                amount,
751                // XXX
752                &StandardPolicy::new())
753            {
754                panic!("Unexpectedly failed to validate {} {:?}: {}.",
755                       path.iter()
756                           .map(|&fpr| KeyID::from(fpr).to_hex())
757                           .collect::<Vec<_>>()
758                           .join(" "),
759                       target_userid,
760                       err);
761            }
762        }
763    }
764
765    fn sp<'a, S>(q: &Network<S>,
766                 target_fpr: &Fingerprint, target_userid: &UserID,
767                 expected: &[ (usize, &[ &Fingerprint ]) ],
768                 min_trust_amount: Option<usize>)
769    where S: Store + Backend<'a>
770    {
771        check(q, target_fpr, target_userid, expected, min_trust_amount, false);
772    }
773
774    fn gp<'a, S>(q: &Network<S>,
775                 target_fpr: &Fingerprint, target_userid: &UserID,
776                 expected: &[ (usize, &[ &Fingerprint ]) ])
777    where S: Store + Backend<'a>
778    {
779        check(q, target_fpr, target_userid, expected, None, true);
780    }
781
782    #[test]
783    #[allow(unused)]
784    fn simple() -> Result<()> {
785        let p = &StandardPolicy::new();
786
787        let alice_fpr: Fingerprint =
788            "85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D"
789           .parse().expect("valid fingerprint");
790        let alice_uid
791            = UserID::from("<alice@example.org>");
792
793        let bob_fpr: Fingerprint =
794            "39A479816C934B9E0464F1F4BC1DCFDEADA4EE90"
795           .parse().expect("valid fingerprint");
796        let bob_uid
797            = UserID::from("<bob@example.org>");
798        // Certified by: 85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D
799
800        let carol_fpr: Fingerprint =
801            "43530F91B450EDB269AA58821A1CF4DC7F500F04"
802           .parse().expect("valid fingerprint");
803        let carol_uid
804            = UserID::from("<carol@example.org>");
805        // Certified by: 39A479816C934B9E0464F1F4BC1DCFDEADA4EE90
806
807        let dave_fpr: Fingerprint =
808            "329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281"
809           .parse().expect("valid fingerprint");
810        let dave_uid
811            = UserID::from("<dave@example.org>");
812        // Certified by: 43530F91B450EDB269AA58821A1CF4DC7F500F04
813
814        let ellen_fpr: Fingerprint =
815            "A7319A9B166AB530A5FBAC8AB43CA77F7C176AF4"
816           .parse().expect("valid fingerprint");
817        let ellen_uid
818            = UserID::from("<ellen@example.org>");
819        // Certified by: 329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281
820
821        let frank_fpr: Fingerprint =
822            "2693237D2CED0BB68F118D78DC86A97CD2C819D9"
823           .parse().expect("valid fingerprint");
824        let frank_uid
825            = UserID::from("<frank@example.org>");
826
827
828        let certs: Vec<Cert> = CertParser::from_bytes(
829            &crate::testdata::data("simple.pgp"))?
830            .map(|c| c.expect("Valid certificate"))
831            .collect();
832        let store = CertStore::from_cert_refs(
833            certs.iter().map(|c| c.into()), p, None)?;
834        let n = NetworkBuilder::rooted(
835            &store, slice::from_ref(&alice_fpr)).build();
836
837        eprintln!("{:?}", n);
838
839        sp(&n, &alice_fpr, &alice_uid.clone(),
840           &[ (120, &[ &alice_fpr ][..]) ][..],
841           None);
842
843        sp(&n, &bob_fpr, &bob_uid.clone(),
844           &[ (100, &[ &alice_fpr, &bob_fpr ][..]) ][..],
845           None);
846
847        sp(&n, &carol_fpr, &carol_uid.clone(),
848           &[ (100, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
849           None);
850
851        sp(&n, &dave_fpr, &dave_uid.clone(),
852           &[ (100, &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
853           None);
854
855        sp(&n, &ellen_fpr, &ellen_uid.clone(),
856           &[][..],
857           None);
858
859        sp(&n, &frank_fpr, &frank_uid.clone(),
860           &[][..],
861           None);
862
863        // No one authenticated Bob's User ID on Carol's key.
864        sp(&n, &carol_fpr, &bob_uid.clone(),
865           &[][..],
866           None);
867
868        let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
869
870        sp(&n, &alice_fpr, &alice_uid.clone(),
871           &[][..],
872           None);
873
874        sp(&n, &bob_fpr, &bob_uid.clone(),
875           &[ (120, &[ &bob_fpr ][..]) ][..],
876           None);
877
878        sp(&n, &carol_fpr, &carol_uid.clone(),
879           &[ (100, &[ &bob_fpr, &carol_fpr ][..]) ][..],
880           None);
881
882        sp(&n, &dave_fpr, &dave_uid.clone(),
883           &[ (100, &[ &bob_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
884           None);
885
886        sp(&n, &ellen_fpr, &ellen_uid.clone(),
887           &[][..],
888           None);
889
890        sp(&n, &frank_fpr, &frank_uid.clone(),
891           &[][..],
892           None);
893
894        // No one authenticated Bob's User ID on Carol's key.
895        sp(&n, &carol_fpr, &bob_uid.clone(),
896           &[][..],
897           None);
898
899        Ok(())
900    }
901
902    #[test]
903    #[allow(unused)]
904    fn simple_gossip() -> Result<()> {
905        let p = &StandardPolicy::new();
906
907        let alice_fpr: Fingerprint =
908            "85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D"
909           .parse().expect("valid fingerprint");
910        let alice_uid
911            = UserID::from("<alice@example.org>");
912
913        let bob_fpr: Fingerprint =
914            "39A479816C934B9E0464F1F4BC1DCFDEADA4EE90"
915           .parse().expect("valid fingerprint");
916        let bob_uid
917            = UserID::from("<bob@example.org>");
918        // Certified by: 85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D
919
920        let carol_fpr: Fingerprint =
921            "43530F91B450EDB269AA58821A1CF4DC7F500F04"
922           .parse().expect("valid fingerprint");
923        let carol_uid
924            = UserID::from("<carol@example.org>");
925        // Certified by: 39A479816C934B9E0464F1F4BC1DCFDEADA4EE90
926
927        let dave_fpr: Fingerprint =
928            "329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281"
929           .parse().expect("valid fingerprint");
930        let dave_uid
931            = UserID::from("<dave@example.org>");
932        // Certified by: 43530F91B450EDB269AA58821A1CF4DC7F500F04
933
934        let ellen_fpr: Fingerprint =
935            "A7319A9B166AB530A5FBAC8AB43CA77F7C176AF4"
936           .parse().expect("valid fingerprint");
937        let ellen_uid
938            = UserID::from("<ellen@example.org>");
939        // Certified by: 329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281
940
941        let frank_fpr: Fingerprint =
942            "2693237D2CED0BB68F118D78DC86A97CD2C819D9"
943           .parse().expect("valid fingerprint");
944        let frank_uid
945            = UserID::from("<frank@example.org>");
946
947
948        let certs: Vec<Cert> = CertParser::from_bytes(
949            &crate::testdata::data("simple.pgp"))?
950            .map(|c| c.expect("Valid certificate"))
951            .collect();
952        let store = CertStore::from_cert_refs(
953            certs.iter().map(|c| c.into()), p, None)?;
954        let n = NetworkBuilder::rooted(
955            &store, slice::from_ref(&alice_fpr)).build();
956
957        eprintln!("{:?}", n);
958
959        gp(&n, &alice_fpr, &alice_uid.clone(),
960           &[
961               (120, &[ &alice_fpr ][..])
962           ][..]);
963
964        gp(&n, &bob_fpr, &bob_uid.clone(),
965           &[
966               (100, &[ &alice_fpr, &bob_fpr ][..]),
967               (0, &[ &bob_fpr ][..]),
968           ][..]);
969
970        gp(&n, &carol_fpr, &carol_uid.clone(),
971           &[
972               (100, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]),
973               (0, &[ &carol_fpr ][..]),
974           ][..]);
975
976        gp(&n, &dave_fpr, &dave_uid.clone(),
977           &[
978               (100, &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr ][..]),
979               (0, &[ &dave_fpr ][..]),
980           ][..]);
981
982        gp(&n, &ellen_fpr, &ellen_uid.clone(),
983           &[
984               (0, &[ &carol_fpr, &dave_fpr, &ellen_fpr ][..]),
985               (0, &[ &ellen_fpr ][..]),
986           ][..]);
987
988        gp(&n, &frank_fpr, &frank_uid.clone(),
989           &[
990               (0, &[ &frank_fpr ][..]),
991           ][..]);
992
993        // No one authenticated Bob's User ID on Carol's key.
994        gp(&n, &carol_fpr, &bob_uid.clone(),
995           &[][..]);
996
997        let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
998
999        gp(&n, &alice_fpr, &alice_uid.clone(),
1000           &[
1001               (0, &[ &alice_fpr ][..]),
1002           ][..]);
1003
1004        gp(&n, &bob_fpr, &bob_uid.clone(),
1005           &[
1006               (120, &[ &bob_fpr ][..]),
1007           ][..]);
1008
1009        gp(&n, &carol_fpr, &carol_uid.clone(),
1010           &[
1011               (100, &[ &bob_fpr, &carol_fpr ][..]),
1012               (0, &[ &carol_fpr ][..]),
1013           ][..]);
1014
1015        gp(&n, &dave_fpr, &dave_uid.clone(),
1016           &[
1017               (100, &[ &bob_fpr, &carol_fpr, &dave_fpr ][..]),
1018               (0, &[ &dave_fpr ][..]),
1019           ][..]);
1020
1021        gp(&n, &ellen_fpr, &ellen_uid.clone(),
1022           &[
1023               (0, &[ &carol_fpr, &dave_fpr, &ellen_fpr ][..]),
1024               (0, &[ &ellen_fpr ][..]),
1025           ][..]);
1026
1027        gp(&n, &frank_fpr, &frank_uid.clone(),
1028           &[
1029               (0, &[ &frank_fpr ][..]),
1030           ][..]);
1031
1032        // No one authenticated Bob's User ID on Carol's key.
1033        gp(&n, &carol_fpr, &bob_uid.clone(),
1034           &[][..]);
1035
1036        Ok(())
1037    }
1038
1039    #[test]
1040    #[allow(unused)]
1041    fn cycle() -> Result<()> {
1042        let p = &StandardPolicy::new();
1043
1044        let alice_fpr: Fingerprint =
1045            "BFC5CA10FB55A4B790E2A1DBA5CFAB9A9E34E183"
1046           .parse().expect("valid fingerprint");
1047        let alice_uid
1048            = UserID::from("<alice@example.org>");
1049
1050        let bob_fpr: Fingerprint =
1051            "A637747DCF876A7F6C9149F74D47846E24A20C0B"
1052           .parse().expect("valid fingerprint");
1053        let bob_uid
1054            = UserID::from("<bob@example.org>");
1055        // Certified by: 4458062DC7388909CF760E6823150D8E4408638A
1056        // Certified by: BFC5CA10FB55A4B790E2A1DBA5CFAB9A9E34E183
1057
1058        let carol_fpr: Fingerprint =
1059            "394B04774FDAB0CDBF4D6FFD7930EA0FB549E303"
1060           .parse().expect("valid fingerprint");
1061        let carol_uid
1062            = UserID::from("<carol@example.org>");
1063        // Certified by: A637747DCF876A7F6C9149F74D47846E24A20C0B
1064
1065        let dave_fpr: Fingerprint =
1066            "4458062DC7388909CF760E6823150D8E4408638A"
1067           .parse().expect("valid fingerprint");
1068        let dave_uid
1069            = UserID::from("<dave@example.org>");
1070        // Certified by: 394B04774FDAB0CDBF4D6FFD7930EA0FB549E303
1071
1072        let ed_fpr: Fingerprint =
1073            "78C3814EFD16E68F4F1AB4B874E30AE11FFCFB1B"
1074           .parse().expect("valid fingerprint");
1075        let ed_uid
1076            = UserID::from("<ed@example.org>");
1077        // Certified by: 4458062DC7388909CF760E6823150D8E4408638A
1078
1079        let frank_fpr: Fingerprint =
1080            "A6219FF753AEAE2DE8A74E8487977DD568A08237"
1081           .parse().expect("valid fingerprint");
1082        let frank_uid
1083            = UserID::from("<frank@example.org>");
1084        // Certified by: 78C3814EFD16E68F4F1AB4B874E30AE11FFCFB1B
1085
1086
1087        let certs: Vec<Cert> = CertParser::from_bytes(
1088            &crate::testdata::data("cycle.pgp"))?
1089            .map(|c| c.expect("Valid certificate"))
1090            .collect();
1091        let store = CertStore::from_cert_refs(
1092            certs.iter().map(|c| c.into()), p, None)?;
1093        let n = NetworkBuilder::rootless(&store).build();
1094
1095        eprintln!("{:?}", n);
1096
1097        let n = NetworkBuilder::rooted(
1098            &store, slice::from_ref(&alice_fpr)).build();
1099
1100        sp(&n, &alice_fpr, &alice_uid.clone(),
1101           &[ (120, &[ &alice_fpr ][..]) ][..],
1102           None);
1103
1104        sp(&n, &bob_fpr, &bob_uid.clone(),
1105           &[
1106               (120,
1107                &[ &alice_fpr, &bob_fpr ][..]
1108               )
1109           ][..],
1110           None);
1111
1112        sp(&n, &carol_fpr, &carol_uid.clone(),
1113           &[
1114               (90,
1115                &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]
1116               )
1117           ][..],
1118           None);
1119
1120        sp(&n, &dave_fpr, &dave_uid.clone(),
1121           &[
1122               (60,
1123                &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr ][..]
1124               )
1125           ][..],
1126           None);
1127
1128        sp(&n, &ed_fpr, &ed_uid.clone(),
1129           &[
1130               (30,
1131                &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr, &ed_fpr ][..]
1132               )
1133           ][..],
1134           None);
1135
1136        sp(&n, &frank_fpr, &frank_uid.clone(),
1137           &[][..],
1138           None);
1139
1140        let n = NetworkBuilder::rooted(
1141            &store, &[ alice_fpr.clone(), dave_fpr.clone()  ]).build();
1142
1143
1144        sp(&n, &alice_fpr, &alice_uid.clone(),
1145           &[ (120, &[ &alice_fpr ][..]) ][..],
1146           None);
1147
1148        // The following paths are identical and the sorting depends
1149        // on the fingerprint.  Thus regenerating the keys could
1150        // create a failure.
1151        sp(&n, &bob_fpr, &bob_uid.clone(),
1152           &[
1153               (120, &[ &alice_fpr, &bob_fpr ][..]),
1154               (120, &[ &dave_fpr, &bob_fpr ][..]),
1155           ][..],
1156           Some(300));
1157
1158        // The following paths are identical and the sorting depends
1159        // on the fingerprint.  Thus regenerating the keys could
1160        // create a failure.
1161        sp(&n, &carol_fpr, &carol_uid.clone(),
1162           &[
1163               (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]),
1164           ][..],
1165           None);
1166
1167        sp(&n, &ed_fpr, &ed_uid.clone(),
1168           &[
1169               (30,
1170                &[ &dave_fpr, &ed_fpr ][..]
1171               )
1172           ][..],
1173           None);
1174
1175        sp(&n, &frank_fpr, &frank_uid.clone(),
1176           &[
1177               (30,
1178                &[ &dave_fpr, &ed_fpr, &frank_fpr ][..]
1179               )
1180           ][..],
1181           None);
1182
1183        Ok(())
1184    }
1185
1186    #[test]
1187    #[allow(unused)]
1188    fn cliques() -> Result<()> {
1189        use std::time::Duration;
1190
1191        let p = &StandardPolicy::new();
1192
1193        let root_fpr: Fingerprint =
1194            "D2B0 C383 5C01 B0C1 20BC  540D A4AA 8F88 0BA5 12B5"
1195           .parse().expect("valid fingerprint");
1196        let root_uid
1197            = UserID::from("<root@example.org>");
1198
1199        let a_0_fpr: Fingerprint =
1200            "3630 82E9 EEB2 2E50 AD30  3D8B 1BFE 9BA3 F4AB D40E"
1201           .parse().expect("valid fingerprint");
1202        let a_0_uid
1203            = UserID::from("<a-0@example.org>");
1204
1205        let a_1_fpr: Fingerprint =
1206            "7974 C04E 8D5B 540D 23CD  4E62 DDFA 779D 91C6 9894"
1207           .parse().expect("valid fingerprint");
1208        let a_1_uid
1209            = UserID::from("<a-1@example.org>");
1210
1211        let b_0_fpr: Fingerprint =
1212            "25D8 EAAB 8947 05BB 64D4  A6A8 9649 EF81 AEFE 5162"
1213           .parse().expect("valid fingerprint");
1214        let b_0_uid
1215            = UserID::from("<b-0@example.org>");
1216
1217        let b_1_fpr: Fingerprint =
1218            "46D2 F5CE D9BD 3D63 A11D  DFEE 1BA0 1950 6BE6 7FBB"
1219           .parse().expect("valid fingerprint");
1220        let b_1_uid
1221            = UserID::from("<b-1@example.org>");
1222
1223        let c_0_fpr: Fingerprint =
1224            "A0CD 8758 2C21 743C 0E30  637F 7FAD B1C3 FEFB FE59"
1225           .parse().expect("valid fingerprint");
1226        let c_0_uid
1227            = UserID::from("<c-0@example.org>");
1228
1229        let c_1_fpr: Fingerprint =
1230            "5277 C14F 9D37 A0F4 D615  DD9C CDCC 1AC8 464C 8FE5"
1231           .parse().expect("valid fingerprint");
1232        let c_1_uid
1233            = UserID::from("<c-1@example.org>");
1234
1235        let d_0_fpr: Fingerprint =
1236            "C24C C091 02D2 2E38 E839  3C55 1669 8256 1E14 0C03"
1237           .parse().expect("valid fingerprint");
1238        let d_0_uid
1239            = UserID::from("<d-0@example.org>");
1240
1241        let d_1_fpr: Fingerprint =
1242            "7A80 DB53 30B7 D900 D5BD  1F82 EAD7 2FF7 9140 78B2"
1243           .parse().expect("valid fingerprint");
1244        let d_1_uid
1245            = UserID::from("<d-1@example.org>");
1246
1247        let e_0_fpr: Fingerprint =
1248            "D1E9 F85C EF62 7169 9FBD  E5AB 26EF E0E0 35AC 522E"
1249           .parse().expect("valid fingerprint");
1250        let e_0_uid
1251            = UserID::from("<e-0@example.org>");
1252
1253        let f_0_fpr: Fingerprint =
1254            "C0FF AEDE F092 8B18 1265  775A 222B 480E B43E 0AFF"
1255           .parse().expect("valid fingerprint");
1256        let f_0_uid
1257            = UserID::from("<f-0@example.org>");
1258
1259        let target_fpr: Fingerprint =
1260            "CE22 ECD2 82F2 19AA 9959  8BA3 B58A 7DA6 1CA9 7F55"
1261           .parse().expect("valid fingerprint");
1262        let target_uid
1263            = UserID::from("<target@example.org>");
1264
1265
1266        let certs: Vec<Cert> = CertParser::from_bytes(
1267            &crate::testdata::data("cliques.pgp"))?
1268            .map(|c| c.expect("Valid certificate"))
1269            .collect();
1270
1271        // Take the reference time from the root certificate, plus 1 year.
1272        let ref_cert = certs.iter()
1273            .find(|c| c.fingerprint() == root_fpr)
1274            .unwrap();
1275        let ref_time = ref_cert
1276            .primary_key()
1277            .key()
1278            .creation_time()
1279            .checked_add(Duration::from_secs(60 * 60 * 24 * 365))
1280            .unwrap();
1281        eprintln!("RefTime: {:?} taken from {}", ref_time, ref_cert.fingerprint());
1282
1283        let store = CertStore::from_cert_refs(
1284            certs.iter().map(|c| c.into()), p, ref_time)?;
1285        let n = NetworkBuilder::rootless(&store).build();
1286
1287        eprintln!("{:?}", n);
1288
1289        let n = NetworkBuilder::rooted(
1290            &store, slice::from_ref(&root_fpr)).build();
1291
1292        // root -> a-0 -> a-1 -> b-0 -> ... -> f-0 -> target
1293        sp(&n, &target_fpr, &target_uid.clone(),
1294           &[
1295               (120, &[
1296                   &root_fpr,
1297                   &a_0_fpr,
1298                   &a_1_fpr,
1299                   &b_0_fpr,
1300                   &b_1_fpr,
1301                   &c_0_fpr,
1302                   &c_1_fpr,
1303                   &d_0_fpr,
1304                   &d_1_fpr,
1305                   &e_0_fpr,
1306                   &f_0_fpr,
1307                   &target_fpr
1308               ][..])
1309           ],
1310           None);
1311
1312        let n = NetworkBuilder::rooted(&store, slice::from_ref(&a_1_fpr)).build();
1313
1314        sp(&n, &target_fpr, &target_uid.clone(),
1315           &[
1316               (120, &[
1317                   &a_1_fpr,
1318                   &b_0_fpr,
1319                   &b_1_fpr,
1320                   &c_0_fpr,
1321                   &c_1_fpr,
1322                   &d_0_fpr,
1323                   &d_1_fpr,
1324                   &e_0_fpr,
1325                   &f_0_fpr,
1326                   &target_fpr
1327               ][..])
1328           ][..],
1329           None);
1330
1331        let certs: Vec<Cert> = CertParser::from_bytes(
1332            &crate::testdata::data("cliques-local-optima.pgp"))?
1333            .map(|c| c.expect("Valid certificate"))
1334            .collect();
1335        let store = CertStore::from_cert_refs(
1336            certs.iter().map(|c| c.into()), p, ref_time)?;
1337        let n = NetworkBuilder::rootless(&store).build();
1338
1339        eprintln!("{:?}", n);
1340
1341        let n = NetworkBuilder::rooted(&store, slice::from_ref(&root_fpr)).build();
1342
1343        // root -> b-0 -> ... -> f-0 -> target
1344        sp(&n, &target_fpr, &target_uid.clone(),
1345           &[
1346               (30, &[
1347                   &root_fpr,
1348                   &b_0_fpr,
1349                   &b_1_fpr,
1350                   &c_0_fpr,
1351                   &c_1_fpr,
1352                   &d_0_fpr,
1353                   &d_1_fpr,
1354                   &e_0_fpr,
1355                   &f_0_fpr,
1356                   &target_fpr
1357               ][..]),
1358               (30, &[
1359                   &root_fpr,
1360                   &a_1_fpr,
1361                   &b_0_fpr,
1362                   &b_1_fpr,
1363                   &c_0_fpr,
1364                   &c_1_fpr,
1365                   &d_0_fpr,
1366                   &d_1_fpr,
1367                   &e_0_fpr,
1368                   &f_0_fpr,
1369                   &target_fpr
1370               ][..]),
1371               (60, &[
1372                   &root_fpr,
1373                   &a_0_fpr,
1374                   &a_1_fpr,
1375                   &b_0_fpr,
1376                   &b_1_fpr,
1377                   &c_0_fpr,
1378                   &c_1_fpr,
1379                   &d_0_fpr,
1380                   &d_1_fpr,
1381                   &e_0_fpr,
1382                   &f_0_fpr,
1383                   &target_fpr
1384               ][..])
1385           ],
1386           None);
1387
1388        let n = NetworkBuilder::rooted(&store, slice::from_ref(&a_1_fpr)).build();
1389
1390        sp(&n, &target_fpr, &target_uid.clone(),
1391           &[
1392               (120, &[
1393                   &a_1_fpr,
1394                   &b_0_fpr,
1395                   &b_1_fpr,
1396                   &c_0_fpr,
1397                   &c_1_fpr,
1398                   &d_0_fpr,
1399                   &d_1_fpr,
1400                   &e_0_fpr,
1401                   &f_0_fpr,
1402                   &target_fpr
1403               ][..])
1404           ][..],
1405           None);
1406
1407
1408        let certs: Vec<Cert> = CertParser::from_bytes(
1409            &crate::testdata::data("cliques-local-optima-2.pgp"))?
1410            .map(|c| c.expect("Valid certificate"))
1411            .collect();
1412        let store = CertStore::from_cert_refs(
1413            certs.iter().map(|c| c.into()), p, ref_time)?;
1414        let n = NetworkBuilder::rootless(&store).build();
1415
1416        eprintln!("{:?}", n);
1417
1418        let n = NetworkBuilder::rooted(&store, slice::from_ref(&root_fpr)).build();
1419
1420        // root -> b-0 -> ... -> f-0 -> target
1421        sp(&n, &target_fpr, &target_uid.clone(),
1422           &[
1423               (30, &[
1424                   &root_fpr,
1425                   &b_0_fpr,
1426                   &b_1_fpr,
1427                   &c_1_fpr,
1428                   &d_0_fpr,
1429                   &d_1_fpr,
1430                   &e_0_fpr,
1431                   &f_0_fpr,
1432                   &target_fpr
1433               ][..]),
1434               (30, &[
1435                   &root_fpr,
1436                   &a_1_fpr,
1437                   &b_0_fpr,
1438                   &b_1_fpr,
1439                   &c_0_fpr,
1440                   &c_1_fpr,
1441                   &d_0_fpr,
1442                   &d_1_fpr,
1443                   &e_0_fpr,
1444                   &f_0_fpr,
1445                   &target_fpr
1446               ][..]),
1447               (60, &[
1448                   &root_fpr,
1449                   &a_0_fpr,
1450                   &a_1_fpr,
1451                   &b_0_fpr,
1452                   &b_1_fpr,
1453                   &c_0_fpr,
1454                   &c_1_fpr,
1455                   &d_0_fpr,
1456                   &d_1_fpr,
1457                   &e_0_fpr,
1458                   &f_0_fpr,
1459                   &target_fpr
1460               ][..])
1461           ],
1462           None);
1463
1464        let n = NetworkBuilder::rooted(&store, slice::from_ref(&a_1_fpr)).build();
1465
1466        sp(&n, &target_fpr, &target_uid.clone(),
1467           &[
1468               (30, &[
1469                   &a_1_fpr,
1470                   &b_0_fpr,
1471                   &b_1_fpr,
1472                   &c_1_fpr,
1473                   &d_0_fpr,
1474                   &d_1_fpr,
1475                   &e_0_fpr,
1476                   &f_0_fpr,
1477                   &target_fpr
1478               ][..]),
1479               (90, &[
1480                   &a_1_fpr,
1481                   &b_0_fpr,
1482                   &b_1_fpr,
1483                   &c_0_fpr,
1484                   &c_1_fpr,
1485                   &d_0_fpr,
1486                   &d_1_fpr,
1487                   &e_0_fpr,
1488                   &f_0_fpr,
1489                   &target_fpr
1490               ][..])
1491           ][..],
1492           None);
1493
1494        Ok(())
1495    }
1496
1497    #[test]
1498    #[allow(unused)]
1499    fn roundabout() -> Result<()> {
1500        let p = &StandardPolicy::new();
1501
1502        let alice_fpr: Fingerprint =
1503            "41E9B069C96EB6D47525294B10BBBD00912BEA02"
1504           .parse().expect("valid fingerprint");
1505        let alice_uid
1506            = UserID::from("<alice@example.org>");
1507
1508        let bob_fpr: Fingerprint =
1509            "2E90AEE966DF28CB916439B20397E086E705AC1A"
1510           .parse().expect("valid fingerprint");
1511        let bob_uid
1512            = UserID::from("<bob@example.org>");
1513        // Certified by: 3267D46247D26101B3E5014CDF4F9BA5831D91DA
1514        // Certified by: 41E9B069C96EB6D47525294B10BBBD00912BEA02
1515
1516        let carol_fpr: Fingerprint =
1517            "92DDE8747C8E6ED09D41A4E1330D1190E858754C"
1518           .parse().expect("valid fingerprint");
1519        let carol_uid
1520            = UserID::from("<carol@example.org>");
1521        // Certified by: 41E9B069C96EB6D47525294B10BBBD00912BEA02
1522
1523        let dave_fpr: Fingerprint =
1524            "D4515E6619084ED8142DF8589059E3846A025611"
1525           .parse().expect("valid fingerprint");
1526        let dave_uid
1527            = UserID::from("<dave@example.org>");
1528        // Certified by: 92DDE8747C8E6ED09D41A4E1330D1190E858754C
1529
1530        let elmar_fpr: Fingerprint =
1531            "E553C11DCFA777F3205E5090F5EE59C2795CDBA2"
1532           .parse().expect("valid fingerprint");
1533        let elmar_uid
1534            = UserID::from("<elmar@example.org>");
1535        // Certified by: AE40578962411356F9609CAA9C2447E61FFDBB15
1536        // Certified by: D4515E6619084ED8142DF8589059E3846A025611
1537
1538        let frank_fpr: Fingerprint =
1539            "3267D46247D26101B3E5014CDF4F9BA5831D91DA"
1540           .parse().expect("valid fingerprint");
1541        let frank_uid
1542            = UserID::from("<frank@example.org>");
1543        // Certified by: E553C11DCFA777F3205E5090F5EE59C2795CDBA2
1544
1545        let george_fpr: Fingerprint =
1546            "CCD5DB27BD7C4F8E2010083605EF17E8A93EB652"
1547           .parse().expect("valid fingerprint");
1548        let george_uid
1549            = UserID::from("<george@example.org>");
1550        // Certified by: AE40578962411356F9609CAA9C2447E61FFDBB15
1551        // Certified by: 2E90AEE966DF28CB916439B20397E086E705AC1A
1552
1553        let henry_fpr: Fingerprint =
1554            "7F62EF97091AE1FCB4E1C67EC8D9E94C4731529B"
1555           .parse().expect("valid fingerprint");
1556        let henry_uid
1557            = UserID::from("<henry@example.org>");
1558        // Certified by: CCD5DB27BD7C4F8E2010083605EF17E8A93EB652
1559
1560        let isaac_fpr: Fingerprint =
1561            "32FD4D68B3227334CD0583E9FA0721F49D2F395D"
1562           .parse().expect("valid fingerprint");
1563        let isaac_uid
1564            = UserID::from("<isaac@example.org>");
1565        // Certified by: 7F62EF97091AE1FCB4E1C67EC8D9E94C4731529B
1566
1567        let jenny_fpr: Fingerprint =
1568            "AE40578962411356F9609CAA9C2447E61FFDBB15"
1569           .parse().expect("valid fingerprint");
1570        let jenny_uid
1571            = UserID::from("<jenny@example.org>");
1572
1573        let certs: Vec<Cert> = CertParser::from_bytes(
1574            &crate::testdata::data("roundabout.pgp"))?
1575            .map(|c| c.expect("Valid certificate"))
1576            .collect();
1577        let store = CertStore::from_cert_refs(
1578            certs.iter().map(|c| c.into()), p, None)?;
1579        let n = NetworkBuilder::rootless(&store).build();
1580
1581        eprintln!("{:?}", n);
1582
1583        let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
1584
1585        sp(&n, &alice_fpr, &alice_uid.clone(),
1586           &[ (120, &[ &alice_fpr ][..]) ][..],
1587           None);
1588
1589        sp(&n, &bob_fpr, &bob_uid.clone(),
1590           &[
1591               (60,
1592                &[ &alice_fpr, &bob_fpr ][..]
1593               ),
1594               (120,
1595                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr,
1596                    &frank_fpr, &bob_fpr ][..]
1597               )
1598           ][..],
1599           None);
1600
1601        sp(&n, &carol_fpr, &carol_uid.clone(),
1602           &[ (120, &[ &alice_fpr, &carol_fpr ][..]) ][..],
1603           None);
1604
1605        sp(&n, &dave_fpr, &dave_uid.clone(),
1606           &[ (120, &[ &alice_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
1607           None);
1608
1609        sp(&n, &elmar_fpr, &elmar_uid.clone(),
1610           &[ (120, &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr ][..]) ][..],
1611           None);
1612
1613        sp(&n, &frank_fpr, &frank_uid.clone(),
1614           &[
1615               (120,
1616                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr,
1617                    &frank_fpr ][..]
1618               )
1619           ][..],
1620           None);
1621
1622        sp(&n, &george_fpr, &george_uid.clone(),
1623           &[
1624               (60,
1625                &[ &alice_fpr, &bob_fpr, &george_fpr ][..]
1626               ),
1627               (60,
1628                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr,
1629                    &frank_fpr, &bob_fpr, &george_fpr ][..]
1630               )
1631           ][..],
1632           None);
1633
1634        sp(&n, &henry_fpr, &henry_uid.clone(),
1635           &[
1636               (60,
1637                &[ &alice_fpr, &bob_fpr, &george_fpr, &henry_fpr ][..]
1638               ),
1639               (60,
1640                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr,
1641                    &frank_fpr, &bob_fpr, &george_fpr, &henry_fpr ][..]
1642               )
1643           ][..],
1644           None);
1645
1646        sp(&n, &isaac_fpr, &isaac_uid.clone(),
1647           &[
1648               (60,
1649                &[ &alice_fpr, &bob_fpr, &george_fpr, &henry_fpr, &isaac_fpr ][..]
1650               ),
1651           ][..],
1652           None);
1653
1654        sp(&n, &jenny_fpr, &jenny_uid.clone(),
1655           &[ ][..],
1656           None);
1657
1658
1659
1660        let n = NetworkBuilder::rooted(&store, slice::from_ref(&jenny_fpr)).build();
1661
1662        sp(&n, &alice_fpr, &alice_uid.clone(),
1663           &[][..],
1664           None);
1665
1666        sp(&n, &bob_fpr, &bob_uid.clone(),
1667           &[
1668               (100,
1669                &[ &jenny_fpr, &elmar_fpr, &frank_fpr, &bob_fpr ][..]
1670               )
1671           ][..],
1672           None);
1673
1674        sp(&n, &carol_fpr, &carol_uid.clone(),
1675           &[][..],
1676           None);
1677
1678        sp(&n, &dave_fpr, &dave_uid.clone(),
1679           &[][..],
1680           None);
1681
1682        sp(&n, &elmar_fpr, &elmar_uid.clone(),
1683           &[
1684               (100,
1685                &[ &jenny_fpr, &elmar_fpr ][..]
1686               )
1687           ][..],
1688           None);
1689
1690        sp(&n, &frank_fpr, &frank_uid.clone(),
1691           &[
1692               (100,
1693                &[ &jenny_fpr, &elmar_fpr, &frank_fpr ][..]
1694               )
1695           ][..],
1696           None);
1697
1698        sp(&n, &george_fpr, &george_uid.clone(),
1699           &[
1700               (100,
1701                &[ &jenny_fpr, &george_fpr ][..]
1702               ),
1703               (100,
1704                &[ &jenny_fpr, &elmar_fpr, &frank_fpr, &bob_fpr, &george_fpr ][..]
1705               )
1706           ][..],
1707           None);
1708
1709        sp(&n, &henry_fpr, &henry_uid.clone(),
1710           &[
1711               (100,
1712                &[ &jenny_fpr, &george_fpr, &henry_fpr ][..]
1713               ),
1714               (20,
1715                &[ &jenny_fpr, &elmar_fpr, &frank_fpr, &bob_fpr, &george_fpr, &henry_fpr ][..]
1716               )
1717           ][..],
1718           None);
1719
1720        sp(&n, &isaac_fpr, &isaac_uid.clone(),
1721           &[][..],
1722           None);
1723
1724        sp(&n, &jenny_fpr, &jenny_uid.clone(),
1725           &[ (120, &[ &jenny_fpr ][..]) ][..],
1726           None);
1727
1728
1729
1730        let n = NetworkBuilder::rooted(&store, &[ alice_fpr.clone(), jenny_fpr.clone() ]).build();
1731
1732        sp(&n, &alice_fpr, &alice_uid.clone(),
1733           &[ (120, &[ &alice_fpr ][..]) ][..],
1734           None);
1735
1736        // In the first iteration of backwards_propagate, we find two paths:
1737        //
1738        //   A -> B (60)
1739        //   J -> E -> F -> B (100)
1740        //
1741        // It doesn't find:
1742        //
1743        //   A -> C -> D -> E -> F -> B (120)
1744        //
1745        // Network::authenticate chooses the path rooted at J,
1746        // because it has more trust.  Then we call
1747        // backwards_propagate again and find:
1748        //
1749        //   A -> B (60)
1750        //
1751        // Finally, we call backwards a third time and find:
1752        //
1753        //   A -> C -> D -> E -> F -> B (120 -> 20)
1754        sp(&n, &bob_fpr, &bob_uid.clone(),
1755           &[
1756               (100,
1757                &[ &jenny_fpr, &elmar_fpr, &frank_fpr, &bob_fpr ][..]
1758                ),
1759               (60,
1760                &[ &alice_fpr, &bob_fpr ][..]
1761                ),
1762               (20,
1763                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr,
1764                    &frank_fpr, &bob_fpr ][..]
1765                ),
1766           ][..],
1767           Some(240));
1768
1769        sp(&n, &carol_fpr, &carol_uid.clone(),
1770           &[ (120, &[ &alice_fpr, &carol_fpr ][..]) ][..],
1771           None);
1772
1773        sp(&n, &dave_fpr, &dave_uid.clone(),
1774           &[ (120, &[ &alice_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
1775           None);
1776
1777        sp(&n, &elmar_fpr, &elmar_uid.clone(),
1778           &[
1779               (120,
1780                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr ][..]
1781               ),
1782           ],
1783           None);
1784
1785        sp(&n, &frank_fpr, &frank_uid.clone(),
1786           &[
1787               (120,
1788                &[ &alice_fpr, &carol_fpr, &dave_fpr, &elmar_fpr,
1789                    &frank_fpr ][..]
1790               ),
1791           ][..],
1792           Some(240));
1793
1794        sp(&n, &george_fpr, &george_uid.clone(),
1795           &[
1796               (100,
1797                &[ &jenny_fpr, &george_fpr ][..]
1798               ),
1799               (100,
1800                &[ &jenny_fpr, &elmar_fpr, &frank_fpr, &bob_fpr, &george_fpr ][..]
1801               ),
1802               (20,
1803                &[ &alice_fpr, &bob_fpr, &george_fpr ][..]
1804               ),
1805           ][..],
1806           Some(240));
1807
1808        sp(&n, &henry_fpr, &henry_uid.clone(),
1809           &[
1810               (60,
1811                &[ &alice_fpr, &bob_fpr, &george_fpr, &henry_fpr ][..]
1812               ),
1813               (60,
1814                &[ &jenny_fpr, &george_fpr, &henry_fpr ][..]
1815               ),
1816           ][..],
1817           None);
1818
1819        sp(&n, &isaac_fpr, &isaac_uid.clone(),
1820           &[
1821               (60,
1822                &[ &alice_fpr, &bob_fpr, &george_fpr, &henry_fpr, &isaac_fpr ][..]
1823               ),
1824           ][..],
1825           None);
1826
1827        sp(&n, &jenny_fpr, &jenny_uid.clone(),
1828           &[ (120, &[ &jenny_fpr ][..]) ][..],
1829           None);
1830
1831
1832        Ok(())
1833    }
1834
1835
1836    #[test]
1837    #[allow(unused)]
1838    fn local_optima() -> Result<()> {
1839        let p = &StandardPolicy::new();
1840
1841        let alice_fpr: Fingerprint =
1842            "EAAE12F98D39F38BF0D1B4C5C46A428ADEFBB2F8"
1843           .parse().expect("valid fingerprint");
1844        let alice_uid
1845            = UserID::from("<alice@example.org>");
1846
1847        let bob_fpr: Fingerprint =
1848            "89C7A9FB7236A77ABBE4F29CB8180FBF6382F90F"
1849           .parse().expect("valid fingerprint");
1850        let bob_uid
1851            = UserID::from("<bob@example.org>");
1852        // Certified by: EAAE12F98D39F38BF0D1B4C5C46A428ADEFBB2F8
1853        // Certified by: EAAE12F98D39F38BF0D1B4C5C46A428ADEFBB2F8
1854
1855        let carol_fpr: Fingerprint =
1856            "E9DF94E389F529F8EF6AA223F6CC1F8544C0874D"
1857           .parse().expect("valid fingerprint");
1858        let carol_uid
1859            = UserID::from("<carol@example.org>");
1860        // Certified by: 89C7A9FB7236A77ABBE4F29CB8180FBF6382F90F
1861        // Certified by: 89C7A9FB7236A77ABBE4F29CB8180FBF6382F90F
1862
1863        let dave_fpr: Fingerprint =
1864            "C2F822F17B68E946853A2DCFF55541D89F27F88B"
1865           .parse().expect("valid fingerprint");
1866        let dave_uid
1867            = UserID::from("<dave@example.org>");
1868        // Certified by: E9DF94E389F529F8EF6AA223F6CC1F8544C0874D
1869        // Certified by: 89C7A9FB7236A77ABBE4F29CB8180FBF6382F90F
1870
1871        let ellen_fpr: Fingerprint =
1872            "70507A9058A57FEAE18CC3CE6A398AC9051D9CA8"
1873           .parse().expect("valid fingerprint");
1874        let ellen_uid
1875            = UserID::from("<ellen@example.org>");
1876        // Certified by: C2F822F17B68E946853A2DCFF55541D89F27F88B
1877        // Certified by: C2F822F17B68E946853A2DCFF55541D89F27F88B
1878        // Certified by: E9DF94E389F529F8EF6AA223F6CC1F8544C0874D
1879
1880        let francis_fpr: Fingerprint =
1881            "D8DDA78A2297CA3C35B9377577E8B54B9350C082"
1882           .parse().expect("valid fingerprint");
1883        let francis_uid
1884            = UserID::from("<francis@example.org>");
1885        // Certified by: 70507A9058A57FEAE18CC3CE6A398AC9051D9CA8
1886        // Certified by: 89C7A9FB7236A77ABBE4F29CB8180FBF6382F90F
1887
1888        let georgina_fpr: Fingerprint =
1889            "C5D1B22FEC75911A04E1A5DC75B66B994E70ADE2"
1890           .parse().expect("valid fingerprint");
1891        let georgina_uid
1892            = UserID::from("<georgina@example.org>");
1893        // Certified by: 70507A9058A57FEAE18CC3CE6A398AC9051D9CA8
1894
1895        let henry_fpr: Fingerprint =
1896            "F260739E3F755389EFC2FEE67F58AACB661D5120"
1897           .parse().expect("valid fingerprint");
1898        let henry_uid
1899            = UserID::from("<henry@example.org>");
1900        // Certified by: 70507A9058A57FEAE18CC3CE6A398AC9051D9CA8
1901
1902
1903        let certs: Vec<Cert> = CertParser::from_bytes(
1904            &crate::testdata::data("local-optima.pgp"))?
1905            .map(|c| c.expect("Valid certificate"))
1906            .collect();
1907        let store = CertStore::from_cert_refs(
1908            certs.iter().map(|c| c.into()), p, None)?;
1909        let n = NetworkBuilder::rootless(&store).build();
1910
1911        eprintln!("{:?}", n);
1912
1913        let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
1914
1915        sp(&n, &alice_fpr, &alice_uid.clone(),
1916           &[ (120, &[ &alice_fpr ][..]) ][..],
1917           None);
1918
1919        sp(&n, &bob_fpr, &bob_uid.clone(),
1920           &[
1921               (120,
1922                &[ &alice_fpr, &bob_fpr ][..]
1923               )
1924           ][..],
1925           None);
1926
1927        sp(&n, &carol_fpr, &carol_uid.clone(),
1928           &[
1929               (100,
1930                &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]
1931               )
1932           ][..],
1933           None);
1934
1935        sp(&n, &dave_fpr, &dave_uid.clone(),
1936           &[
1937               (50,
1938                &[ &alice_fpr, &bob_fpr, &dave_fpr ][..]
1939               )
1940           ][..],
1941           None);
1942
1943        sp(&n, &ellen_fpr, &ellen_uid.clone(),
1944           &[
1945               (100,
1946                &[ &alice_fpr, &bob_fpr, &carol_fpr, &ellen_fpr ][..]
1947               ),
1948               (20,
1949                &[ &alice_fpr, &bob_fpr, &dave_fpr, &ellen_fpr ][..]
1950               ),
1951           ][..],
1952           None);
1953
1954        sp(&n, &francis_fpr, &francis_uid.clone(),
1955           &[
1956               (75,
1957                &[ &alice_fpr, &bob_fpr, &francis_fpr ][..]
1958               ),
1959               (45,
1960                &[ &alice_fpr, &bob_fpr, &carol_fpr, &ellen_fpr, &francis_fpr ][..]
1961               ),
1962           ][..],
1963           None);
1964
1965        sp(&n, &georgina_fpr, &georgina_uid.clone(),
1966           &[
1967               (30,
1968                &[ &alice_fpr, &bob_fpr, &dave_fpr, &ellen_fpr, &georgina_fpr ][..]
1969               ),
1970           ][..],
1971           None);
1972
1973        sp(&n, &henry_fpr, &henry_uid.clone(),
1974           &[
1975               (100,
1976                &[ &alice_fpr, &bob_fpr, &carol_fpr, &ellen_fpr, &henry_fpr ][..]
1977               ),
1978               (20,
1979                &[ &alice_fpr, &bob_fpr, &dave_fpr, &ellen_fpr, &henry_fpr ][..]
1980               ),
1981           ][..],
1982           None);
1983
1984        let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
1985
1986        sp(&n, &alice_fpr, &alice_uid.clone(),
1987           &[][..],
1988           None);
1989
1990        sp(&n, &bob_fpr, &bob_uid.clone(),
1991           &[ (120, &[ &bob_fpr ][..]) ][..],
1992           None);
1993
1994        sp(&n, &carol_fpr, &carol_uid.clone(),
1995           &[
1996               (100,
1997                &[ &bob_fpr, &carol_fpr ][..]
1998               )
1999           ][..],
2000           None);
2001
2002        sp(&n, &dave_fpr, &dave_uid.clone(),
2003           &[
2004               (50,
2005                &[ &bob_fpr, &dave_fpr ][..]
2006               )
2007           ][..],
2008           None);
2009
2010        sp(&n, &ellen_fpr, &ellen_uid.clone(),
2011           &[
2012               (100,
2013                &[ &bob_fpr, &carol_fpr, &ellen_fpr ][..]
2014               ),
2015               (50,
2016                &[ &bob_fpr, &dave_fpr, &ellen_fpr ][..]
2017               ),
2018           ][..],
2019           None);
2020
2021        sp(&n, &francis_fpr, &francis_uid.clone(),
2022           &[
2023               (75,
2024                &[ &bob_fpr, &francis_fpr ][..]
2025               ),
2026               (100,
2027                &[ &bob_fpr, &carol_fpr, &ellen_fpr, &francis_fpr ][..]
2028                ),
2029               (20,
2030                &[ &bob_fpr, &dave_fpr, &ellen_fpr, &francis_fpr ][..]
2031               ),
2032           ][..],
2033           Some(240));
2034
2035        Ok(())
2036    }
2037
2038    #[test]
2039    #[allow(unused)]
2040    fn multiple_userids_3() -> Result<()> {
2041        let p = &StandardPolicy::new();
2042
2043        let alice_fpr: Fingerprint =
2044            "DA3CFC60BD4B8835702A66782C7A431946C12DF7"
2045           .parse().expect("valid fingerprint");
2046        let alice_uid
2047            = UserID::from("<alice@example.org>");
2048
2049        let bob_fpr: Fingerprint =
2050            "28C108707090FCDFF630D1E141FB02F0E397D55E"
2051           .parse().expect("valid fingerprint");
2052        let bob_uid
2053            = UserID::from("<bob@other.org>");
2054        // Certified by: DA3CFC60BD4B8835702A66782C7A431946C12DF7
2055        let bob_some_org_uid
2056            = UserID::from("<bob@some.org>");
2057        // Certified by: DA3CFC60BD4B8835702A66782C7A431946C12DF7
2058        let bob_third_org_uid
2059            = UserID::from("<bob@third.org>");
2060
2061        let carol_fpr: Fingerprint =
2062            "9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8"
2063           .parse().expect("valid fingerprint");
2064        let carol_uid
2065            = UserID::from("<carol@example.org>");
2066        // Certified by: 28C108707090FCDFF630D1E141FB02F0E397D55E
2067
2068        let dave_fpr: Fingerprint =
2069            "0C131F8959F45D08B6136FDAAD2E16A26F73D48E"
2070           .parse().expect("valid fingerprint");
2071        let dave_uid
2072            = UserID::from("<dave@example.org>");
2073        // Certified by: 28C108707090FCDFF630D1E141FB02F0E397D55E
2074
2075        let ed_fpr: Fingerprint =
2076            "296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB"
2077           .parse().expect("valid fingerprint");
2078        let ed_uid
2079            = UserID::from("<ed@example.org>");
2080        // Certified by: 0C131F8959F45D08B6136FDAAD2E16A26F73D48E
2081
2082        let frank_fpr: Fingerprint =
2083            "A72AA1B7D9D8CB04D988F1520A404E37A7766608"
2084           .parse().expect("valid fingerprint");
2085        let frank_uid
2086            = UserID::from("<frank@example.org>");
2087        // Certified by: 9FB1D2F41AB5C478378E728C8DD5A5A434EEAAB8
2088        // Certified by: 296935FAE420CCCF3AEDCEC9232BFF0AE9A7E5DB
2089
2090        let certs: Vec<Cert> = CertParser::from_bytes(
2091            &crate::testdata::data("multiple-userids-3.pgp"))?
2092            .map(|c| c.expect("Valid certificate"))
2093            .collect();
2094        let store = CertStore::from_cert_refs(
2095            certs.iter().map(|c| c.into()), p, None)?;
2096        let n = NetworkBuilder::rootless(&store).build();
2097
2098        eprintln!("{:?}", n);
2099
2100        let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2101
2102        /// Tests.
2103
2104        sp(&n, &frank_fpr, &frank_uid.clone(),
2105           &[
2106               (20, &[ &alice_fpr, &bob_fpr, &carol_fpr, &frank_fpr ][..]),
2107               (10, &[ &alice_fpr, &bob_fpr, &dave_fpr, &ed_fpr, &frank_fpr ][..]),
2108           ][..],
2109           None);
2110
2111        Ok(())
2112    }
2113
2114    #[test]
2115    #[allow(unused)]
2116    fn certification_liveness() -> Result<()> {
2117        let p = &StandardPolicy::new();
2118
2119        let alice_fpr: Fingerprint =
2120            "77C077250C26357E5E64A58A41426350B1D7F738"
2121           .parse().expect("valid fingerprint");
2122        let alice_uid
2123            = UserID::from("<alice@example.org>");
2124
2125        let bob_fpr: Fingerprint =
2126            "840891562819D3A108C4DA1BB31438DE34F8CF69"
2127           .parse().expect("valid fingerprint");
2128        let bob_uid
2129            = UserID::from("<bob@example.org>");
2130        // Certified by: 77C077250C26357E5E64A58A41426350B1D7F738
2131        // Certified by: 77C077250C26357E5E64A58A41426350B1D7F738
2132
2133        let carol_fpr: Fingerprint =
2134            "E8BB154D000C17AC87291D7271553C836973FE01"
2135           .parse().expect("valid fingerprint");
2136        let carol_uid
2137            = UserID::from("<carol@example.org>");
2138        // Certified by: 840891562819D3A108C4DA1BB31438DE34F8CF69
2139        // Certified by: 840891562819D3A108C4DA1BB31438DE34F8CF69
2140
2141        let certs: Vec<Cert> = CertParser::from_bytes(
2142            &crate::testdata::data("certification-liveness.pgp"))?
2143            .map(|c| c.expect("Valid certificate"))
2144            .collect();
2145
2146        // $ date '+%s' -d 20200202
2147        // 1580598000
2148        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
2149        // $ date '+%s' -d 20200302
2150        // 1583103600
2151        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
2152        // $ date '+%s' -d 20200402
2153        // 1585778400
2154        let t3 = time::UNIX_EPOCH + time::Duration::new(1585778400, 0);
2155
2156        for (i, t) in [t1, t2, t3].iter().enumerate() {
2157            eprintln!("\n\nTrying at t{}", i + 1);
2158
2159            let store = CertStore::from_cert_refs(
2160                certs.iter().map(|c| c.into()), p, *t)?;
2161            let n = NetworkBuilder::rootless(&store).build();
2162
2163            eprintln!("{:?}", n);
2164
2165            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2166
2167            sp(&n, &carol_fpr, &carol_uid.clone(),
2168               &[
2169                   (match i + 1 {
2170                       1 => 60,
2171                       2 => 120,
2172                       3 => 60,
2173                       _ => unreachable!(),
2174                   },
2175                   &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]),
2176               ][..],
2177               None);
2178        }
2179
2180        Ok(())
2181    }
2182
2183    #[test]
2184    #[allow(unused)]
2185    fn cert_revoked_soft() -> Result<()> {
2186        let p = &StandardPolicy::new();
2187
2188        let alice_fpr: Fingerprint =
2189            "66037F98B444BBAFDFE98E871738DFAB86878262"
2190           .parse().expect("valid fingerprint");
2191        let alice_uid
2192            = UserID::from("<alice@example.org>");
2193
2194        let bob_fpr: Fingerprint =
2195            "4CD8737F76C2B897C4F058DBF28C47540FA2C3B3"
2196           .parse().expect("valid fingerprint");
2197        let bob_uid
2198            = UserID::from("<bob@example.org>");
2199        // Certified by: 66037F98B444BBAFDFE98E871738DFAB86878262
2200
2201        let carol_fpr: Fingerprint =
2202            "AB4E3F8EE8BBD3459754D75ACE570F9B8C7DC75D"
2203           .parse().expect("valid fingerprint");
2204        let carol_uid
2205            = UserID::from("<carol@example.org>");
2206        // Certified by: 66037F98B444BBAFDFE98E871738DFAB86878262
2207
2208        let dave_fpr: Fingerprint =
2209            "DF6A440ED9DE723B0EBC7F50E24FBB1B9FADC999"
2210           .parse().expect("valid fingerprint");
2211        let dave_uid
2212            = UserID::from("<dave@example.org>");
2213        // Certified by: 4CD8737F76C2B897C4F058DBF28C47540FA2C3B3
2214        // Certified by: AB4E3F8EE8BBD3459754D75ACE570F9B8C7DC75D
2215        // Certified by: 4CD8737F76C2B897C4F058DBF28C47540FA2C3B3
2216
2217        let certs: Vec<Cert> = CertParser::from_bytes(
2218            &crate::testdata::data("cert-revoked-soft.pgp"))?
2219            .map(|c| c.expect("no errors"))
2220            .collect();
2221
2222        // $ date '+%s' -d 20200202
2223        // 1580598000
2224        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
2225        // $ date '+%s' -d 20200302
2226        // 1583103600
2227        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
2228        // $ date '+%s' -d 20200402
2229        // 1585778400
2230        let t3 = time::UNIX_EPOCH + time::Duration::new(1585778400, 0);
2231
2232        // At t1, soft revocations are in the future so certifications
2233        // are still valid.
2234        //
2235        // At t2, B is soft revoked so existing certifications are
2236        // still valid, but we can no longer authenticate B.
2237        //
2238        // At t3, A recertifies B and B recertifies D.  These
2239        // certifications should be ignored as they are made after B
2240        // was revoked.
2241        for (i, t) in [t1, t2, t3].iter().enumerate() {
2242            eprintln!("\n\nTrying at t{}", i + 1);
2243
2244            let store = CertStore::from_cert_refs(
2245                certs.iter().map(|c| c.into()), p, *t)?;
2246            let n = NetworkBuilder::rootless(&store).build();
2247
2248            eprintln!("{:?}", n);
2249
2250            // Consider just the code path where B is the issuer.
2251            //
2252            // Covers scenarios #1 at t1, #3 at t2 and t3
2253            let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
2254            sp(&n, &dave_fpr, &dave_uid.clone(),
2255               &[
2256                   (60, &[ &bob_fpr, &dave_fpr ][..]),
2257               ][..],
2258               None);
2259
2260            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2261
2262            // Consider just the code path where B is the target.
2263            //
2264            // Covers scenarios #2 at t1, #4 at t2 and t3.
2265            if i + 1 == 1 {
2266                sp(&n, &bob_fpr, &bob_uid.clone(),
2267                   &[
2268                       (90, &[ &alice_fpr, &bob_fpr ][..]),
2269                   ][..],
2270                   None);
2271            } else {
2272                sp(&n, &bob_fpr, &bob_uid.clone(),
2273                   &[][..],
2274                   None);
2275            }
2276
2277            // Consider the code path where B is both an issuer and a
2278            // target.
2279            //
2280            // Covers scenarios #1 & #2 at t1, #3 & #4 at t2 and t3.
2281            sp(&n, &dave_fpr, &dave_uid.clone(),
2282               &[
2283                   (60, &[ &alice_fpr, &bob_fpr, &dave_fpr ][..]),
2284                   (30, &[ &alice_fpr, &carol_fpr, &dave_fpr ][..]),
2285               ][..],
2286               None);
2287        }
2288
2289        Ok(())
2290    }
2291
2292    #[test]
2293    #[allow(unused)]
2294    fn cert_revoked_hard() -> Result<()> {
2295        let p = &StandardPolicy::new();
2296
2297        let alice_fpr: Fingerprint =
2298            "219AAB661C8AAF4526DBC31AA751A7A0532863BA"
2299           .parse().expect("valid fingerprint");
2300        let alice_uid
2301            = UserID::from("<alice@example.org>");
2302
2303        let bob_fpr: Fingerprint =
2304            "90E02BFB03FAA04714D1D3D87543157EF3B12BE9"
2305           .parse().expect("valid fingerprint");
2306        let bob_uid
2307            = UserID::from("<bob@example.org>");
2308        // Certified by: 219AAB661C8AAF4526DBC31AA751A7A0532863BA
2309        // Certified by: 219AAB661C8AAF4526DBC31AA751A7A0532863BA
2310
2311        let carol_fpr: Fingerprint =
2312            "BF680710128E6BCCB2268154569F5F6BFB95C544"
2313           .parse().expect("valid fingerprint");
2314        let carol_uid
2315            = UserID::from("<carol@example.org>");
2316        // Certified by: 219AAB661C8AAF4526DBC31AA751A7A0532863BA
2317
2318        let dave_fpr: Fingerprint =
2319            "46945292F8F643F0573AF71183F9C1A4759A16D6"
2320           .parse().expect("valid fingerprint");
2321        let dave_uid
2322            = UserID::from("<dave@example.org>");
2323        // Certified by: 90E02BFB03FAA04714D1D3D87543157EF3B12BE9
2324        // Certified by: BF680710128E6BCCB2268154569F5F6BFB95C544
2325        // Certified by: 90E02BFB03FAA04714D1D3D87543157EF3B12BE9
2326
2327
2328        let certs: Vec<Cert> = CertParser::from_bytes(
2329            &crate::testdata::data("cert-revoked-hard.pgp"))?
2330            .map(|c| c.expect("no errors"))
2331            .collect();
2332
2333        // $ date '+%s' -d 20200202
2334        // 1580598000
2335        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
2336        // $ date '+%s' -d 20200302
2337        // 1583103600
2338        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
2339        // $ date '+%s' -d 20200402
2340        // 1585778400
2341        let t3 = time::UNIX_EPOCH + time::Duration::new(1585778400, 0);
2342
2343        // At t1, B is hard revoked in the future so all
2344        // certifications are invalid.
2345        //
2346        // At t2, B is hard revoked so all certifications are invalid.
2347        //
2348        // At t3, A recertifies B and B recertifies D.  These
2349        // certifications should also be ignored.
2350        for (i, t) in [t1, t2, t3].iter().enumerate() {
2351            eprintln!("\n\nTrying at t{}", i + 1);
2352
2353            let store = CertStore::from_cert_refs(
2354                certs.iter().map(|c| c.into()), p, *t)?;
2355            let n = NetworkBuilder::rootless(&store).build();
2356
2357            eprintln!("{:?}", n);
2358
2359            // Consider just the code path where B is the issuer.
2360            //
2361            // Covers scenarios #5 at t1, #7 at t2 and t3
2362            let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
2363            sp(&n, &dave_fpr, &dave_uid.clone(),
2364               &[][..],
2365               None);
2366
2367            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2368
2369            // Consider just the code path where B is the target.
2370            //
2371            // Covers scenarios #6 at t1, #8 at t2 and t3.
2372            sp(&n, &bob_fpr, &bob_uid.clone(),
2373               &[][..],
2374               None);
2375
2376            // Consider the code path where B is both an issuer and a
2377            // target.
2378            //
2379            // Covers scenarios #5 & #6 at t1, #7 & #8 at t2 and t3.
2380            sp(&n, &dave_fpr, &dave_uid.clone(),
2381               &[
2382                   (30, &[ &alice_fpr, &carol_fpr, &dave_fpr ][..]),
2383               ][..],
2384               None);
2385        }
2386
2387        Ok(())
2388    }
2389
2390    #[test]
2391    #[allow(unused)]
2392    fn cert_expired() -> Result<()> {
2393        let p = &StandardPolicy::new();
2394
2395        let alice_fpr: Fingerprint =
2396            "1FA62523FB7C06E71EEFB82BB5159F3FC3EB3AC9"
2397           .parse().expect("valid fingerprint");
2398        let alice_uid
2399            = UserID::from("<alice@example.org>");
2400
2401        let bob_fpr: Fingerprint =
2402            "B166B31AE5F95600B3F7184FE74C6CE62821686F"
2403           .parse().expect("valid fingerprint");
2404        let bob_uid
2405            = UserID::from("<bob@example.org>");
2406        // Certified by: 1FA62523FB7C06E71EEFB82BB5159F3FC3EB3AC9
2407
2408        let carol_fpr: Fingerprint =
2409            "81CD118AC5BD9156DC113772626222D76ACDFFCF"
2410           .parse().expect("valid fingerprint");
2411        let carol_uid
2412            = UserID::from("<carol@example.org>");
2413        // Certified by: B166B31AE5F95600B3F7184FE74C6CE62821686F
2414
2415        let certs: Vec<Cert> = CertParser::from_bytes(
2416            &crate::testdata::data("cert-expired.pgp"))?
2417            .map(|c| c.expect("Valid certificate"))
2418            .collect();
2419
2420        // $ date '+%s' -d 20200202
2421        // 1580598000
2422        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
2423        // $ date '+%s' -d 20200302
2424        // 1583103600
2425        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
2426        // $ date '+%s' -d 20200402
2427        // 1585778400
2428        let t3 = time::UNIX_EPOCH + time::Duration::new(1585778400, 0);
2429
2430        for (i, t) in [t1, t2, t3].iter().enumerate() {
2431            eprintln!("\n\nTrying at t{}", i + 1);
2432
2433            let store = CertStore::from_cert_refs(
2434                certs.iter().map(|c| c.into()), p, *t)?;
2435            let n = NetworkBuilder::rootless(&store).build();
2436
2437            eprintln!("{:?}", n);
2438
2439            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2440
2441            // Bob as target.  (Once Bob has expired it can be used as
2442            // a trusted introducer for prior certifications, but
2443            // bindings cannot be authenticated.)
2444            if i + 1 == 1 {
2445                sp(&n, &bob_fpr, &bob_uid.clone(),
2446                   &[ (60, &[ &alice_fpr, &bob_fpr ][..]) ][..],
2447                   None);
2448            } else {
2449                sp(&n, &bob_fpr, &bob_uid.clone(),
2450                   &[][..],
2451                   None);
2452            }
2453
2454            // Bob in the middle.
2455            sp(&n, &carol_fpr, &carol_uid.clone(),
2456               & [ (60, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
2457               None);
2458
2459            // Bob as root.
2460            let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
2461            sp(&n, &carol_fpr, &carol_uid.clone(),
2462               & [ (60, &[ &bob_fpr, &carol_fpr ][..]) ][..],
2463               None);
2464
2465            // Bob's self signature.
2466            if i + 1 == 1 {
2467                sp(&n, &bob_fpr, &bob_uid.clone(),
2468                   & [ (120, &[ &bob_fpr ][..]) ][..],
2469                   None);
2470            } else {
2471                sp(&n, &bob_fpr, &bob_uid.clone(),
2472                   &[][..],
2473                   None);
2474            }
2475        }
2476
2477        Ok(())
2478    }
2479
2480    #[test]
2481    #[allow(unused)]
2482    fn userid_revoked() -> Result<()> {
2483        let p = &StandardPolicy::new();
2484
2485        let alice_fpr: Fingerprint =
2486            "01672BB67E4B4047E5A4EC0A731CEA092C465FC8"
2487           .parse().expect("valid fingerprint");
2488        let alice_uid
2489            = UserID::from("<alice@example.org>");
2490
2491        let bob_fpr: Fingerprint =
2492            "EA479A77CD074458EAFE56B4861BF42FF490C581"
2493           .parse().expect("valid fingerprint");
2494        let bob_uid
2495            = UserID::from("<bob@example.org>");
2496        // Certified by: 01672BB67E4B4047E5A4EC0A731CEA092C465FC8
2497        // Certified by: 01672BB67E4B4047E5A4EC0A731CEA092C465FC8
2498
2499        let carol_fpr: Fingerprint =
2500            "212873BB9C4CC49F8E5A6FEA78BC5397470BA7F0"
2501           .parse().expect("valid fingerprint");
2502        let carol_uid
2503            = UserID::from("<carol@example.org>");
2504        // Certified by: EA479A77CD074458EAFE56B4861BF42FF490C581
2505        // Certified by: EA479A77CD074458EAFE56B4861BF42FF490C581
2506
2507        let certs: Vec<Cert> = CertParser::from_bytes(
2508            &crate::testdata::data("userid-revoked.pgp"))?
2509            .map(|c| c.expect("Valid certificate"))
2510            .collect();
2511
2512        // $ date '+%s' -d 20200202
2513        // 1580598000
2514        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
2515        // $ date '+%s' -d 20200302
2516        // 1583103600
2517        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
2518        // $ date '+%s' -d 20200402
2519        // 1585778400
2520        let t3 = time::UNIX_EPOCH + time::Duration::new(1585778400, 0);
2521
2522        // At t2, B is soft revoked so all future certifications are
2523        // invalid.
2524        for (i, t) in [t1, t2, t3].iter().enumerate() {
2525            eprintln!("\n\nTrying at t{}", i + 1);
2526
2527            let store = CertStore::from_cert_refs(
2528                certs.iter().map(|c| c.into()), p, *t)?;
2529            let n = NetworkBuilder::rootless(&store).build();
2530
2531            eprintln!("{:?}", n);
2532
2533            // Revoked User ID on the root.
2534            let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
2535            if i + 1 == 1 {
2536                sp(&n, &bob_fpr, &bob_uid.clone(),
2537                   &[ (120, &[ &bob_fpr ][..]), ][..],
2538                   None);
2539            } else {
2540                sp(&n, &bob_fpr, &bob_uid.clone(),
2541                   &[][..],
2542                   None);
2543            }
2544
2545            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2546
2547            if i + 1 == 1 {
2548                sp(&n, &bob_fpr, &bob_uid.clone(),
2549                   &[ (60, &[ &alice_fpr, &bob_fpr ][..]), ][..],
2550                   None);
2551            } else {
2552                // Can't authenticate binding with a revoked User ID.
2553                sp(&n, &bob_fpr, &bob_uid.clone(),
2554                   &[][..],
2555                   None);
2556            }
2557
2558            // Can use a delegation even if the certification that it
2559            // is a part of has had its User ID revoked.
2560            if i + 1 < 3 {
2561                sp(&n, &carol_fpr, &carol_uid.clone(),
2562                   &[
2563                       (60, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]),
2564                   ][..],
2565                   None);
2566            } else {
2567                sp(&n, &carol_fpr, &carol_uid.clone(),
2568                   &[
2569                       (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]),
2570                   ][..],
2571                   None);
2572            }
2573        }
2574
2575        Ok(())
2576    }
2577
2578    #[test]
2579    #[allow(unused)]
2580    fn certifications_revoked() -> Result<()> {
2581        let p = &StandardPolicy::new();
2582
2583        let alice_fpr: Fingerprint =
2584            "817C2BE18D9FF48FFE58FF39B699FC21AD92EFDC"
2585           .parse().expect("valid fingerprint");
2586        let alice_uid
2587            = UserID::from("<alice@example.org>");
2588
2589        let bob_fpr: Fingerprint =
2590            "4258ACF6C3C8FCE130D6EBAB0CC5158AEA25F24A"
2591           .parse().expect("valid fingerprint");
2592        let bob_uid
2593            = UserID::from("<bob@example.org>");
2594        // Certified by: 817C2BE18D9FF48FFE58FF39B699FC21AD92EFDC
2595        // Certified by: 817C2BE18D9FF48FFE58FF39B699FC21AD92EFDC
2596
2597        let carol_fpr: Fingerprint =
2598            "36766215FFD2FA000B0804BFF54577580DDC1741"
2599           .parse().expect("valid fingerprint");
2600        let carol_uid
2601            = UserID::from("<carol@example.org>");
2602        // Certified by: 4258ACF6C3C8FCE130D6EBAB0CC5158AEA25F24A
2603
2604        let certs: Vec<Cert> = CertParser::from_bytes(
2605            &crate::testdata::data("certification-revoked.pgp"))?
2606            .map(|c| c.expect("Valid certificate"))
2607            .collect();
2608
2609        /// Tests.
2610
2611        // $ date '+%s' -d 20200202
2612        // 1580598000
2613        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
2614        // $ date '+%s' -d 20200302
2615        // 1583103600
2616        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
2617        // $ date '+%s' -d 20200402
2618        // 1585778400
2619        let t3 = time::UNIX_EPOCH + time::Duration::new(1585778400, 0);
2620
2621        for (i, t) in [t1, t2, t3].iter().enumerate() {
2622            eprintln!("\n\nTrying at t{}", i + 1);
2623
2624            let store = CertStore::from_cert_refs(
2625                certs.iter().map(|c| c.into()), p, *t)?;
2626            let n = NetworkBuilder::rootless(&store).build();
2627
2628            eprintln!("{:?}", n);
2629
2630            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
2631
2632            sp(&n, &alice_fpr, &alice_uid.clone(),
2633               &[ (120, &[&alice_fpr][..]), ][..],
2634               None);
2635
2636            match i + 1 {
2637                1 => {
2638                    sp(&n, &bob_fpr, &bob_uid.clone(),
2639                       &[ (60, &[&alice_fpr, &bob_fpr][..]), ][..],
2640                       None);
2641                    sp(&n, &carol_fpr, &carol_uid.clone(),
2642                       &[ (60, &[&alice_fpr, &bob_fpr, &carol_fpr][..]), ][..],
2643                       None);
2644                }
2645                2 => {
2646                    sp(&n, &bob_fpr, &bob_uid.clone(),
2647                       &[][..],
2648                       None);
2649                    sp(&n, &carol_fpr, &carol_uid.clone(),
2650                       &[][..],
2651                       None);
2652                }
2653                3 => {
2654                    sp(&n, &bob_fpr, &bob_uid.clone(),
2655                       &[ (120, &[&alice_fpr, &bob_fpr][..]), ][..],
2656                       None);
2657                    sp(&n, &carol_fpr, &carol_uid.clone(),
2658                       &[ (120, &[&alice_fpr, &bob_fpr, &carol_fpr][..]), ][..],
2659                       None);
2660                }
2661                _ => unreachable!(),
2662            }
2663
2664            // Alice, not Bob, revokes Bob's user id.  So when Bob is
2665            // the root, the self signature should still be good.
2666            let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
2667            sp(&n, &bob_fpr, &bob_uid.clone(),
2668               &[ (120, &[&bob_fpr][..]), ][..],
2669               None);
2670        }
2671
2672        Ok(())
2673    }
2674
2675    #[test]
2676    #[allow(unused)]
2677    fn infinity_and_beyond() -> Result<()> {
2678        let p = &StandardPolicy::new();
2679
2680        let u1_fpr: Fingerprint =
2681            "B557862780A97676CC32F4BB1491A9C2BDE6F1DC"
2682           .parse().expect("valid fingerprint");
2683        let u1_uid
2684            = UserID::from("<u1@example.org>");
2685
2686        let u260_fpr: Fingerprint =
2687            "B69A678AA242FA4F0BBF12205C0608799B0E3C51"
2688           .parse().expect("valid fingerprint");
2689        let u260_uid
2690            = UserID::from("<u260@example.org>");
2691
2692        let u254_fpr: Fingerprint =
2693            "AF097DA4DB5C0E2116EF583B25A6B381B621C082"
2694           .parse().expect("valid fingerprint");
2695        let u254_uid
2696            = UserID::from("<u254@example.org>");
2697
2698        let fprs: [&Fingerprint; 260] = [
2699            &"B557862780A97676CC32F4BB1491A9C2BDE6F1DC".parse().unwrap(),
2700            &"0618F850B6D0C48DBF406BBFAB3DAED809A35F78".parse().unwrap(),
2701            &"70B0C5FEFFE6B55F2CEE85455621246D16D6785E".parse().unwrap(),
2702            &"EC4475DE5BD76EA7DD4798777E9C990C249738B1".parse().unwrap(),
2703            &"FB00C7044A9DD164243CEC460B48AA8ADD29A129".parse().unwrap(),
2704            &"7DCB823AB1B33C6D22FC84AC3026DA74AEEB4A6E".parse().unwrap(),
2705            &"0058DCF7A7C6C4360DE9095DB6F33843D961E818".parse().unwrap(),
2706            &"D0BF1856B95A62763DE49088CE6FF96D17E0EAF0".parse().unwrap(),
2707            &"7F945244A20A74E1BA50BE73E917BC24D2D53F79".parse().unwrap(),
2708            &"12C92685CA2A867B93FD79762B2D56CF0B94304E".parse().unwrap(),
2709            &"02B1DB86B6869BCF92C0F74312D1A5F22E128F18".parse().unwrap(),
2710            &"9C8245F2DD06E4A2FE21FB1643A9663DDF7DF168".parse().unwrap(),
2711            &"CB7C6D3FCBB8DA0B3D7F6EC0DD193A96517579DC".parse().unwrap(),
2712            &"66D0F95325D4A02A36C14265FD247584CCA3C8BA".parse().unwrap(),
2713            &"291ABB75D735BC5B625E221B021152DF0CA1F86A".parse().unwrap(),
2714            &"27DF659AEE573E30D3A65B6E43474D9A4CA64DE3".parse().unwrap(),
2715            &"591492CAF51C06516278723EAFB9AF2643B89A3A".parse().unwrap(),
2716            &"20B481FFB7B72F6781BA49806C8E35B5C79A3E41".parse().unwrap(),
2717            &"270E3D9E87CA0999D422CD22F905BF87E8F60A36".parse().unwrap(),
2718            &"192124BD42BA6BF54A8820FB94B6B70D818241E3".parse().unwrap(),
2719            &"07C1D93539328F97517C59D27ABC3071DB73A790".parse().unwrap(),
2720            &"A915D1BA3F066E989B965ADFA27CC8D161C0F48A".parse().unwrap(),
2721            &"D968AFB7EAF13E04BB71D96100CC514119C8303E".parse().unwrap(),
2722            &"A62F988F2896A0286F92F8B8201E7737D11D7039".parse().unwrap(),
2723            &"9BF8933FCA5306F567F5F5750CE3375AFA9398A1".parse().unwrap(),
2724            &"5EC7400A739E579B704E618809345EF1045B304A".parse().unwrap(),
2725            &"2C7B74D1388CE0F2C4002CE41EAD11DBB281472A".parse().unwrap(),
2726            &"C18D79710A68696E972B0F321E6DE596CD08B4FD".parse().unwrap(),
2727            &"C1B1150980254353538D9CC5A91187FE2DBD51FF".parse().unwrap(),
2728            &"4FD94C288F39C4633FBBD120BF1A1C6B6789F983".parse().unwrap(),
2729            &"DE70A745F098EBCC45B4A3B25D0195EC3C6E0D65".parse().unwrap(),
2730            &"44350591F20A4069F131156283AABF91FE4AE5EF".parse().unwrap(),
2731            &"76E9D213C5F67F2DBE410F57DF3F9BB9622AAFC7".parse().unwrap(),
2732            &"A48F536C34D4A493CD233870C05B675B873B139D".parse().unwrap(),
2733            &"7C3FEDFAB082D236A9181B8E2B6483A582756C6E".parse().unwrap(),
2734            &"0FDFAF64606B6C72BF1C940D24F80C95D5B8310E".parse().unwrap(),
2735            &"6B5A25C2DD40AE58272FB17D15C33EF13B9D7FE8".parse().unwrap(),
2736            &"3814E465DDDCDB7F352E513D9C34D38E08A4360A".parse().unwrap(),
2737            &"2BF243991E5B6444861FC662E93888456D33F149".parse().unwrap(),
2738            &"124760101EF948B0E9EC24D9326FFEBD505BE4D3".parse().unwrap(),
2739            &"074E083627D1ED618486FB18865EA7123912BE53".parse().unwrap(),
2740            &"955B6A60E5EA85BADD68B1E08AF3E45D3AB93DE9".parse().unwrap(),
2741            &"857B9C8DCF9EBD72556237A40E652DDF8101E2D0".parse().unwrap(),
2742            &"FA11A49DA2E22F686471A4343E6A36C53F7C2155".parse().unwrap(),
2743            &"90DF0E04097EBFD295E05B9F40BE700A2E8D0995".parse().unwrap(),
2744            &"90BA919C17ED4252F8F0ED327192D79A112A0CE6".parse().unwrap(),
2745            &"3762EB478F47FEA848ADA9E1611C433D28D84071".parse().unwrap(),
2746            &"E960CD893E6CF7F41E752BEF15ED83ECDF49463C".parse().unwrap(),
2747            &"B1256D987F2789601FC5D8FAF268AB5F6AB44782".parse().unwrap(),
2748            &"5EE4B68A4828F5C15DD87114DC4A8509993DCFAB".parse().unwrap(),
2749            &"5C472E1C68A9A587C2AF9F00BC59B13A9918BBC1".parse().unwrap(),
2750            &"5320428600FCDB9A3AA32DA3E14D0128D7C372EC".parse().unwrap(),
2751            &"41958AAE8E1EED80B680F4DCD5ABFA33A1DB1C23".parse().unwrap(),
2752            &"7F4DFF6FC276995C94C2BF92146B7BED38209DB9".parse().unwrap(),
2753            &"6DE33C3735906B7E69AE593A0CD724AF410A89CE".parse().unwrap(),
2754            &"70F56B5B0EA57CB9ACDEB08B5333D900488A16B1".parse().unwrap(),
2755            &"02C9977BFF7BA0295AF671AA31894E2CD88A0F0D".parse().unwrap(),
2756            &"81FF106638ACE77B0C1039D5E69BCC93690A6B8D".parse().unwrap(),
2757            &"136368A84C7E56A86515ACC6DCD0744ABE10225D".parse().unwrap(),
2758            &"2B5E1D94813CED1CD63A3F28FEF343EA790E2333".parse().unwrap(),
2759            &"680ADF1182D00512D298417C6DBFC9084BFDB79D".parse().unwrap(),
2760            &"17DFBFB2149AB4A82B1DE5E5AE63FBDCE6874162".parse().unwrap(),
2761            &"2FD6D0F680B55F9AF128DBCBA4C71E44F433B728".parse().unwrap(),
2762            &"26551C85DBFDDEA97B7E7A0068DBDE9E792A7A49".parse().unwrap(),
2763            &"341BB68A3695B3D9EE307D7794317B145CEFCB60".parse().unwrap(),
2764            &"2E65A5B2F70D16D5D4D0664D360AE9BD58C555C1".parse().unwrap(),
2765            &"DEE7D3162919AC8AC9592051BFACF193B344DEF1".parse().unwrap(),
2766            &"2A8CE469DD783B95C92A6F3294A5A609AA679F71".parse().unwrap(),
2767            &"8A9FE07B40482C5559A6770B57B79188B52BD346".parse().unwrap(),
2768            &"6993EE3E5C4653A03EACBEC25604E4A55B4F75AB".parse().unwrap(),
2769            &"66DF2690FEAC606C285AA4D986376ACD1964BE48".parse().unwrap(),
2770            &"29FD7B1C6B29663CFA64306670E67F3E7F6FBCD4".parse().unwrap(),
2771            &"2C6E7C99DE5F5922E05D11D235C2E562CC528E76".parse().unwrap(),
2772            &"88E99AC4D5CB6ACF3CD396D5D6AA9961B4F938AB".parse().unwrap(),
2773            &"4471A85059215D231D47B1D4A109C3F0B6BDB258".parse().unwrap(),
2774            &"2C755244C6B83CAA7E48BD234C7FDB8645611B3B".parse().unwrap(),
2775            &"9C015FEBD3D19A81716E7700052058B47F889611".parse().unwrap(),
2776            &"9014E514D677C2ED19D93329C1485FE55F1C72D6".parse().unwrap(),
2777            &"343F2C6F9DB8F9EE4E59F5C0886BAE56FA55CE26".parse().unwrap(),
2778            &"13C37CE8ED0ACC92CF61808755241D6DA1633FA4".parse().unwrap(),
2779            &"ED5C07A820DCB2AA6DAFDE9C8562765D88A4BB36".parse().unwrap(),
2780            &"21655669D7B36A2EB5007B31442FCE197ADCC8D8".parse().unwrap(),
2781            &"CD220E58B30D2D1CBBC5B921555C92A70B303860".parse().unwrap(),
2782            &"5FF5C8CBD8D670565B300519887E3ED2F9E0DDA9".parse().unwrap(),
2783            &"B47FF2EF9DEB08C7FC55532C746F0F2DB723C462".parse().unwrap(),
2784            &"F8F8F30931EEB93C2FDE9363F9EE328402F33860".parse().unwrap(),
2785            &"3714D9CB0A8A0B4EE695B21AB052CAE69A2A7689".parse().unwrap(),
2786            &"FF093E66CCFB8804193115058643E0CB52C5A793".parse().unwrap(),
2787            &"0A5553209858B36F3EA0EFA463FD6758FF116167".parse().unwrap(),
2788            &"D9C06C9D100813BEBD35427DF65F7634EB2EAD6A".parse().unwrap(),
2789            &"05CA2D388297E826B9C3B431A8B15D93895257F9".parse().unwrap(),
2790            &"BF79DD51D462180014D2AD71D2462BE4CF36F625".parse().unwrap(),
2791            &"FC0DE4AD683BE64F47E8642F7472D7BB781E5C76".parse().unwrap(),
2792            &"F1FE09936F39A4E7A907D909CDFA4993BE4124AF".parse().unwrap(),
2793            &"465CD9AD11B5003A48BB28118DB2CEBD29D4F603".parse().unwrap(),
2794            &"9DF99BDB7078BE13CE3F66D97F212BF669F995C6".parse().unwrap(),
2795            &"57071A60EFBBFFA6DDCE7796F14A1B2C681A8A83".parse().unwrap(),
2796            &"8AB11E4F18DC57F2BA400B8D7B5FD8990C1CCAC5".parse().unwrap(),
2797            &"286EC5D4E5D1D136E54C996FE2D9E350B7CF3D8A".parse().unwrap(),
2798            &"AF87AF1183FB3E9370D509CE4E255380D5F3A8D5".parse().unwrap(),
2799            &"036F0956E3436BB10D030C89241EB37A3E931678".parse().unwrap(),
2800            &"33C2757572312304682BDD62C46C67D099B92680".parse().unwrap(),
2801            &"47A458ECE5784E7AF11C2286AA75FA9B8401E257".parse().unwrap(),
2802            &"43950C8B0B46693E9E48676637A98A31CF4B62AD".parse().unwrap(),
2803            &"A881411005DCCA6AF01331438783D3432031442F".parse().unwrap(),
2804            &"AA96AB4A6A98A839676621E66E756674E8DE55F3".parse().unwrap(),
2805            &"6844B0D8AB1D74A5766311157F652BC182F0875D".parse().unwrap(),
2806            &"B6F83FFF8B788418D48C11FA084D0F3AC9A2AECD".parse().unwrap(),
2807            &"99B269CFF458C780108B370C7A3F523A4DD62521".parse().unwrap(),
2808            &"48ADBA117B6D38703248D7AE72FB58B9E9798B7E".parse().unwrap(),
2809            &"FBC503FCBE4143C984E88358E700E23D4F573CCF".parse().unwrap(),
2810            &"E249A634759A417A040615736E200525AAF6F629".parse().unwrap(),
2811            &"BC782C4357D9E72075AF3DBF2C2FCAB09C09C252".parse().unwrap(),
2812            &"7B47E68EFB03A0C8346BD80E4A2FA75B6488D6D3".parse().unwrap(),
2813            &"DC2807A9E1CCD83B797A1EB2829D1F4641E0DB9B".parse().unwrap(),
2814            &"33C7585C640E74974790F349F64B2668DF09DE8E".parse().unwrap(),
2815            &"C766141BA6C7998C7EE40DE116FB427F2C57657F".parse().unwrap(),
2816            &"D0DF7D293426D9451E9EE0FD03A4D8196D10976D".parse().unwrap(),
2817            &"D56E5DB01CFAAD99697B33163B81D229170F58B4".parse().unwrap(),
2818            &"97D592FDE6199E3A4F6B437F40B34142AA67397B".parse().unwrap(),
2819            &"8C19F12A8386D0EF3FC0AFD28D7FE8D90F070EFB".parse().unwrap(),
2820            &"5B87566BAA2C8EC78C7D44594F21D5ABA36767F2".parse().unwrap(),
2821            &"53AB6BCCE1111DCD151E66625F52509FC67F4076".parse().unwrap(),
2822            &"318DA1A8A8E92698EAAC0AB468406FF3D0B6733A".parse().unwrap(),
2823            &"350068CCCD295D7EB80C6A97060FCBD15175ADB2".parse().unwrap(),
2824            &"3A7DF039CCCA3B3C9286B01619D8EA302427C910".parse().unwrap(),
2825            &"3C964F3E9C57330753EE5923B49FC01974400307".parse().unwrap(),
2826            &"4E9E5E2E1A868706DAADFD5A362C66828E5E4621".parse().unwrap(),
2827            &"36328DA9EAC85DB46843FA168A4AA6C4B47ADE22".parse().unwrap(),
2828            &"0AB20633A6D636B80337EFE3403702D89A3CD852".parse().unwrap(),
2829            &"8CDF07D3CEA5ED1B72ECD8869CA0A447943C1F3B".parse().unwrap(),
2830            &"E052363BDCA7BB374570774F9EE1EA2E8BF88026".parse().unwrap(),
2831            &"6603EA823BC641A465D8E5C45EDAD32360EDFC6A".parse().unwrap(),
2832            &"7D2E0E09E14B5BAB084A268786B0C6357215757B".parse().unwrap(),
2833            &"44F5446DBE64118D55D007453C6EF4840B47CD82".parse().unwrap(),
2834            &"419FA3D74A917B54F53AF2157B81A4A67CBA27F0".parse().unwrap(),
2835            &"36EB37E159817A86D0D4F506A3DDF317DFEDF32F".parse().unwrap(),
2836            &"9F5918BE6A7898670283859B05280E0DDA09EC95".parse().unwrap(),
2837            &"24EFDB2253318E11B73B617C6A7C5DC8792A2A55".parse().unwrap(),
2838            &"4AF832B3208DB3DD126C21E3CAF4AA3126156F8B".parse().unwrap(),
2839            &"E00EE6E5D079CA81E37F964EAD799F4D59738D54".parse().unwrap(),
2840            &"5A962B09EF649F4267DFDAE046B2F28E5134573F".parse().unwrap(),
2841            &"BAB9FB2EC409E68165AEF78D58BB96EB511C41B2".parse().unwrap(),
2842            &"ADD6E345227F27489E1E8AA7E0CD788437CC47BF".parse().unwrap(),
2843            &"BCD1FB9A7524E6B2D1ADB920653E81204C30A119".parse().unwrap(),
2844            &"17DE4392A165DC82CF50E879B5CB17B550CC0DE2".parse().unwrap(),
2845            &"5E9C128259B95B3C90C651E3E106A3276D83FFD1".parse().unwrap(),
2846            &"837B524C48C821FB23C4331A764076A4958D02E6".parse().unwrap(),
2847            &"1DBFA683F2744FCCFCF46D35989519FEB16FB4B1".parse().unwrap(),
2848            &"16561C850378BDB387F6E620B261465512DF841D".parse().unwrap(),
2849            &"40903D9038604F9F0325F4F595735AB9651D3899".parse().unwrap(),
2850            &"542CE462E1A66CEECDE4A15E3B614535DCA71EEF".parse().unwrap(),
2851            &"91FE56BE25CCB3CF5439DFAAC42E3BADAAFA919A".parse().unwrap(),
2852            &"0EBD96F41958B13F8F69B5FFD95B370820AE2176".parse().unwrap(),
2853            &"FE6500EC3768698238FA02AE836FE5675367B4F9".parse().unwrap(),
2854            &"34E96CA46093CDFC25ACE6A3A2FE701D926F093A".parse().unwrap(),
2855            &"45046E989B2E1B90A1DAEB5ADB7580D1B78D3BC6".parse().unwrap(),
2856            &"64A9859344F5073B183BD5C8AA60941E63199D9D".parse().unwrap(),
2857            &"729EDA4A2A634E776780E1847CA24E9550F7D0A7".parse().unwrap(),
2858            &"8844DCA493E8F20107CB447191FEA3BD4C01890B".parse().unwrap(),
2859            &"F965044BE1E7300C7B6716E293C396B4FA94CD92".parse().unwrap(),
2860            &"BC007EC19B0BC8DDE59847B09EA70EB3222D9E51".parse().unwrap(),
2861            &"B333A058F7209C46F2D027BB03738EAAC50701ED".parse().unwrap(),
2862            &"A9A1A3B0F12233D6120809D6F8F0C11D96152693".parse().unwrap(),
2863            &"2BFE10D7FEE9E5DF5833B6F61B584BAB2FD86575".parse().unwrap(),
2864            &"E5F3B17D545521F9B5395B10E92020FDB3E8109E".parse().unwrap(),
2865            &"58035C57B66B0EBFB069F9B7F3C623A5C52A3B92".parse().unwrap(),
2866            &"003E9C5A9DAB8626FD1694AAC2C43642A20E1496".parse().unwrap(),
2867            &"E7947E382B12FE628BDA130201EFC9D900B5540C".parse().unwrap(),
2868            &"17B55B1078D282C73FA2E76287FAB537AEAFE66C".parse().unwrap(),
2869            &"27CE83D68C669FE4F1B8C938D4A919E6F59E4D0B".parse().unwrap(),
2870            &"86B1E98692F4CA34122012C1524B4079CF57E850".parse().unwrap(),
2871            &"5B8A8AC5213064AE84C97DE41ED4BF239D9C10F2".parse().unwrap(),
2872            &"3FEAB08FC63829C080412CBFC6D3836C6E817789".parse().unwrap(),
2873            &"231605AEE34762F3BBC8ECF73808EFA9258837F8".parse().unwrap(),
2874            &"AE2759F4EC850FA6CE98FA4729FD82649411B973".parse().unwrap(),
2875            &"E7529E3567F59BBCADAAD1246613DBC86DAD45F8".parse().unwrap(),
2876            &"CF320590351A8C41C9EA0C1F4C6F00F7AEA73AD5".parse().unwrap(),
2877            &"475A44091578C02A0C5C2D62F106918D87E15476".parse().unwrap(),
2878            &"5B88BF2E7163D0594CE0E302C2AD0FE43D473EFE".parse().unwrap(),
2879            &"E4ADA4F5D702AD510C2F7A19316950AD7429C1FA".parse().unwrap(),
2880            &"6D6B846B8661F1013E7BC8D64C7280F7DF9DA6E6".parse().unwrap(),
2881            &"49883F6CA68B9F452F2A5F2F04687A6078E00FBF".parse().unwrap(),
2882            &"3046B5075B9DAF5645F51717D01AB61342900011".parse().unwrap(),
2883            &"16213F8B540AC28FE0CB3548D84F0D748AC23379".parse().unwrap(),
2884            &"9C68E98198FF9964FA2366ADCBAD3A465C76396B".parse().unwrap(),
2885            &"6EC3A10AA0B6B70DC5408CAE74B0BE836FD382D6".parse().unwrap(),
2886            &"E25E062BE69B48D3B99A96086991D15CA7370F0C".parse().unwrap(),
2887            &"A01A30A1AB191AF9C148C3704F4582E27D8D7527".parse().unwrap(),
2888            &"5D33551903E14FAABF75E9ECFB7AE6C2AC9959FB".parse().unwrap(),
2889            &"B37AE84FB0B4226FB935A3090F7C543F95A21EEF".parse().unwrap(),
2890            &"65B2CD9E6A6F6A36496B54A285F9BA4B68AA5174".parse().unwrap(),
2891            &"C0AA5CFC45580335A785DC2B3F9EE769EAAFE70D".parse().unwrap(),
2892            &"09973DF6334673259B774B840B1496371FDC2BE6".parse().unwrap(),
2893            &"29AAA5AF7CF941F4307DE966BD9E690D59FE5383".parse().unwrap(),
2894            &"9BDA50D8A6C78525051AAE07CC26594022C7D4AE".parse().unwrap(),
2895            &"2B0B6FDB04B9E8FF3A31EBE16A6B0A72A6571C45".parse().unwrap(),
2896            &"5C2650D8DA9842951614026288805244633C686B".parse().unwrap(),
2897            &"EEA6502B34AB08FA2F3BDA1E355AC29B6D8B67FA".parse().unwrap(),
2898            &"61B00DCDC02069F46F20D7F91075929DC6DA674C".parse().unwrap(),
2899            &"A1F5307F398FA45ECFC68CA92A5FC888D2DD2728".parse().unwrap(),
2900            &"AB0ADD3BF024EB6C75D9A366ABE69FC6E9F60DA0".parse().unwrap(),
2901            &"20DFEEF42F418CCEB02DB3E896E40B0413F1B4C5".parse().unwrap(),
2902            &"59C4E41C31D1E16F11BCF51304E7B81D67AD1FA0".parse().unwrap(),
2903            &"C0A3A190F8BFB6115A87CF7CBEC9211A2E210C86".parse().unwrap(),
2904            &"8932D417D3C0C4E3694E90480B92349F276E4EE0".parse().unwrap(),
2905            &"5BE288B0F7DCD89200D112D009E73AB06030B4EB".parse().unwrap(),
2906            &"CF472156042D6F2032BC025B68544E0A5844F3A7".parse().unwrap(),
2907            &"D54401DBBDE32805DAF08C4E1177C10E27F7D235".parse().unwrap(),
2908            &"56100D18E943687F7CFBC3CB20479A11B7DD5E1D".parse().unwrap(),
2909            &"9349703A779BD3725C5C822E21DA8172102EC4CD".parse().unwrap(),
2910            &"5DCAAB77198D13785C340D7B375DD44D815A0481".parse().unwrap(),
2911            &"5959CAC7EB9C1C7D9ECF10B8C023ED12A0F7F556".parse().unwrap(),
2912            &"7D4EA25C4F364AF1B61B64164816D289775352A8".parse().unwrap(),
2913            &"84291C882E059C5100C5C1AD1746298F01E7D682".parse().unwrap(),
2914            &"F3A95472FDB65D965EC2C4E3D22BD567B60BE41E".parse().unwrap(),
2915            &"0B9B18FB07F29E89D33AA0A86ED47AC9E7B86518".parse().unwrap(),
2916            &"2A11B65832E97E65DAA69D690C304130A843F532".parse().unwrap(),
2917            &"BB1B2F93AE4C4D41B4385AB653A4193345AA17C7".parse().unwrap(),
2918            &"4B526E27DAA41961F9D89404ED2F25E650D82444".parse().unwrap(),
2919            &"8DC51F77AEFAE450554792A0C704999EF5D32A6B".parse().unwrap(),
2920            &"ACD80C31E49FEAF9AA07DBD9FA96E7E857A694DE".parse().unwrap(),
2921            &"F2A4AE3ABC6DE0475E22B836DB0B8264BE496577".parse().unwrap(),
2922            &"14AA7B5B7D9088CBBD5FF8CB95F34513BA887EC0".parse().unwrap(),
2923            &"185A81E45751F6322490BE7987DDCD2A02E38D38".parse().unwrap(),
2924            &"BFCC758F6B567FF489801B539ED707902064CF71".parse().unwrap(),
2925            &"6F80DC80D1F4C14810750CAF51FAB910F100F6AB".parse().unwrap(),
2926            &"D220EB0F833DB97983F221D902D45679E35E555A".parse().unwrap(),
2927            &"6F757C636ED4E157D6F6570DBC03D6A8FCC6CD68".parse().unwrap(),
2928            &"C0C4B2D29A88A8F042FB13422605B3290364FF74".parse().unwrap(),
2929            &"23EBA00A8576434AE4B077F9819A1B623B2E138C".parse().unwrap(),
2930            &"88C18A2D51339461068DDF72693871FAF6FFC6FF".parse().unwrap(),
2931            &"CDA5DE7236C247F0D116CC0A1A25910D0CD909C0".parse().unwrap(),
2932            &"E405060228D49BA43C6ED9A3E25ADFDCC0012F48".parse().unwrap(),
2933            &"575DB527D78D5A063AB4197891DB2946F8EE3A8C".parse().unwrap(),
2934            &"D4BBE60FCA2FC7850FF7309102DEF04D111BA114".parse().unwrap(),
2935            &"97794BE1FD5729470D049D86BE16BB8E38D6D8EB".parse().unwrap(),
2936            &"4C011F0F9E4C58022DBD2E1FAA549F086FB77001".parse().unwrap(),
2937            &"950D06C53390F94AF59A15609900DA7A91A638CF".parse().unwrap(),
2938            &"013B231F139A46312550BBCBC52451FDB72285FC".parse().unwrap(),
2939            &"A814BA237B27B4605C71A907B8A8D55FC49CB5E6".parse().unwrap(),
2940            &"A3AE147DBC887FA325852A4DC3FFE143772A8587".parse().unwrap(),
2941            &"4D88E9B314F4ECAF99E02611C985FD350408C791".parse().unwrap(),
2942            &"CE9A27BE12483A5F094F85330E51D13DC2830B24".parse().unwrap(),
2943            &"B6565ADDD563FDD720D05411CD3449BD50892312".parse().unwrap(),
2944            &"F1EBB0F94C08A777867F403E9FAFBE3A10228952".parse().unwrap(),
2945            &"94D627E627E15F9B9144457816A736F442FD6A6F".parse().unwrap(),
2946            &"B3B1CDB5875CD8725B5FC915B1ED7C0FCE7721EE".parse().unwrap(),
2947            &"9E80CD683AA01265FE25DF265DADCE433039185C".parse().unwrap(),
2948            &"AFDE99A008E9BC761DFA6367C984AF52546308CF".parse().unwrap(),
2949            &"364854C36A1EFFDCAC7B80296A8F683B48BC5F33".parse().unwrap(),
2950            &"77C3730DB611591E71EE4528A15EE7D5EF32333F".parse().unwrap(),
2951            &"138CC2085B1A06F02DE1946D5FB391D63C886EE6".parse().unwrap(),
2952            &"AF097DA4DB5C0E2116EF583B25A6B381B621C082".parse().unwrap(),
2953            &"02DF6CB2758D7695940B6937804CAD30CDAC243C".parse().unwrap(),
2954            &"7F7C33899D1A34BE0D2B3C1C3B8F983DFABA03B4".parse().unwrap(),
2955            &"041549DBA90F2C4EB9E22505B4515224EB745A2C".parse().unwrap(),
2956            &"B73206C4F70E0735E9288128BAC3400233738122".parse().unwrap(),
2957            &"FCDF4C1D67ACFA8B42F6A77C408A9CB7367171C2".parse().unwrap(),
2958            &"B69A678AA242FA4F0BBF12205C0608799B0E3C51".parse().unwrap(),
2959        ];
2960
2961        let certs: Vec<Cert> = CertParser::from_bytes(
2962            &crate::testdata::data("infinity-and-beyond.pgp"))?
2963            .map(|c| c.expect("Valid certificate"))
2964            .collect();
2965        let store = CertStore::from_cert_refs(
2966            certs.iter().map(|c| c.into()), p, None)?;
2967        let n = NetworkBuilder::rootless(&store).build();
2968
2969        eprintln!("{:?}", n);
2970
2971        let n = NetworkBuilder::rooted(&store, slice::from_ref(&u1_fpr)).build();
2972
2973        /// Tests.
2974
2975        // This should always work.
2976        sp(&n, &u254_fpr, &u254_uid.clone(),
2977           &[ (120, &fprs[0..254]), ][..],
2978           None);
2979
2980        // This tests that depth=255 really means infinity.
2981        sp(&n, &u260_fpr, &u260_uid.clone(),
2982           &[ (120, &fprs[..]), ][..],
2983           None);
2984
2985        Ok(())
2986    }
2987
2988    #[test]
2989    #[allow(unused)]
2990    fn zero_trust() -> Result<()> {
2991        let p = &StandardPolicy::new();
2992
2993        let alice_fpr: Fingerprint =
2994            "931E51F99B89649783A1DFF265266E28246040C2"
2995           .parse().expect("valid fingerprint");
2996        let alice_uid
2997            = UserID::from("<alice@example.org>");
2998
2999        let bob_fpr: Fingerprint =
3000            "A1042B157AFA71F005208D645915549D8D21A97B"
3001           .parse().expect("valid fingerprint");
3002        let bob_uid
3003            = UserID::from("<bob@example.org>");
3004        // Certified by: 931E51F99B89649783A1DFF265266E28246040C2
3005        // Certified by: 931E51F99B89649783A1DFF265266E28246040C2
3006
3007        let carol_fpr: Fingerprint =
3008            "E06DB0539D99759681D7EC8508A267AE8FA838F4"
3009           .parse().expect("valid fingerprint");
3010        let carol_uid
3011            = UserID::from("<carol@example.org>");
3012        // Certified by: A1042B157AFA71F005208D645915549D8D21A97B
3013
3014        let certs: Vec<Cert> = CertParser::from_bytes(
3015            &crate::testdata::data("zero-trust.pgp"))?
3016            .map(|c| c.expect("Valid certificate"))
3017            .collect();
3018
3019        /// Tests.
3020
3021        // $ date '+%s' -d 20200202
3022        // 1580598000
3023        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
3024        // $ date '+%s' -d 20200302
3025        // 1583103600
3026        let t2 = time::UNIX_EPOCH + time::Duration::new(1583103600, 0);
3027
3028        // At t2, B is certified with a trust amount of 0.  This
3029        // should eliminate the path.
3030        for (i, t) in [t1, t2].iter().enumerate() {
3031            eprintln!("\n\nTrying at t{}", i + 1);
3032
3033            let store = CertStore::from_cert_refs(
3034                certs.iter().map(|c| c.into()), p, *t)?;
3035            let n = NetworkBuilder::rootless(&store).build();
3036
3037            eprintln!("{:?}", n);
3038
3039            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr)).build();
3040
3041            if i + 1 == 1 {
3042                sp(&n, &carol_fpr, &carol_uid.clone(),
3043                   &[ (60, &[&alice_fpr, &bob_fpr, &carol_fpr][..]), ][..],
3044                   None);
3045            } else {
3046                sp(&n, &carol_fpr, &carol_uid.clone(),
3047                   &[][..],
3048                   None);
3049            }
3050
3051            // Start with bob and make sure that a certification by a
3052            // root with a 0 trust amount is also respected.
3053            let n = NetworkBuilder::rooted(&store, slice::from_ref(&bob_fpr)).build();
3054
3055            if i + 1 == 1 {
3056                sp(&n, &carol_fpr, &carol_uid.clone(),
3057                   &[ (60, &[&bob_fpr, &carol_fpr][..]), ][..],
3058                   None);
3059            } else {
3060                sp(&n, &carol_fpr, &carol_uid.clone(),
3061                   &[][..],
3062                   None);
3063            }
3064        }
3065
3066        Ok(())
3067    }
3068
3069    #[test]
3070    #[allow(unused)]
3071    fn partially_trusted_roots() -> Result<()> {
3072        let p = &StandardPolicy::new();
3073
3074        let alice_fpr: Fingerprint =
3075            "85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D"
3076           .parse().expect("valid fingerprint");
3077        let alice_uid
3078            = UserID::from("<alice@example.org>");
3079
3080        let bob_fpr: Fingerprint =
3081            "39A479816C934B9E0464F1F4BC1DCFDEADA4EE90"
3082           .parse().expect("valid fingerprint");
3083        let bob_uid
3084            = UserID::from("<bob@example.org>");
3085        // Certified by: 85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D
3086
3087        let carol_fpr: Fingerprint =
3088            "43530F91B450EDB269AA58821A1CF4DC7F500F04"
3089           .parse().expect("valid fingerprint");
3090        let carol_uid
3091            = UserID::from("<carol@example.org>");
3092        // Certified by: 39A479816C934B9E0464F1F4BC1DCFDEADA4EE90
3093
3094        let dave_fpr: Fingerprint =
3095            "329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281"
3096           .parse().expect("valid fingerprint");
3097        let dave_uid
3098            = UserID::from("<dave@example.org>");
3099        // Certified by: 43530F91B450EDB269AA58821A1CF4DC7F500F04
3100
3101        let ellen_fpr: Fingerprint =
3102            "A7319A9B166AB530A5FBAC8AB43CA77F7C176AF4"
3103           .parse().expect("valid fingerprint");
3104        let ellen_uid
3105            = UserID::from("<ellen@example.org>");
3106        // Certified by: 329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281
3107
3108        let frank_fpr: Fingerprint =
3109            "2693237D2CED0BB68F118D78DC86A97CD2C819D9"
3110           .parse().expect("valid fingerprint");
3111        let frank_uid
3112            = UserID::from("<frank@example.org>");
3113
3114
3115        let certs: Vec<Cert> = CertParser::from_bytes(
3116            &crate::testdata::data("simple.pgp"))?
3117            .map(|c| c.expect("Valid certificate"))
3118            .collect();
3119        let store = CertStore::from_cert_refs(
3120            certs.iter().map(|c| c.into()), p, None)?;
3121        let n = NetworkBuilder::rootless(&store).build();
3122
3123        eprintln!("{:?}", n);
3124
3125        let n = NetworkBuilder::rooted(&store, &[ (alice_fpr.clone(), 90) ])
3126            .build();
3127
3128        sp(&n, &alice_fpr, &alice_uid.clone(),
3129           &[ (90, &[ &alice_fpr ][..]) ][..],
3130           None);
3131
3132        sp(&n, &bob_fpr, &bob_uid.clone(),
3133           &[ (90, &[ &alice_fpr, &bob_fpr ][..]) ][..],
3134           None);
3135
3136        sp(&n, &carol_fpr, &carol_uid.clone(),
3137           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
3138           None);
3139
3140        sp(&n, &dave_fpr, &dave_uid.clone(),
3141           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
3142           None);
3143
3144        sp(&n, &ellen_fpr, &ellen_uid.clone(),
3145           &[][..],
3146           None);
3147
3148        sp(&n, &frank_fpr, &frank_uid.clone(),
3149           &[][..],
3150           None);
3151
3152        // No one authenticated Bob's User ID on Carol's key.
3153        sp(&n, &carol_fpr, &bob_uid.clone(),
3154           &[][..],
3155           None);
3156
3157        // Multiple partially trusted roots.  Check that together they
3158        // can fully certify a self signature.
3159        let n = NetworkBuilder::rooted(
3160            &store,
3161            &[
3162                (alice_fpr.clone(), 90),
3163                (bob_fpr.clone(), 90)
3164            ])
3165            .build();
3166
3167
3168        sp(&n, &alice_fpr, &alice_uid.clone(),
3169           &[ (90, &[ &alice_fpr ][..]) ][..],
3170           None);
3171
3172        sp(&n, &bob_fpr, &bob_uid.clone(),
3173           &[
3174               (90, &[ &bob_fpr ][..]),
3175               (90, &[ &alice_fpr, &bob_fpr ][..]),
3176           ][..],
3177           None);
3178
3179        Ok(())
3180    }
3181
3182    #[test]
3183    #[allow(unused)]
3184    fn self_signed() -> Result<()> {
3185        let p = &StandardPolicy::new();
3186
3187        let alice_fpr: Fingerprint =
3188            "838454E0D61D046300B408A908A4FDB4F368ECB9"
3189           .parse().expect("valid fingerprint");
3190        let alice_uid
3191            = UserID::from("<alice@example.org>");
3192
3193        let bob_fpr: Fingerprint =
3194            "7A7B5DE6C8F464CAB78BEFB9CE14BEE51D4DEC01"
3195           .parse().expect("valid fingerprint");
3196        let bob_uid
3197            = UserID::from("<bob@example.org>");
3198        // Certified by: 838454E0D61D046300B408A908A4FDB4F368ECB9
3199
3200        let carol_fpr: Fingerprint =
3201            "830230061426EE99A0455E6ADA869CF879A5630D"
3202           .parse().expect("valid fingerprint");
3203        let carol_uid
3204            = UserID::from("<carol@example.org>");
3205        // Certified by: 7A7B5DE6C8F464CAB78BEFB9CE14BEE51D4DEC01
3206        let carol_other_org_uid
3207            = UserID::from("<carol@other.org>");
3208
3209        let dave_fpr: Fingerprint =
3210            "51A5E15F87AC6ECAFBEA930FA5F30AF6EB6EF14A"
3211           .parse().expect("valid fingerprint");
3212        let dave_uid
3213            = UserID::from("<dave@example.org>");
3214        // Certified by: 830230061426EE99A0455E6ADA869CF879A5630D
3215
3216        let certs: Vec<Cert> = CertParser::from_bytes(
3217            &crate::testdata::data("self-signed.pgp"))?
3218            .map(|c| c.expect("Valid certificate"))
3219            .collect();
3220        let store = CertStore::from_cert_refs(
3221            certs.iter().map(|c| c.into()), p, None)?;
3222        let n = NetworkBuilder::rootless(&store).build();
3223
3224        eprintln!("{:?}", n);
3225
3226        /// Tests.
3227
3228        let n = NetworkBuilder::rooted(
3229            &store,
3230            &[
3231                (alice_fpr.clone(), 120),
3232            ])
3233            .build();
3234
3235        sp(&n, &bob_fpr, &bob_uid.clone(),
3236           &[ (100, &[ &alice_fpr, &bob_fpr ][..]) ][..],
3237           None);
3238
3239        sp(&n, &carol_fpr, &carol_uid.clone(),
3240           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
3241           None);
3242
3243        sp(&n, &carol_fpr, &carol_other_org_uid.clone(),
3244           &[][..],
3245           None);
3246
3247        sp(&n, &dave_fpr, &dave_uid.clone(),
3248           &[][..],
3249           None);
3250
3251        let n = NetworkBuilder::rooted(
3252            &store,
3253            &[
3254                (bob_fpr.clone(), 120),
3255            ])
3256            .build();
3257
3258        sp(&n, &bob_fpr, &bob_uid.clone(),
3259           &[ (120, &[ &bob_fpr ][..]) ][..],
3260           None);
3261
3262        sp(&n, &carol_fpr, &carol_uid.clone(),
3263           &[ (90, &[ &bob_fpr, &carol_fpr ][..]) ][..],
3264           None);
3265
3266        sp(&n, &carol_fpr, &carol_other_org_uid.clone(),
3267           &[ (90, &[ &bob_fpr, &carol_fpr, &carol_fpr ][..]) ][..],
3268           None);
3269
3270        sp(&n, &dave_fpr, &dave_uid.clone(),
3271           &[ (90, &[ &bob_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
3272           None);
3273
3274        Ok(())
3275    }
3276
3277    #[test]
3278    #[allow(unused)]
3279    fn isolated_root() -> Result<()> {
3280        let p = &StandardPolicy::new();
3281
3282        let alice_fpr: Fingerprint =
3283            "DCF3020AAB76ECC7F0E5AC0D375DCE1BEE264B87"
3284           .parse().expect("valid fingerprint");
3285        let alice_uid
3286            = UserID::from("<alice@example.org>");
3287        let alice_other_org_uid
3288            = UserID::from("<alice@other.org>");
3289
3290        let certs: Vec<Cert> = CertParser::from_bytes(
3291            &crate::testdata::data("isolated-root.pgp"))?
3292            .map(|c| c.expect("Valid certificate"))
3293            .collect();
3294
3295        /// Tests.
3296        // $ date '+%s' -d 20200102
3297        // 1577919600
3298        let t0 = time::UNIX_EPOCH + time::Duration::new(1577919600, 0);
3299        // $ date '+%s' -d 20200202
3300        // 1580598000
3301        let t1 = time::UNIX_EPOCH + time::Duration::new(1580598000, 0);
3302
3303        for (i, t) in [t0, t1].iter().enumerate() {
3304            eprintln!("\n\nTrying at t{}", i + 1);
3305
3306            let store = CertStore::from_cert_refs(
3307                certs.iter().map(|c| c.into()), p, *t)?;
3308            let n = NetworkBuilder::rootless(&store).build();
3309
3310            eprintln!("{:?}", n);
3311
3312            let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr))
3313                .build();
3314
3315            if i == 0 {
3316                sp(&n, &alice_fpr, &alice_uid.clone(),
3317                   &[ (120, &[&alice_fpr][..]), ][..],
3318                   None);
3319            } else {
3320                sp(&n, &alice_fpr, &alice_uid.clone(),
3321                   &[][..],
3322                   None);
3323            }
3324
3325            sp(&n, &alice_fpr, &alice_other_org_uid.clone(),
3326               &[ (120, &[&alice_fpr][..]), ][..],
3327               None);
3328        }
3329
3330        Ok(())
3331    }
3332
3333    #[test]
3334    fn limit_depth() -> Result<()> {
3335        let p = &StandardPolicy::new();
3336
3337        let alice_fpr: Fingerprint =
3338            "85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D"
3339           .parse().expect("valid fingerprint");
3340        let alice_uid
3341            = UserID::from("<alice@example.org>");
3342
3343        let bob_fpr: Fingerprint =
3344            "39A479816C934B9E0464F1F4BC1DCFDEADA4EE90"
3345           .parse().expect("valid fingerprint");
3346        let bob_uid
3347            = UserID::from("<bob@example.org>");
3348        // Certified by: 85DAB65713B2D0ABFC5A4F28BC10C9CE4A699D8D
3349
3350        let carol_fpr: Fingerprint =
3351            "43530F91B450EDB269AA58821A1CF4DC7F500F04"
3352           .parse().expect("valid fingerprint");
3353        let carol_uid
3354            = UserID::from("<carol@example.org>");
3355        // Certified by: 39A479816C934B9E0464F1F4BC1DCFDEADA4EE90
3356
3357        let dave_fpr: Fingerprint =
3358            "329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281"
3359           .parse().expect("valid fingerprint");
3360        let dave_uid
3361            = UserID::from("<dave@example.org>");
3362        // Certified by: 43530F91B450EDB269AA58821A1CF4DC7F500F04
3363
3364        let ellen_fpr: Fingerprint =
3365            "A7319A9B166AB530A5FBAC8AB43CA77F7C176AF4"
3366           .parse().expect("valid fingerprint");
3367        let ellen_uid
3368            = UserID::from("<ellen@example.org>");
3369        // Certified by: 329D5AAF73DC70B4E3DD2D11677CB70FFBFE1281
3370
3371        let certs: Vec<Cert> = CertParser::from_bytes(
3372            &crate::testdata::data("simple.pgp"))?
3373            .map(|c| c.expect("Valid certificate"))
3374            .collect();
3375        let store = CertStore::from_cert_refs(
3376            certs.iter().map(|c| c.into()), p, None)?;
3377        let n = NetworkBuilder::rootless(&store).build();
3378
3379
3380        eprintln!("{:?}", n);
3381
3382        eprintln!("Unconstrained query.");
3383        let n = NetworkBuilder::rooted(&store, &[ (alice_fpr.clone(), 90) ])
3384            .build();
3385
3386        sp(&n, &alice_fpr, &alice_uid.clone(),
3387           &[ (90, &[ &alice_fpr ][..]) ][..],
3388           None);
3389
3390        sp(&n, &bob_fpr, &bob_uid.clone(),
3391           &[ (90, &[ &alice_fpr, &bob_fpr ][..]) ][..],
3392           None);
3393
3394        sp(&n, &carol_fpr, &carol_uid.clone(),
3395           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
3396           None);
3397
3398        sp(&n, &dave_fpr, &dave_uid.clone(),
3399           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
3400           None);
3401
3402        sp(&n, &ellen_fpr, &ellen_uid.clone(),
3403           &[][..],
3404           None);
3405
3406        // Network constrained to a depth of 2.  This doesn't change
3407        // anything, as Alice's tsig on Bob also has depth 2.
3408        eprintln!("Network constrained to a depth of 2:");
3409        let n = NetworkBuilder::rooted(&store, &[ (alice_fpr.clone(), 90) ])
3410            .maximum_depth(2)
3411            .build();
3412
3413        sp(&n, &alice_fpr, &alice_uid.clone(),
3414           &[ (90, &[ &alice_fpr ][..]) ][..],
3415           None);
3416
3417        sp(&n, &bob_fpr, &bob_uid.clone(),
3418           &[ (90, &[ &alice_fpr, &bob_fpr ][..]) ][..],
3419           None);
3420
3421        sp(&n, &carol_fpr, &carol_uid.clone(),
3422           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
3423           None);
3424
3425        sp(&n, &dave_fpr, &dave_uid.clone(),
3426           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr, &dave_fpr ][..]) ][..],
3427           None);
3428
3429        sp(&n, &ellen_fpr, &ellen_uid.clone(),
3430           &[][..],
3431           None);
3432
3433        // Network constrained to a depth of 1.
3434        eprintln!("Network constrained to a depth of 1:");
3435        let n = NetworkBuilder::rooted(&store, &[ (alice_fpr.clone(), 90) ])
3436            .maximum_depth(1)
3437            .build();
3438
3439        sp(&n, &alice_fpr, &alice_uid.clone(),
3440           &[ (90, &[ &alice_fpr ][..]) ][..],
3441           None);
3442
3443        sp(&n, &bob_fpr, &bob_uid.clone(),
3444           &[ (90, &[ &alice_fpr, &bob_fpr ][..]) ][..],
3445           None);
3446
3447        sp(&n, &carol_fpr, &carol_uid.clone(),
3448           &[ (90, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]) ][..],
3449           None);
3450
3451        sp(&n, &dave_fpr, &dave_uid.clone(),
3452           &[][..],
3453           None);
3454
3455        sp(&n, &ellen_fpr, &ellen_uid.clone(),
3456           &[][..],
3457           None);
3458
3459        // Network constrained to a depth of 0.
3460        eprintln!("Network constrained to a depth of 0:");
3461        let n = NetworkBuilder::rooted(&store, &[ (alice_fpr.clone(), 90) ])
3462            .maximum_depth(0)
3463            .build();
3464
3465        sp(&n, &alice_fpr, &alice_uid.clone(),
3466           &[ (90, &[ &alice_fpr ][..]) ][..],
3467           None);
3468
3469        sp(&n, &bob_fpr, &bob_uid.clone(),
3470           &[ (90, &[ &alice_fpr, &bob_fpr ][..]) ][..],
3471           None);
3472
3473        sp(&n, &carol_fpr, &carol_uid.clone(),
3474           &[][..],
3475           None);
3476
3477        sp(&n, &dave_fpr, &dave_uid.clone(),
3478           &[][..],
3479           None);
3480
3481        sp(&n, &ellen_fpr, &ellen_uid.clone(),
3482           &[][..],
3483           None);
3484
3485        Ok(())
3486    }
3487
3488    #[test]
3489    fn regex4() -> Result<()> {
3490        // Consider:
3491        //
3492        // <alice@example.org>
3493        // |
3494        // | Authorization (depth: 1, amount: 120),
3495        // | Regular expression: some.org
3496        // v
3497        // <bob@example.org>
3498        //
3499        // Alice designates Bob as an introducer for some.org.  At the
3500        // same time, she vouches that '<bob@example.org>' controls a
3501        // particular certificate.  What's interesting about this is
3502        // that the user ID has a different domain from the scope!
3503        // This test checks that we can correctly authenticate Bob's
3504        // self-signed user ID '<bob@some.org>' via
3505        // '<bob@example.org>', but can't authenticate his other
3506        // self-signed user ID '<bob@other.org>' via
3507        // '<bob@example.org>' as it doesn't match the scope.
3508
3509        let alice_fpr: Fingerprint =
3510            "43ED15FAF18395C08AEDEDC0FC9EB4BFABE67F70"
3511           .parse().expect("valid fingerprint");
3512        let alice_uid
3513            = UserID::from("<alice@example.org>");
3514
3515        let bob_fpr: Fingerprint =
3516            "3A9E44015431B8655CD3FECFBFB6DEC7D711138F"
3517           .parse().expect("valid fingerprint");
3518        let bob_uid
3519            = UserID::from("<bob@example.org>");
3520        // Regular expression: <[^>]+[@.]some\.org>$
3521        // Certified by: 43ED15FAF18395C08AEDEDC0FC9EB4BFABE67F70 <alice@example.org> (UNAUTHENTICATED)
3522        let bob_other_org_uid
3523            = UserID::from("<bob@other.org>");
3524        let bob_some_org_uid
3525            = UserID::from("<bob@some.org>");
3526
3527        let carol_fpr: Fingerprint =
3528            "03357E46D9E0C47A9D92CA58F71DE1B5B9CD2D10"
3529           .parse().expect("valid fingerprint");
3530        let carol_uid
3531            = UserID::from("<carol@some.org>");
3532        // Certified by: 3A9E44015431B8655CD3FECFBFB6DEC7D711138F <bob@example.org> (UNAUTHENTICATED)
3533
3534        let dave_fpr: Fingerprint =
3535            "B7FE472208AE5188971466F1FF7C4B36B578B709"
3536           .parse().expect("valid fingerprint");
3537        let dave_uid
3538            = UserID::from("<dave@other.org>");
3539        // Certified by: 3A9E44015431B8655CD3FECFBFB6DEC7D711138F <bob@example.org> (UNAUTHENTICATED)
3540
3541        let p = &StandardPolicy::new();
3542
3543        let certs: Vec<Cert> = CertParser::from_bytes(
3544            &crate::testdata::data("regex-4.pgp"))?
3545            .map(|c| c.expect("Valid certificate"))
3546            .collect();
3547        let store = CertStore::from_cert_refs(
3548            certs.iter().map(|c| c.into()), p, None)?;
3549        let n = NetworkBuilder::rootless(&store).build();
3550
3551        eprintln!("{:?}", n);
3552
3553        eprintln!("Unconstrained query.");
3554        let n = NetworkBuilder::rooted(&store, slice::from_ref(&alice_fpr))
3555            .build();
3556
3557        sp(&n, &alice_fpr, &alice_uid.clone(),
3558           &[ (120, &[ &alice_fpr ][..]) ][..],
3559           None);
3560        // Alice certified bob@example.org.
3561        sp(&n, &bob_fpr, &bob_uid.clone(),
3562           &[
3563               (120, &[ &alice_fpr, &bob_fpr ][..]),
3564           ][..],
3565           None);
3566        // Alice made Bob via a certification on bob@example.org a
3567        // trusted introducer for some.org so he can introducer this
3568        // self-signed user ID.
3569        sp(&n, &bob_fpr, &bob_some_org_uid.clone(),
3570           &[
3571               (120, &[ &alice_fpr, &bob_fpr, &bob_fpr ][..]),
3572           ][..],
3573           None);
3574        // Alice made Bob a trusted introducer for some.org, but not
3575        // other.org.
3576        sp(&n, &bob_fpr, &bob_other_org_uid.clone(),
3577           &[][..],
3578           None);
3579        sp(&n, &carol_fpr, &carol_uid.clone(),
3580           &[
3581               (120, &[ &alice_fpr, &bob_fpr, &carol_fpr ][..]),
3582           ][..],
3583           None);
3584        sp(&n, &dave_fpr, &dave_uid.clone(),
3585           &[][..],
3586           None);
3587
3588        Ok(())
3589    }
3590
3591    /// This is like the regex_4 test, but instead of Alice making Bob
3592    /// a CA via a user ID, she does a delegation (i.e., a direct key
3593    /// signature).
3594    ///
3595    /// ```
3596    /// alice
3597    ///   |
3598    ///   | Delegation (uid=None, depth=unconstrained, amount=120)
3599    ///   | Regex: <[^>]+[@.]some\.org>$
3600    ///   v
3601    /// bob
3602    ///   └── self-signed UID: <bob@other.org>
3603    /// ```
3604    #[test]
3605    fn regex4_2() {
3606        // We build the network manually, because sq doesn't currently
3607        // support creating delegations.
3608        use std::time::Duration;
3609        use std::time::UNIX_EPOCH;
3610
3611        use openpgp::Fingerprint;
3612        use openpgp::packet::UserID;
3613
3614        use crate::CertSynopsis;
3615        use crate::Certification;
3616        use crate::UserIDSynopsis;
3617
3618        fn make_fpr(id: u8) -> Fingerprint {
3619            let mut bytes = [0u8; 20];
3620            bytes[0] = id;
3621            bytes[19] = id.wrapping_add(1);
3622            Fingerprint::from_bytes(4, &bytes).expect("valid v4 fingerprint")
3623        }
3624
3625        let ref_time = UNIX_EPOCH + Duration::from_secs(1_700_000_000);
3626        let alice_fpr = make_fpr(1);
3627        let bob_fpr = make_fpr(2);
3628
3629        // Alice's certificate.
3630        let alice_cert = CertSynopsis::new(
3631            alice_fpr.clone(), None,
3632            crate::RevocationStatus::NotAsFarAsWeKnow,
3633            vec![UserIDSynopsis::from(
3634                ("<alice@example.org>", ref_time - Duration::from_secs(86400)),
3635            )].into_iter(),
3636        );
3637
3638        // Bob's certificate with a user ID that matches the regex and
3639        // another one that does not.
3640        let bob_cert = CertSynopsis::new(
3641            bob_fpr.clone(),
3642            None,
3643            crate::RevocationStatus::NotAsFarAsWeKnow,
3644            vec![
3645                UserIDSynopsis::from(
3646                    ("<bob@other.org>", ref_time - Duration::from_secs(86400))),
3647                UserIDSynopsis::from(
3648                    ("<bob@some.org>", ref_time - Duration::from_secs(86400))),
3649            ].into_iter());
3650        let bob_other_org_uid = UserID::from("<bob@other.org>");
3651        let bob_some_org_uid = UserID::from("<bob@some.org>");
3652
3653
3654        // Alice makes Bob a trusted introducer for the "some.org"
3655        // domain.  This is a delegation (uid=None), NOT a user ID
3656        // certification.
3657        let delegation = Certification::new(
3658            alice_cert.clone(),
3659            None::<UserID>, // None => delegation.
3660            bob_cert.clone(),
3661            ref_time - Duration::from_secs(3600))
3662                .set_amount(120)
3663                .set_depth(Depth::unconstrained())
3664                .set_regular_expressions(
3665                    [&b"<[^>]+[@.]some\\.org>$"[..]].into_iter(),
3666                );
3667
3668        let certs = [alice_cert, bob_cert];
3669        let certifications = [delegation];
3670
3671        let n = Network::from_synopses(
3672            &certs, &certifications, ref_time, &[alice_fpr.clone()])
3673            .expect("valid network");
3674
3675        // We should be able to authenticate bob@some.org via the
3676        // delegation.
3677        let paths = n.authenticate(
3678            bob_some_org_uid.clone(), bob_fpr.clone(), 1);
3679
3680        assert_eq!(paths.len(), 1);
3681        let (path, amount) = paths.iter().next().unwrap();
3682        assert_eq!(*amount, 120);
3683        assert_eq!(path.certificates().map(|c| c.fingerprint()).collect::<Vec<_>>(),
3684                   vec![ alice_fpr, bob_fpr.clone(), bob_fpr.clone() ]);
3685
3686        // We shouldn't be able to authenticate bob@other.org via the
3687        // delegation.
3688        let paths = n.authenticate(
3689            bob_other_org_uid.clone(), bob_fpr.clone(), 1);
3690
3691        assert_eq!(paths.len(), 0);
3692    }
3693}