mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-14 20:59:39 +02:00
Integrate SubkeyLookup with CertificateStore
This commit is contained in:
parent
7b66954199
commit
8a7bbdbf03
8 changed files with 240 additions and 160 deletions
|
@ -6,6 +6,7 @@ package pgp.certificate_store;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class Certificate {
|
||||
/**
|
||||
|
@ -30,4 +31,6 @@ public abstract class Certificate {
|
|||
* @return tag
|
||||
*/
|
||||
public abstract String getTag() throws IOException;
|
||||
|
||||
public abstract Set<Long> getSubkeyIds() throws IOException;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package pgp.certificate_store;
|
||||
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import pgp.certificate_store.exception.BadNameException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Certificate storage definition.
|
||||
* This interface defines methods to insert and retrieve {@link Certificate Certificates} to and from a store.
|
||||
*
|
||||
* {@link Certificate Certificates} are hereby identified by identifiers. An identifier can either be a fingerprint
|
||||
* or a special name. Special names are implementation-defined identifiers for certificates.
|
||||
*
|
||||
* Fingerprints are expected to be hexadecimal lowercase character sequences.
|
||||
*/
|
||||
public interface CertificateDirectory {
|
||||
|
||||
/**
|
||||
* Return the certificate that matches the given identifier.
|
||||
* If no matching certificate can be found, return null.
|
||||
*
|
||||
* @param identifier identifier for a certificate.
|
||||
* @return certificate or null
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate getCertificate(String identifier)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
/**
|
||||
* Return the certificate that matches the given identifier, but only iff it changed since the last invocation.
|
||||
* To compare the certificate against its last returned result, the given tag is used.
|
||||
* If the tag of the currently found certificate matches the given argument, return null.
|
||||
*
|
||||
* @param identifier identifier for a certificate
|
||||
* @param tag tag to compare freshness
|
||||
* @return changed certificate or null
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate getCertificateIfChanged(String identifier, String tag)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* If an instance of the certificate is already present in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will block until a write-lock on the store can be acquired. If you cannot afford blocking,
|
||||
* consider to use {@link #tryInsertCertificate(InputStream, MergeCallback)} instead.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
* @throws InterruptedException in case the inserting thread gets interrupted
|
||||
*/
|
||||
Certificate insertCertificate(InputStream data, MergeCallback merge)
|
||||
throws IOException, InterruptedException, BadDataException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* If an instance of the certificate is already present in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will not block. Instead, if the store is already write-locked, this method will simply return null
|
||||
* without any writing.
|
||||
* However, if the write-lock is available, this method will acquire the lock, write to the store, release the lock
|
||||
* and return the written certificate.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate or null if the store cannot be locked
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate tryInsertCertificate(InputStream data, MergeCallback merge)
|
||||
throws IOException, BadDataException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* The certificate will be stored under the given special name instead of its fingerprint.
|
||||
*
|
||||
* If an instance of the certificate is already present under the special name in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will block until a write-lock on the store can be acquired. If you cannot afford blocking,
|
||||
* consider to use {@link #tryInsertCertificateBySpecialName(String, InputStream, MergeCallback)} instead.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate or null if the store cannot be locked
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate insertCertificateBySpecialName(String specialName, InputStream data, MergeCallback merge)
|
||||
throws IOException, InterruptedException, BadDataException, BadNameException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* The certificate will be stored under the given special name instead of its fingerprint.
|
||||
*
|
||||
* If an instance of the certificate is already present under the special name in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will not block. Instead, if the store is already write-locked, this method will simply return null
|
||||
* without any writing.
|
||||
* However, if the write-lock is available, this method will acquire the lock, write to the store, release the lock
|
||||
* and return the written certificate.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate or null if the store cannot be locked
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate tryInsertCertificateBySpecialName(String specialName, InputStream data, MergeCallback merge)
|
||||
throws IOException, BadDataException, BadNameException;
|
||||
|
||||
/**
|
||||
* Return an {@link Iterator} containing all certificates in the store.
|
||||
* The iterator will contain both certificates addressed by special names and by fingerprints.
|
||||
*
|
||||
* @return certificates
|
||||
*/
|
||||
Iterator<Certificate> getCertificates();
|
||||
|
||||
/**
|
||||
* Return an {@link Iterator} containing all certificate fingerprints from the store.
|
||||
* Note that this only includes the fingerprints of certificate primary keys, not those of subkeys.
|
||||
*
|
||||
* @return fingerprints
|
||||
*/
|
||||
Iterator<String> getFingerprints();
|
||||
}
|
|
@ -4,144 +4,6 @@
|
|||
|
||||
package pgp.certificate_store;
|
||||
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import pgp.certificate_store.exception.BadNameException;
|
||||
public interface CertificateStore extends CertificateDirectory, SubkeyLookup {
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Certificate storage definition.
|
||||
* This interface defines methods to insert and retrieve {@link Certificate Certificates} to and from a store.
|
||||
*
|
||||
* {@link Certificate Certificates} are hereby identified by identifiers. An identifier can either be a fingerprint
|
||||
* or a special name. Special names are implementation-defined identifiers for certificates.
|
||||
*
|
||||
* Fingerprints are expected to be hexadecimal lowercase character sequences.
|
||||
*/
|
||||
public interface CertificateStore {
|
||||
|
||||
/**
|
||||
* Return the certificate that matches the given identifier.
|
||||
* If no matching certificate can be found, return null.
|
||||
*
|
||||
* @param identifier identifier for a certificate.
|
||||
* @return certificate or null
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate getCertificate(String identifier)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
/**
|
||||
* Return the certificate that matches the given identifier, but only iff it changed since the last invocation.
|
||||
* To compare the certificate against its last returned result, the given tag is used.
|
||||
* If the tag of the currently found certificate matches the given argument, return null.
|
||||
*
|
||||
* @param identifier identifier for a certificate
|
||||
* @param tag tag to compare freshness
|
||||
* @return changed certificate or null
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate getCertificateIfChanged(String identifier, String tag)
|
||||
throws IOException, BadNameException, BadDataException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* If an instance of the certificate is already present in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will block until a write-lock on the store can be acquired. If you cannot afford blocking,
|
||||
* consider to use {@link #tryInsertCertificate(InputStream, MergeCallback)} instead.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
* @throws InterruptedException in case the inserting thread gets interrupted
|
||||
*/
|
||||
Certificate insertCertificate(InputStream data, MergeCallback merge)
|
||||
throws IOException, InterruptedException, BadDataException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* If an instance of the certificate is already present in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will not block. Instead, if the store is already write-locked, this method will simply return null
|
||||
* without any writing.
|
||||
* However, if the write-lock is available, this method will acquire the lock, write to the store, release the lock
|
||||
* and return the written certificate.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate or null if the store cannot be locked
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate tryInsertCertificate(InputStream data, MergeCallback merge)
|
||||
throws IOException, BadDataException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* The certificate will be stored under the given special name instead of its fingerprint.
|
||||
*
|
||||
* If an instance of the certificate is already present under the special name in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will block until a write-lock on the store can be acquired. If you cannot afford blocking,
|
||||
* consider to use {@link #tryInsertCertificateBySpecialName(String, InputStream, MergeCallback)} instead.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate or null if the store cannot be locked
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate insertCertificateBySpecialName(String specialName, InputStream data, MergeCallback merge)
|
||||
throws IOException, InterruptedException, BadDataException, BadNameException;
|
||||
|
||||
/**
|
||||
* Insert a certificate into the store.
|
||||
* The certificate will be stored under the given special name instead of its fingerprint.
|
||||
*
|
||||
* If an instance of the certificate is already present under the special name in the store, the given {@link MergeCallback} will be
|
||||
* used to merge both the existing and the new instance of the {@link Certificate}. The resulting merged certificate
|
||||
* will be stored in the store and returned.
|
||||
*
|
||||
* This method will not block. Instead, if the store is already write-locked, this method will simply return null
|
||||
* without any writing.
|
||||
* However, if the write-lock is available, this method will acquire the lock, write to the store, release the lock
|
||||
* and return the written certificate.
|
||||
*
|
||||
* @param data input stream containing the new certificate instance
|
||||
* @param merge callback for merging with an existing certificate instance
|
||||
* @return merged certificate or null if the store cannot be locked
|
||||
*
|
||||
* @throws IOException in case of an IO-error
|
||||
*/
|
||||
Certificate tryInsertCertificateBySpecialName(String specialName, InputStream data, MergeCallback merge)
|
||||
throws IOException, BadDataException, BadNameException;
|
||||
|
||||
/**
|
||||
* Return an {@link Iterator} containing all certificates in the store.
|
||||
* The iterator will contain both certificates addressed by special names and by fingerprints.
|
||||
*
|
||||
* @return certificates
|
||||
*/
|
||||
Iterator<Certificate> getCertificates();
|
||||
|
||||
/**
|
||||
* Return an {@link Iterator} containing all certificate fingerprints from the store.
|
||||
* Note that this only includes the fingerprints of certificate primary keys, not those of subkeys.
|
||||
*
|
||||
* @return fingerprints
|
||||
*/
|
||||
Iterator<String> getFingerprints();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ dependencies {
|
|||
testImplementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||
|
||||
implementation project(":pgpainless-cert-d")
|
||||
implementation project(":pgp-cert-d-java-jdbc-sqlite-lookup")
|
||||
|
||||
// picocli for cli
|
||||
implementation "info.picocli:picocli:4.6.2"
|
||||
|
|
|
@ -6,14 +6,18 @@ package pgp.cert_d.cli;
|
|||
|
||||
import org.pgpainless.certificate_store.CertificateReader;
|
||||
import org.pgpainless.certificate_store.SharedPGPCertificateDirectoryAdapter;
|
||||
import pgp.cert_d.BaseDirectoryProvider;
|
||||
import pgp.cert_d.SharedPGPCertificateDirectoryImpl;
|
||||
import pgp.cert_d.cli.commands.Get;
|
||||
import pgp.cert_d.cli.commands.Import;
|
||||
import pgp.cert_d.jdbc.sqlite.SqliteSubkeyLookup;
|
||||
import pgp.certificate_store.SubkeyLookup;
|
||||
import pgp.certificate_store.exception.NotAStoreException;
|
||||
import pgp.certificate_store.CertificateStore;
|
||||
import pgp.certificate_store.CertificateDirectory;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@CommandLine.Command(
|
||||
subcommands = {
|
||||
|
@ -26,28 +30,30 @@ public class PGPCertDCli {
|
|||
@CommandLine.Option(names = "--base-directory", paramLabel = "DIRECTORY", description = "Overwrite the default certificate directory")
|
||||
File baseDirectory;
|
||||
|
||||
private static CertificateStore certificateStore;
|
||||
private static CertificateDirectory certificateDirectory;
|
||||
|
||||
private int executionStrategy(CommandLine.ParseResult parseResult) {
|
||||
try {
|
||||
initStore();
|
||||
} catch (NotAStoreException e) {
|
||||
} catch (NotAStoreException | SQLException e) {
|
||||
return -1;
|
||||
}
|
||||
return new CommandLine.RunLast().execute(parseResult);
|
||||
}
|
||||
|
||||
private void initStore() throws NotAStoreException {
|
||||
private void initStore() throws NotAStoreException, SQLException {
|
||||
SharedPGPCertificateDirectoryImpl certificateDirectory;
|
||||
if (baseDirectory != null) {
|
||||
certificateDirectory = new SharedPGPCertificateDirectoryImpl(
|
||||
baseDirectory,
|
||||
new CertificateReader());
|
||||
} else {
|
||||
certificateDirectory = new SharedPGPCertificateDirectoryImpl(
|
||||
new CertificateReader());
|
||||
SubkeyLookup subkeyLookup;
|
||||
if (baseDirectory == null) {
|
||||
baseDirectory = BaseDirectoryProvider.getDefaultBaseDir();
|
||||
}
|
||||
certificateStore = new SharedPGPCertificateDirectoryAdapter(certificateDirectory);
|
||||
|
||||
certificateDirectory = new SharedPGPCertificateDirectoryImpl(
|
||||
baseDirectory,
|
||||
new CertificateReader());
|
||||
subkeyLookup = SqliteSubkeyLookup.forDatabaseFile(new File(baseDirectory, "_pgpainless_subkey_map.db"));
|
||||
|
||||
PGPCertDCli.certificateDirectory = new SharedPGPCertificateDirectoryAdapter(certificateDirectory, subkeyLookup);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -57,7 +63,7 @@ public class PGPCertDCli {
|
|||
.execute(args);
|
||||
}
|
||||
|
||||
public static CertificateStore getCertificateDirectory() {
|
||||
return certificateStore;
|
||||
public static CertificateDirectory getCertificateDirectory() {
|
||||
return certificateDirectory;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
package org.pgpainless.certificate_store;
|
||||
|
||||
import org.bouncycastle.openpgp.PGPPublicKey;
|
||||
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
import org.pgpainless.key.OpenPgpFingerprint;
|
||||
|
@ -14,6 +15,9 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
public class CertificateFactory {
|
||||
|
||||
|
@ -40,6 +44,16 @@ public class CertificateFactory {
|
|||
digest.update(publicKeyRing.getEncoded());
|
||||
return Base64.toBase64String(digest.digest());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> getSubkeyIds() throws IOException {
|
||||
Set<Long> keyIds = new HashSet<>();
|
||||
Iterator<PGPPublicKey> keys = publicKeyRing.getPublicKeys();
|
||||
while (keys.hasNext()) {
|
||||
keyIds.add(keys.next().getKeyID());
|
||||
}
|
||||
return keyIds;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,31 +7,36 @@ package org.pgpainless.certificate_store;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import pgp.cert_d.SharedPGPCertificateDirectory;
|
||||
import pgp.cert_d.SpecialNames;
|
||||
import pgp.certificate_store.Certificate;
|
||||
import pgp.certificate_store.CertificateDirectory;
|
||||
import pgp.certificate_store.CertificateStore;
|
||||
import pgp.certificate_store.MergeCallback;
|
||||
import pgp.certificate_store.SubkeyLookup;
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import pgp.certificate_store.exception.BadNameException;
|
||||
|
||||
/**
|
||||
* Adapter class used to adapt the {@link SharedPGPCertificateDirectory} for use with
|
||||
* {@link CertificateStore}.
|
||||
* {@link CertificateDirectory}.
|
||||
*/
|
||||
public class SharedPGPCertificateDirectoryAdapter
|
||||
implements CertificateStore {
|
||||
|
||||
private final SharedPGPCertificateDirectory directory;
|
||||
private final SubkeyLookup subkeyLookup;
|
||||
|
||||
/**
|
||||
* Create an adapter to use {@link SharedPGPCertificateDirectory} objects as {@link CertificateStore CertificateStores}.
|
||||
* Create an adapter to use {@link SharedPGPCertificateDirectory} objects as {@link CertificateDirectory CertificateStores}.
|
||||
*
|
||||
* @param directory directory instance
|
||||
*/
|
||||
public SharedPGPCertificateDirectoryAdapter(SharedPGPCertificateDirectory directory) {
|
||||
public SharedPGPCertificateDirectoryAdapter(SharedPGPCertificateDirectory directory, SubkeyLookup subkeyLookup) {
|
||||
this.directory = directory;
|
||||
this.subkeyLookup = subkeyLookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,13 +66,17 @@ public class SharedPGPCertificateDirectoryAdapter
|
|||
@Override
|
||||
public Certificate insertCertificate(InputStream data, MergeCallback merge)
|
||||
throws IOException, InterruptedException, BadDataException {
|
||||
return directory.insert(data, merge);
|
||||
Certificate certificate = directory.insert(data, merge);
|
||||
storeIdentifierForSubkeys(certificate);
|
||||
return certificate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Certificate tryInsertCertificate(InputStream data, MergeCallback merge)
|
||||
throws IOException, BadDataException {
|
||||
return directory.tryInsert(data, merge);
|
||||
Certificate certificate = directory.tryInsert(data, merge);
|
||||
storeIdentifierForSubkeys(certificate);
|
||||
return certificate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,4 +100,24 @@ public class SharedPGPCertificateDirectoryAdapter
|
|||
public Iterator<String> getFingerprints() {
|
||||
return directory.fingerprints();
|
||||
}
|
||||
|
||||
private void storeIdentifierForSubkeys(Certificate certificate) throws IOException {
|
||||
if (certificate == null) {
|
||||
return;
|
||||
}
|
||||
String fingerprint = certificate.getFingerprint();
|
||||
for (Long subkeyId : certificate.getSubkeyIds()) {
|
||||
storeIdentifierForSubkeyId(subkeyId, fingerprint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getIdentifiersForSubkeyId(long subkeyId) throws IOException {
|
||||
return subkeyLookup.getIdentifiersForSubkeyId(subkeyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeIdentifierForSubkeyId(long subkeyId, String identifier) throws IOException {
|
||||
subkeyLookup.storeIdentifierForSubkeyId(subkeyId, identifier);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
@ -26,17 +28,21 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.pgpainless.certificate_store.CertificateReader;
|
||||
import org.pgpainless.certificate_store.SharedPGPCertificateDirectoryAdapter;
|
||||
import pgp.cert_d.InMemorySubkeyLookup;
|
||||
import pgp.cert_d.SharedPGPCertificateDirectoryImpl;
|
||||
import pgp.certificate_store.CertificateStore;
|
||||
import pgp.certificate_store.exception.BadDataException;
|
||||
import pgp.certificate_store.exception.BadNameException;
|
||||
import pgp.certificate_store.exception.NotAStoreException;
|
||||
import pgp.certificate_store.Certificate;
|
||||
import pgp.certificate_store.CertificateStore;
|
||||
|
||||
public class SharedPGPCertificateDirectoryAdapterTest {
|
||||
|
||||
private static final String testCertificate = "98330462069cc616092b06010401da470f010107400db5906b09f701ab1f7f96087eedab6ba44c02fcbd2470137cfeacac5a2d032db405416c696365888f0413160a0041050262069cc609906f054e826378552516a104505b134a7e62f0f154ec3d036f054e8263785525029e01029b01059602030100048b09080705950a09080b0299010000a12600fd117925c0f2192ef5b2a44e3d3038e2a7ce5ba0343fc2dfb661a3a46d1276fb380100bf2872e7e36b63f61ae3556464c4a04344e7d36e0d7313e623effb0290ce0b0fb8380462069cc6120a2b06010401975501050101074034ffd523242385fe92034a5e326a82f4edff614516cc1028ca91fb653557f25b0301080788750418160a001d050262069cc6029e01029b0c059602030100048b09080705950a09080b000a09106f054e8263785525391400ff4eb85df8ddfc15e94c9cf28bc0aa9d0426b571ca64c5421be5889d5410d8632f00fd1ac5e9aed683e711282489d8980222d2ceff15c5ce0499fcb36716d850749406b8330462069cc616092b06010401da470f0101074058f296fb7ce456039856144db677f14018963a8bfd281c84aaeebe7e14df8f1c88d50418160a007d050262069cc6029e01029b02059602030100048b09080705950a09080b5f200419160a0006050262069cc6000a09108119c86e0a4c6dc73a7600ff5e25427da84d824cc3f8890bc6bd037f423f610006e1249b1aad3d7f70ac47a100fc08e67a6a945c1feec301df9dc27e7ea4e61d107d0720e814eea1dc4f1da20a08000a09106f054e8263785525359700ff4ce78cf267c261468322de906118d4f003ceefa72fa3b86119e26f99be3727fc00fe3895207c4aac814549f0189d2f494f5b1fcee7f6da344e63a0c32743b216b406";
|
||||
private static final String testCertFingerprint = "505b134a7e62f0f154ec3d036f054e8263785525";
|
||||
private static final long testCertificateSubkey1 = 7999886635015099685L;
|
||||
private static final long testCertificateSubkey2 = -5375724347241457298L;
|
||||
private static final long testCertificateSubkey3 = -9144057193454342713L;
|
||||
|
||||
private SharedPGPCertificateDirectoryAdapter adapter;
|
||||
private CertificateStore store;
|
||||
|
@ -44,7 +50,8 @@ public class SharedPGPCertificateDirectoryAdapterTest {
|
|||
@BeforeEach
|
||||
public void setupInstance() throws IOException, NotAStoreException {
|
||||
adapter = new SharedPGPCertificateDirectoryAdapter(
|
||||
new SharedPGPCertificateDirectoryImpl(tempDir(), new CertificateReader()));
|
||||
new SharedPGPCertificateDirectoryImpl(tempDir(), new CertificateReader()),
|
||||
new InMemorySubkeyLookup());
|
||||
store = adapter;
|
||||
}
|
||||
|
||||
|
@ -73,6 +80,12 @@ public class SharedPGPCertificateDirectoryAdapterTest {
|
|||
Certificate certificate = store.insertCertificate(byteIn, (data, existing) -> data);
|
||||
|
||||
assertEquals(fingerprint, certificate.getFingerprint());
|
||||
Set<Long> expectedSubkeys = new HashSet<>(Arrays.asList(testCertificateSubkey1, testCertificateSubkey2, testCertificateSubkey3));
|
||||
Set<Long> subkeys = certificate.getSubkeyIds();
|
||||
assertEquals(expectedSubkeys, subkeys);
|
||||
for (long subkey : subkeys) {
|
||||
assertEquals(Collections.singleton(fingerprint), store.getIdentifiersForSubkeyId(subkey));
|
||||
}
|
||||
|
||||
Certificate retrieved = store.getCertificate(fingerprint);
|
||||
assertNotNull(retrieved);
|
||||
|
@ -92,6 +105,11 @@ public class SharedPGPCertificateDirectoryAdapterTest {
|
|||
Certificate certificate = store.tryInsertCertificate(byteIn, (data, existing) -> data);
|
||||
|
||||
assertEquals(fingerprint, certificate.getFingerprint());
|
||||
Set<Long> subkeys = certificate.getSubkeyIds();
|
||||
assertEquals(3, subkeys.size());
|
||||
for (long subkey : subkeys) {
|
||||
assertEquals(Collections.singleton(fingerprint), store.getIdentifiersForSubkeyId(subkey));
|
||||
}
|
||||
|
||||
Certificate retrieved = store.getCertificate(fingerprint);
|
||||
assertNotNull(retrieved);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue