fetchEuTrustedLists function

Future<PdfEuTrustListSnapshot> fetchEuTrustedLists({
  1. required PdfTrustListFetch fetch,
  2. Set<String> pinnedSigners = PdfEuLotl.signerFingerprints,
  3. DateTime? now,
})

Fetches the LOTL and every Member State list through fetch, verifies each signature (the LOTL against pinnedSigners, each national list against the certificates the LOTL names for it) and collects the qualified CA anchors. A list that fails to download or verify is skipped and reported in PdfEuTrustListSnapshot.problems - including one that is expired at now; a LOTL that fails or is expired is fatal (thrown). The snapshot's PdfEuTrustListSnapshot.expires is the earliest NextUpdate of the lists it was built from.

Implementation

Future<PdfEuTrustListSnapshot> fetchEuTrustedLists({
  required PdfTrustListFetch fetch,
  Set<String> pinnedSigners = PdfEuLotl.signerFingerprints,
  DateTime? now,
}) async {
  final at = (now ?? DateTime.now()).toUtc();
  final lotl = parseEuLotl(await fetch(PdfEuLotl.url),
      pinnedSigners: pinnedSigners, now: at);
  // One list per territory (the first XML pointer), fetched concurrently -
  // the downloads dominate, and the lists are independent.
  final byTerritory = <String, PdfTrustListPointer>{};
  for (final pointer in lotl.pointers) {
    byTerritory.putIfAbsent(pointer.territory, () => pointer);
  }
  final problems = <String, String>{};
  final results = await Future.wait([
    for (final pointer in byTerritory.values)
      () async {
        try {
          return parseEuTrustedList(await fetch(pointer.location), pointer,
              now: at);
        } on Object catch (e) {
          problems[pointer.territory] = '${pointer.location}: $e';
          return null;
        }
      }(),
  ]);
  final entries = <PdfTrustListEntry>[];
  var expires = lotl.nextUpdate!; // parseEuLotl refuses a list without one
  for (final list in results) {
    if (list == null) continue;
    entries.addAll(list.entries);
    if (list.nextUpdate.isBefore(expires)) expires = list.nextUpdate;
  }
  return PdfEuTrustListSnapshot(
    entries: entries,
    fetchedAt: at,
    lotlSequenceNumber: lotl.sequence,
    lotlIssued: lotl.issued,
    lotlNextUpdate: lotl.nextUpdate,
    expires: expires,
    problems: problems,
  );
}