mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 04:17:59 +01:00
Move Network initialization, test vectors to pgpainless-wot
This commit is contained in:
parent
0335d7e55d
commit
2a063597e6
28 changed files with 293 additions and 100 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'java-library'
|
id 'java-library'
|
||||||
|
id 'java-test-fixtures'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'org.pgpainless'
|
group 'org.pgpainless'
|
||||||
|
@ -13,13 +14,20 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// JUnit
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
||||||
|
testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
||||||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||||
|
|
||||||
|
testFixturesImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion"
|
||||||
|
testFixturesImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion"
|
||||||
|
testFixturesRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||||
|
|
||||||
implementation(project(":pgpainless-core"))
|
implementation(project(":pgpainless-core"))
|
||||||
|
implementation(project(":wot-dijkstra"))
|
||||||
|
|
||||||
// Certificate store
|
// Certificate store
|
||||||
api "org.pgpainless:pgp-certificate-store:$certDJavaVersion"
|
api "org.pgpainless:pgp-certificate-store:$certDJavaVersion"
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.wot;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because an {@link Iterator} is not {@link Iterable} ¯\_(ツ)_/¯.
|
||||||
|
* @param <T> item
|
||||||
|
*/
|
||||||
|
public final class IterableIterator<T> implements Iterable<T> {
|
||||||
|
|
||||||
|
private final Iterator<T> iterator;
|
||||||
|
|
||||||
|
public IterableIterator(Iterator<T> iterator) {
|
||||||
|
this.iterator = iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.wot;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new {@link Iterator} with a prepended item.
|
||||||
|
* @param <T> item type
|
||||||
|
*/
|
||||||
|
public class PrefixedIterator<T> implements Iterator<T> {
|
||||||
|
|
||||||
|
private T prefix;
|
||||||
|
private Iterator<T> iterator;
|
||||||
|
|
||||||
|
public PrefixedIterator(T prefix, Iterator<T> iterator) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.iterator = iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return prefix != null || iterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T next() {
|
||||||
|
if (prefix != null) {
|
||||||
|
T t = prefix;
|
||||||
|
prefix = null;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return iterator.next();
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,15 +4,41 @@
|
||||||
|
|
||||||
package org.pgpainless.wot;
|
package org.pgpainless.wot;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.sig.RevocationReason;
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignature;
|
||||||
|
import org.pgpainless.PGPainless;
|
||||||
|
import org.pgpainless.algorithm.KeyFlag;
|
||||||
|
import org.pgpainless.algorithm.RevocationState;
|
||||||
|
import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
|
import org.pgpainless.key.util.RevocationAttributes;
|
||||||
|
import org.pgpainless.policy.Policy;
|
||||||
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.CertSynopsis;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.CertificationSet;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.Network;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.Optional;
|
||||||
|
import org.pgpainless.wot.dijkstra.sq.ReferenceTime;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import pgp.certificate_store.certificate.Certificate;
|
import pgp.certificate_store.certificate.Certificate;
|
||||||
import pgp.certificate_store.exception.BadDataException;
|
import pgp.certificate_store.exception.BadDataException;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class WebOfTrust implements CertificateAuthority {
|
public class WebOfTrust implements CertificateAuthority {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(WebOfTrust.class);
|
||||||
|
|
||||||
private final WebOfTrustCertificateStore certificateStore;
|
private final WebOfTrustCertificateStore certificateStore;
|
||||||
|
private Network network;
|
||||||
|
|
||||||
public WebOfTrust(WebOfTrustCertificateStore certificateStore) {
|
public WebOfTrust(WebOfTrustCertificateStore certificateStore) {
|
||||||
this.certificateStore = certificateStore;
|
this.certificateStore = certificateStore;
|
||||||
|
@ -22,8 +48,109 @@ public class WebOfTrust implements CertificateAuthority {
|
||||||
* Do the heavy lifting of calculating the web of trust.
|
* Do the heavy lifting of calculating the web of trust.
|
||||||
*/
|
*/
|
||||||
public void initialize() throws BadDataException, IOException {
|
public void initialize() throws BadDataException, IOException {
|
||||||
Certificate trustRoot = certificateStore.getTrustRootCertificate();
|
Iterator<Certificate> certificates = certificateStore.getAllItems();
|
||||||
// TODO: Implement
|
IterableIterator<Certificate> iterable = new IterableIterator<>(certificates);
|
||||||
|
network = fromCertificates(iterable, PGPainless.getPolicy(), Optional.just(ReferenceTime.now()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link Network} from a set of certificates.
|
||||||
|
*
|
||||||
|
* @param certificates set of certificates
|
||||||
|
* @param policy evaluation policy
|
||||||
|
* @param optReferenceTime reference time for evaluation
|
||||||
|
* @return network
|
||||||
|
*/
|
||||||
|
public static Network fromCertificates(
|
||||||
|
Iterable<Certificate> certificates,
|
||||||
|
Policy policy,
|
||||||
|
Optional<ReferenceTime> optReferenceTime) {
|
||||||
|
ReferenceTime referenceTime = optReferenceTime.isPresent() ? optReferenceTime.get() : ReferenceTime.now();
|
||||||
|
List<KeyRingInfo> validCerts = new ArrayList<>();
|
||||||
|
for (Certificate cert : certificates) {
|
||||||
|
try {
|
||||||
|
PGPPublicKeyRing publicKey = PGPainless.readKeyRing().publicKeyRing(cert.getInputStream());
|
||||||
|
// No Certificate data
|
||||||
|
if (publicKey == null) {
|
||||||
|
throw new IOException("Certificate " + cert.getFingerprint() + " was null. No certificate data?");
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyRingInfo info = new KeyRingInfo(publicKey, policy, referenceTime.getTimestamp());
|
||||||
|
if (info.getValidUserIds().isEmpty()) {
|
||||||
|
LOGGER.warn("Certificate " + cert.getFingerprint() + " has no valid user-ids. Ignore.");
|
||||||
|
// Ignore invalid cert
|
||||||
|
// TODO: Allow user-id-less certificates?
|
||||||
|
} else {
|
||||||
|
validCerts.add(info);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warn("Could not parse certificate " + cert.getFingerprint(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromValidCertificates(
|
||||||
|
validCerts,
|
||||||
|
referenceTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link Network} from a set of validated certificates.
|
||||||
|
*
|
||||||
|
* @param validatedCertificates set of validated certificates
|
||||||
|
* @param referenceTime reference time
|
||||||
|
* @return network
|
||||||
|
*/
|
||||||
|
public static Network fromValidCertificates(
|
||||||
|
Iterable<KeyRingInfo> validatedCertificates,
|
||||||
|
ReferenceTime referenceTime) {
|
||||||
|
|
||||||
|
Map<OpenPgpFingerprint, KeyRingInfo> byFingerprint = new HashMap<>();
|
||||||
|
Map<Long, List<KeyRingInfo>> byKeyId = new HashMap<>();
|
||||||
|
|
||||||
|
Map<OpenPgpFingerprint, CertSynopsis> certSynopsisMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (KeyRingInfo cert : validatedCertificates) {
|
||||||
|
// noinspection Java8MapApi
|
||||||
|
if (byFingerprint.get(cert.getFingerprint()) == null) {
|
||||||
|
byFingerprint.put(cert.getFingerprint(), cert);
|
||||||
|
}
|
||||||
|
List<KeyRingInfo> byKeyIdEntry = byKeyId.get(cert.getKeyId());
|
||||||
|
|
||||||
|
// noinspection Java8MapApi
|
||||||
|
if (byKeyIdEntry == null) {
|
||||||
|
byKeyIdEntry = new ArrayList<>();
|
||||||
|
byKeyId.put(cert.getKeyId(), byKeyIdEntry);
|
||||||
|
}
|
||||||
|
byKeyIdEntry.add(cert);
|
||||||
|
|
||||||
|
certSynopsisMap.put(cert.getFingerprint(),
|
||||||
|
new CertSynopsis(cert.getFingerprint(),
|
||||||
|
cert.getExpirationDateForUse(KeyFlag.CERTIFY_OTHER),
|
||||||
|
revocationStateFromSignature(cert.getRevocationSelfSignature()),
|
||||||
|
new HashSet<>(cert.getValidUserIds())));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<OpenPgpFingerprint, List<CertificationSet>> edges = new HashMap<>();
|
||||||
|
Map<OpenPgpFingerprint, List<CertificationSet>> reverseEdges = new HashMap<>();
|
||||||
|
|
||||||
|
return new Network(certSynopsisMap, edges, reverseEdges, referenceTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static RevocationState revocationStateFromSignature(PGPSignature revocation) {
|
||||||
|
if (revocation == null) {
|
||||||
|
return RevocationState.notRevoked();
|
||||||
|
}
|
||||||
|
|
||||||
|
RevocationReason revocationReason = SignatureSubpacketsUtil.getRevocationReason(revocation);
|
||||||
|
if (revocationReason == null) {
|
||||||
|
return RevocationState.hardRevoked();
|
||||||
|
}
|
||||||
|
|
||||||
|
return RevocationAttributes.Reason.isHardRevocation(revocationReason.getRevocationReason()) ?
|
||||||
|
RevocationState.hardRevoked() : RevocationState.softRevoked(revocation.getCreationTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,11 @@ package org.pgpainless.wot;
|
||||||
|
|
||||||
import pgp.cert_d.PGPCertificateDirectory;
|
import pgp.cert_d.PGPCertificateDirectory;
|
||||||
import pgp.cert_d.subkey_lookup.SubkeyLookup;
|
import pgp.cert_d.subkey_lookup.SubkeyLookup;
|
||||||
|
import pgp.certificate_store.exception.BadDataException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import pgp.certificate_store.certificate.Certificate;
|
||||||
|
|
||||||
public class WebOfTrustCertificateStore extends PGPCertificateDirectory {
|
public class WebOfTrustCertificateStore extends PGPCertificateDirectory {
|
||||||
|
|
||||||
|
@ -13,4 +18,9 @@ public class WebOfTrustCertificateStore extends PGPCertificateDirectory {
|
||||||
super(backend, subkeyLookup);
|
super(backend, subkeyLookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Certificate> getAllItems()
|
||||||
|
throws BadDataException, IOException {
|
||||||
|
Iterator<Certificate> trustRootAndCerts = new PrefixedIterator<>(getTrustRootCertificate(), items());
|
||||||
|
return trustRootAndCerts;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.wot;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.pgpainless.wot.testfixtures.TestCertificateStores;
|
||||||
|
import pgp.certificate_store.exception.BadDataException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class WebOfTrustTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithCrossSignedCertificates()
|
||||||
|
throws BadDataException, IOException, InterruptedException {
|
||||||
|
WebOfTrustCertificateStore store = TestCertificateStores.disconnectedGraph();
|
||||||
|
WebOfTrust wot = new WebOfTrust(store);
|
||||||
|
wot.initialize();
|
||||||
|
|
||||||
|
// TODO: Test stuff
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.wot.testfixtures;
|
||||||
|
|
||||||
|
import org.opentest4j.TestAbortedException;
|
||||||
|
import org.pgpainless.certificate_store.KeyMaterialReader;
|
||||||
|
import org.pgpainless.wot.WebOfTrustCertificateStore;
|
||||||
|
import pgp.cert_d.PGPCertificateDirectory;
|
||||||
|
import pgp.cert_d.backend.InMemoryCertificateDirectoryBackend;
|
||||||
|
import pgp.cert_d.subkey_lookup.InMemorySubkeyLookup;
|
||||||
|
import pgp.cert_d.subkey_lookup.SubkeyLookup;
|
||||||
|
import pgp.certificate_store.certificate.KeyMaterial;
|
||||||
|
import pgp.certificate_store.certificate.KeyMaterialMerger;
|
||||||
|
import pgp.certificate_store.certificate.KeyMaterialReaderBackend;
|
||||||
|
import pgp.certificate_store.exception.BadDataException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class TestCertificateStores {
|
||||||
|
|
||||||
|
private static final KeyMaterialMerger merger = new KeyMaterialMerger() {
|
||||||
|
@Override
|
||||||
|
public KeyMaterial merge(KeyMaterial data, KeyMaterial existing) throws IOException {
|
||||||
|
return data; // Always use newer material
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static InputStream requireResource(String resourceName) {
|
||||||
|
InputStream inputStream = TestCertificateStores.class.getClassLoader().getResourceAsStream(resourceName);
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new TestAbortedException("Cannot read resource " + resourceName + ": InputStream is null.");
|
||||||
|
}
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebOfTrustCertificateStore disconnectedGraph()
|
||||||
|
throws BadDataException, IOException, InterruptedException {
|
||||||
|
SubkeyLookup subkeyLookup = new InMemorySubkeyLookup();
|
||||||
|
KeyMaterialReaderBackend readerBackend = new KeyMaterialReader();
|
||||||
|
PGPCertificateDirectory.Backend backend = new InMemoryCertificateDirectoryBackend(readerBackend);
|
||||||
|
WebOfTrustCertificateStore wotStore = new WebOfTrustCertificateStore(backend, subkeyLookup);
|
||||||
|
|
||||||
|
wotStore.insertTrustRoot(getTestVector("cross_signed/foobankCaCert.asc"), merger);
|
||||||
|
wotStore.insert(getTestVector("cross_signed/foobankEmployeeCert.asc"), merger);
|
||||||
|
wotStore.insert(getTestVector("cross_signed/foobankAdminCert.asc"), merger);
|
||||||
|
wotStore.insert(getTestVector("cross_signed/barbankCaCert.asc"), merger);
|
||||||
|
wotStore.insert(getTestVector("cross_signed/barbankEmployeeCert.asc"), merger);
|
||||||
|
|
||||||
|
return wotStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream getTestVector(String testVectorName) {
|
||||||
|
return requireResource("test_vectors/" + testVectorName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,23 +4,12 @@
|
||||||
|
|
||||||
package org.pgpainless.wot.dijkstra.sq;
|
package org.pgpainless.wot.dijkstra.sq;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.sig.RevocationReason;
|
|
||||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
|
||||||
import org.pgpainless.algorithm.KeyFlag;
|
|
||||||
import org.pgpainless.algorithm.RevocationState;
|
|
||||||
import org.pgpainless.key.OpenPgpFingerprint;
|
import org.pgpainless.key.OpenPgpFingerprint;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
|
||||||
import org.pgpainless.key.util.RevocationAttributes;
|
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
|
||||||
|
|
||||||
public class Network {
|
public class Network {
|
||||||
|
|
||||||
|
@ -53,78 +42,6 @@ public class Network {
|
||||||
referenceTime);
|
referenceTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link Network} from a set of certificates.
|
|
||||||
*
|
|
||||||
* @param certificates set of certificates
|
|
||||||
* @param policy evaluation policy
|
|
||||||
* @param optReferenceTime reference time for evaluation
|
|
||||||
* @return network
|
|
||||||
*/
|
|
||||||
public static Network fromCertificates(
|
|
||||||
Iterable<PGPPublicKeyRing> certificates,
|
|
||||||
Policy policy,
|
|
||||||
Optional<ReferenceTime> optReferenceTime) {
|
|
||||||
ReferenceTime referenceTime = optReferenceTime.isPresent() ? optReferenceTime.get() : ReferenceTime.now();
|
|
||||||
List<KeyRingInfo> validCerts = new ArrayList<>();
|
|
||||||
for (PGPPublicKeyRing cert : certificates) {
|
|
||||||
KeyRingInfo info = new KeyRingInfo(cert, policy, referenceTime.getTimestamp());
|
|
||||||
if (info.getValidUserIds().isEmpty()) {
|
|
||||||
// Ignore invalid cert
|
|
||||||
} else {
|
|
||||||
validCerts.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fromValidCertificates(
|
|
||||||
validCerts,
|
|
||||||
referenceTime
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link Network} from a set of validated certificates.
|
|
||||||
*
|
|
||||||
* @param validatedCertificates set of validated certificates
|
|
||||||
* @param referenceTime reference time
|
|
||||||
* @return network
|
|
||||||
*/
|
|
||||||
public static Network fromValidCertificates(
|
|
||||||
Iterable<KeyRingInfo> validatedCertificates,
|
|
||||||
ReferenceTime referenceTime) {
|
|
||||||
|
|
||||||
Map<OpenPgpFingerprint, KeyRingInfo> byFingerprint = new HashMap<>();
|
|
||||||
Map<Long, List<KeyRingInfo>> byKeyId = new HashMap<>();
|
|
||||||
|
|
||||||
Map<OpenPgpFingerprint, CertSynopsis> certSynopsisMap = new HashMap<>();
|
|
||||||
|
|
||||||
for (KeyRingInfo cert : validatedCertificates) {
|
|
||||||
// noinspection Java8MapApi
|
|
||||||
if (byFingerprint.get(cert.getFingerprint()) == null) {
|
|
||||||
byFingerprint.put(cert.getFingerprint(), cert);
|
|
||||||
}
|
|
||||||
List<KeyRingInfo> byKeyIdEntry = byKeyId.get(cert.getKeyId());
|
|
||||||
|
|
||||||
// noinspection Java8MapApi
|
|
||||||
if (byKeyIdEntry == null) {
|
|
||||||
byKeyIdEntry = new ArrayList<>();
|
|
||||||
byKeyId.put(cert.getKeyId(), byKeyIdEntry);
|
|
||||||
}
|
|
||||||
byKeyIdEntry.add(cert);
|
|
||||||
|
|
||||||
certSynopsisMap.put(cert.getFingerprint(),
|
|
||||||
new CertSynopsis(cert.getFingerprint(),
|
|
||||||
cert.getExpirationDateForUse(KeyFlag.CERTIFY_OTHER),
|
|
||||||
revocationStateFromSignature(cert.getRevocationSelfSignature()),
|
|
||||||
new HashSet<>(cert.getValidUserIds())));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<OpenPgpFingerprint, List<CertificationSet>> edges = new HashMap<>();
|
|
||||||
Map<OpenPgpFingerprint, List<CertificationSet>> reverseEdges = new HashMap<>();
|
|
||||||
|
|
||||||
return new Network(certSynopsisMap, edges, reverseEdges, referenceTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<OpenPgpFingerprint, CertSynopsis> getNodes() {
|
public Map<OpenPgpFingerprint, CertSynopsis> getNodes() {
|
||||||
return new HashMap<>(nodes);
|
return new HashMap<>(nodes);
|
||||||
}
|
}
|
||||||
|
@ -141,17 +58,4 @@ public class Network {
|
||||||
return referenceTime;
|
return referenceTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RevocationState revocationStateFromSignature(PGPSignature revocation) {
|
|
||||||
if (revocation == null) {
|
|
||||||
return RevocationState.notRevoked();
|
|
||||||
}
|
|
||||||
|
|
||||||
RevocationReason revocationReason = SignatureSubpacketsUtil.getRevocationReason(revocation);
|
|
||||||
if (revocationReason == null) {
|
|
||||||
return RevocationState.hardRevoked();
|
|
||||||
}
|
|
||||||
|
|
||||||
return RevocationAttributes.Reason.isHardRevocation(revocationReason.getRevocationReason()) ?
|
|
||||||
RevocationState.hardRevoked() : RevocationState.softRevoked(revocation.getCreationTime());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue